Introduction
Testify extends Go standard testing with assertions that make tests more readable and mocks that make testing easier. Instead of writing verbose if-else checks with t.Errorf(), you write assert.Equal(t, expected, actual) — clear, concise, and with helpful error messages.
With over 26,000 GitHub stars, Testify is used in virtually every Go project that goes beyond trivial testing. Its assert, require, mock, and suite packages cover the full spectrum of testing needs.
What Testify Does
Testify provides three main packages: assert (soft assertions that continue on failure), require (hard assertions that stop the test), and mock (interface mocking with expectations). The suite package adds setup/teardown lifecycle methods similar to JUnit or pytest fixtures.
Architecture Overview
[Testify Packages]
|
+-------+-------+-------+
| | | |
[assert] [require] [mock]
Soft Hard Interface
assertions assertions mocking
(continue (stop on with
on fail) fail) expectations
|
[suite]
Test suites with
SetupTest()
TearDownTest()
SetupSuite()
TearDownSuite()Self-Hosting & Configuration
// Mocking example
type UserRepository interface {
GetUser(id int) (*User, error)
SaveUser(user *User) error
}
// Generated or hand-written mock
type MockUserRepo struct {
mock.Mock
}
func (m *MockUserRepo) GetUser(id int) (*User, error) {
args := m.Called(id)
if args.Get(0) == nil {
return nil, args.Error(1)
}
return args.Get(0).(*User), args.Error(1)
}
func (m *MockUserRepo) SaveUser(user *User) error {
return m.Called(user).Error(0)
}
// Test with mock
func TestGetUserService(t *testing.T) {
mockRepo := new(MockUserRepo)
mockRepo.On("GetUser", 1).Return(&User{ID: 1, Name: "Alice"}, nil)
mockRepo.On("GetUser", 999).Return(nil, errors.New("not found"))
service := NewUserService(mockRepo)
user, err := service.GetUser(1)
assert.NoError(t, err)
assert.Equal(t, "Alice", user.Name)
_, err = service.GetUser(999)
assert.Error(t, err)
mockRepo.AssertExpectations(t)
}// Test suite with setup/teardown
type UserServiceSuite struct {
suite.Suite
db *sql.DB
service *UserService
}
func (s *UserServiceSuite) SetupSuite() {
s.db, _ = sql.Open("postgres", testDSN)
s.service = NewUserService(s.db)
}
func (s *UserServiceSuite) TearDownSuite() {
s.db.Close()
}
func (s *UserServiceSuite) SetupTest() {
s.db.Exec("DELETE FROM users")
}
func (s *UserServiceSuite) TestCreateUser() {
user, err := s.service.Create("Alice")
s.NoError(err)
s.Equal("Alice", user.Name)
}
func TestUserServiceSuite(t *testing.T) {
suite.Run(t, new(UserServiceSuite))
}Key Features
- assert — 70+ assertion functions (Equal, Contains, Len, Error, etc.)
- require — same assertions but stops test on failure
- mock — interface mocking with expected calls and return values
- suite — test suites with SetupTest/TearDownTest lifecycle
- Helpful Messages — clear diff output on assertion failures
- Custom Messages — add context to any assertion
- HTTP Testing — assert on HTTP responses (status, body, headers)
- Standard Compatible — works with go test, no special runner needed
Comparison with Similar Tools
| Feature | Testify | gomock | gocheck | is | standard lib |
|---|---|---|---|---|---|
| Assertions | 70+ | No | Yes | Minimal | Manual |
| Mocking | Built-in | Code-gen (mockgen) | No | No | Manual |
| Suites | Yes | No | Yes | No | No |
| Error Messages | Excellent | Good | Good | Good | Manual |
| Code Gen | No | Yes (mockgen) | No | No | No |
| Popularity | Dominant | Popular | Declining | Growing | Built-in |
FAQ
Q: assert vs require — when to use which? A: Use require for preconditions (if this fails, nothing else makes sense). Use assert for verifications (check multiple things even if one fails). Example: require.NoError for setup, assert.Equal for validations.
Q: Should I use testify mocks or gomock? A: Testify mocks for hand-written mocks with flexible expectations. gomock with mockgen for auto-generated mocks from interfaces. Testify is simpler; gomock is more rigorous.
Q: Is testify considered idiomatic Go? A: Purists prefer the standard library, but testify is the most pragmatic choice. The Go team does not officially endorse testing libraries, but testify is the community standard.
Q: How do I generate mocks automatically? A: Use mockery (github.com/vektra/mockery) to auto-generate testify mocks from interfaces: "mockery --all" generates mock files for all interfaces in your project.
Sources
- GitHub: https://github.com/stretchr/testify
- Documentation: https://pkg.go.dev/github.com/stretchr/testify
- Created by Mat Ryer and Tyler Bunnell
- License: MIT