
Golang Stretchr Testify
- 33.5k installs
- 2.8k repo stars
- Updated July 27, 2026
- samber/cc-skills-golang
golang-stretchr-testify is a Go testing skill that teaches assert vs require patterns and testify best practices.
About
Go testing skill focused on stretchr/testify library usage. Covers assert vs require patterns for test structure, precondition handling, and verification strategies. Helps developers write maintainable and clear test code.
- assert vs require patterns for test flow control
- Precondition vs verification assertion strategies
- testify library best practices
Golang Stretchr Testify by the numbers
- 33,494 all-time installs (skills.sh)
- +461 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #16 of 2,184 Testing & QA skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
golang-stretchr-testify capabilities & compatibility
- Capabilities
- testing · unit testing
- Use cases
- testing
What golang-stretchr-testify says it does
Tests whether the model uses require for preconditions and assert for verifications
npx skills add https://github.com/samber/cc-skills-golang --skill golang-stretchr-testifyAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 33.5k |
|---|---|
| repo stars | ★ 2.8k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | samber/cc-skills-golang ↗ |
When should Go tests use testify require vs assert?
Go developers need structured testing patterns with testify library to write clear test assertions and handle test preconditions correctly.
Who is it for?
Go developers writing unit tests with testify
Skip if: Projects using only stdlib testing, testify suites without assert/require, or teams that do not run AI-generated Go tests.
When should I use this skill?
Writing Go unit tests, structuring test assertions, using testify library
What you get
_test.go files with require preconditions, assert verifications, and eval-passing testify patterns.
- testify _test.go files
- require/assert split pattern
By the numbers
- Includes assert-vs-require-precondition eval with 3 field assertions after parse
- JSON config eval checks Port, Host, and Debug values
Files
Persona: You are a Go engineer who treats tests as executable specifications. You write tests to constrain behavior and make failures self-explanatory — not to hit coverage targets.
Modes:
- Write mode — adding new tests or mocks to a codebase.
- Review mode — auditing existing test code for testify misuse.
stretchr/testify
testify complements Go's testing package with readable assertions, mocks, and suites. It does not replace testing — always use *testing.T as the entry point.
This skill is not exhaustive. Please refer to library documentation and code examples for more information. Context7 can help as a discoverability platform. For Go package docs, versions, symbols, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill.
assert vs require
Both offer identical assertions. The difference is failure behavior:
- assert: records failure, continues — see all failures at once
- require: calls
t.FailNow()— use for preconditions where continuing would panic or mislead
Use assert.New(t) / require.New(t) for readability. Name them is and must:
func TestParseConfig(t *testing.T) {
is := assert.New(t)
must := require.New(t)
cfg, err := ParseConfig("testdata/valid.yaml")
must.NoError(err) // stop if parsing fails — cfg would be nil
must.NotNil(cfg)
is.Equal("production", cfg.Environment)
is.Equal(8080, cfg.Port)
is.True(cfg.TLS.Enabled)
}Rule: require for preconditions (setup, error checks), assert for verifications. Never mix randomly.
Core Assertions
is := assert.New(t)
// Equality
is.Equal(expected, actual) // DeepEqual + exact type
is.NotEqual(unexpected, actual)
is.EqualValues(expected, actual) // converts to common type first
is.EqualExportedValues(expected, actual)
// Nil / Bool / Emptiness
is.Nil(obj) is.NotNil(obj)
is.True(cond) is.False(cond)
is.Empty(collection) is.NotEmpty(collection)
is.Len(collection, n)
// Contains (strings, slices, map keys)
is.Contains("hello world", "world")
is.Contains([]int{1, 2, 3}, 2)
is.Contains(map[string]int{"a": 1}, "a")
// Comparison
is.Greater(actual, threshold) is.Less(actual, ceiling)
is.Positive(val) is.Negative(val)
is.Zero(val)
// Errors
is.Error(err) is.NoError(err)
is.ErrorIs(err, ErrNotFound) // walks error chain
is.ErrorAs(err, &target)
is.ErrorContains(err, "not found")
// Type
is.IsType(&User{}, obj)
is.Implements((*io.Reader)(nil), obj)Argument order: always (expected, actual) — swapping produces confusing diff output.
Advanced Assertions
is.ElementsMatch([]string{"b", "a", "c"}, result) // unordered comparison
is.InDelta(3.14, computedPi, 0.01) // float tolerance
is.JSONEq(`{"name":"alice"}`, `{"name": "alice"}`) // ignores whitespace/key order
is.WithinDuration(expected, actual, 5*time.Second)
is.Regexp(`^user-[a-f0-9]+$`, userID)
// Async polling
is.Eventually(func() bool {
status, _ := client.GetJobStatus(jobID)
return status == "completed"
}, 5*time.Second, 100*time.Millisecond)
// Async polling with rich assertions
is.EventuallyWithT(func(c *assert.CollectT) {
resp, err := client.GetOrder(orderID)
assert.NoError(c, err)
assert.Equal(c, "shipped", resp.Status)
}, 10*time.Second, 500*time.Millisecond)testify/mock
Mock interfaces to isolate the unit under test. Embed mock.Mock, implement methods with m.Called(), always verify with AssertExpectations(t).
Key matchers: mock.Anything, mock.AnythingOfType("T"), mock.MatchedBy(func). Call modifiers: .Once(), .Times(n), .Maybe(), .Run(func).
For defining mocks, argument matchers, call modifiers, return sequences, and verification, see Mock reference.
testify/suite
Suites group related tests with shared setup/teardown.
Lifecycle
SetupSuite() → once before all tests
SetupTest() → before each test
TestXxx()
TearDownTest() → after each test
TearDownSuite() → once after all testsExample
type TokenServiceSuite struct {
suite.Suite
store *MockTokenStore
service *TokenService
}
func (s *TokenServiceSuite) SetupTest() {
s.store = new(MockTokenStore)
s.service = NewTokenService(s.store)
}
func (s *TokenServiceSuite) TestGenerate_ReturnsValidToken() {
s.store.On("Save", mock.Anything, mock.Anything).Return(nil)
token, err := s.service.Generate("user-42")
s.NoError(err)
s.NotEmpty(token)
s.store.AssertExpectations(s.T())
}
// Required launcher
func TestTokenServiceSuite(t *testing.T) {
suite.Run(t, new(TokenServiceSuite))
}Suite methods like s.Equal() behave like assert. For require: s.Require().NotNil(obj).
Common Mistakes
- Forgetting `AssertExpectations(t)` — mock expectations silently pass without verification
- `is.Equal(ErrNotFound, err)` — fails on wrapped errors. Use
is.ErrorIsto walk the chain - Swapped argument order — testify assumes
(expected, actual). Swapping produces backwards diffs - `assert` for guards — test continues after failure and panics on nil dereference. Use
require - Missing `suite.Run()` — without the launcher function, zero tests execute silently
- Comparing pointers —
is.Equal(ptr1, ptr2)compares addresses. Dereference or useEqualExportedValues
Linters
Use testifylint to catch wrong argument order, assert/require misuse, and more. See samber/cc-skills-golang@golang-lint skill.
Cross-References
- → See
samber/cc-skills-golang@golang-testingskill for general test patterns, table-driven tests, and CI - → See
samber/cc-skills-golang@golang-lintskill for testifylint configuration
[
{
"id": 1,
"name": "assert-vs-require-precondition",
"description": "Tests whether the model uses require for preconditions and assert for verifications, not mixing them randomly",
"prompt": "Write a Go test using testify that parses a JSON config file, checks it has no error, verifies the config is not nil, then checks that config.Port equals 8080, config.Host equals 'localhost', and config.Debug is false.",
"trap": "Model may use assert for the error check and nil check (preconditions), which would cause a nil pointer panic on subsequent assertions if parsing fails",
"assertions": [
{"id": "1.1", "text": "Uses require (not assert) for the NoError check on parsing"},
{"id": "1.2", "text": "Uses require (not assert) for the NotNil check on config"},
{"id": "1.3", "text": "Uses assert for the subsequent value checks (Port, Host, Debug)"},
{"id": "1.4", "text": "Does NOT use require for all assertions indiscriminately"},
{"id": "1.5", "text": "Argument order is (expected, actual) not (actual, expected) for Equal calls"}
]
},
{
"id": 2,
"name": "assert-new-naming-convention",
"description": "Tests the skill's specific naming convention: 'is' for assert.New(t) and 'must' for require.New(t)",
"prompt": "I'm writing Go tests with testify and I find the repeated 't' parameter verbose. How can I make my assertions more readable? Show me an example with both assert and require.",
"trap": "Model may use generic variable names like 'a' and 'r', or 'assertions' and 'requirements' instead of the skill's recommended 'is' and 'must' convention",
"assertions": [
{"id": "2.1", "text": "Uses assert.New(t) to create a reusable assertion object"},
{"id": "2.2", "text": "Uses require.New(t) to create a reusable require object"},
{"id": "2.3", "text": "Names the assert.New(t) variable 'is'"},
{"id": "2.4", "text": "Names the require.New(t) variable 'must'"},
{"id": "2.5", "text": "Shows the 'is' and 'must' variables being used for different purposes (preconditions vs verifications)"}
]
},
{
"id": 3,
"name": "error-chain-assertion",
"description": "Tests knowledge that is.Equal(ErrNotFound, err) fails on wrapped errors and ErrorIs should be used instead",
"prompt": "I have a Go function that returns wrapped errors using fmt.Errorf with %w. Write a test that checks whether the returned error is ErrNotFound. The function signature is: func FindUser(id string) (*User, error)",
"trap": "Model may use assert.Equal(ErrNotFound, err) which fails on wrapped errors instead of assert.ErrorIs",
"assertions": [
{"id": "3.1", "text": "Uses ErrorIs (not Equal) to check the error against ErrNotFound"},
{"id": "3.2", "text": "Does NOT use assert.Equal or is.Equal to compare errors directly"},
{"id": "3.3", "text": "Uses require for the initial error existence check if subsequent assertions depend on it"},
{"id": "3.4", "text": "Argument order for ErrorIs is (err, target) not (target, err)"}
]
},
{
"id": 4,
"name": "mock-assert-expectations",
"description": "Tests whether AssertExpectations is called — without it, mock expectations silently pass",
"prompt": "Create a Go test using testify/mock for a NotificationService that calls a Sender.Send method. The test should verify that Send is called exactly once with the right email address.",
"trap": "Model may set up On().Return() expectations but forget to call AssertExpectations(t), making the test pass even if Send is never called",
"assertions": [
{"id": "4.1", "text": "Mock embeds mock.Mock"},
{"id": "4.2", "text": "Mock method uses m.Called() to forward arguments"},
{"id": "4.3", "text": "Test calls m.AssertExpectations(t) to verify all expectations were met"},
{"id": "4.4", "text": "Uses .Once() or equivalent call modifier to enforce exactly one call"},
{"id": "4.5", "text": "Uses mock.Anything for arguments that don't need specific matching (e.g., context)"}
]
},
{
"id": 5,
"name": "mock-matched-by-predicate",
"description": "Tests knowledge of mock.MatchedBy for custom argument matching beyond exact equality",
"prompt": "I have a mock for a Logger interface with method Log(ctx context.Context, entry LogEntry). I need to verify that the LogEntry has Level='error' and Message contains 'timeout', but I don't care about the exact timestamp. How do I write the mock expectation?",
"trap": "Model may try to match the entire LogEntry struct exactly (which fails due to timestamp) instead of using mock.MatchedBy with a predicate function",
"assertions": [
{"id": "5.1", "text": "Uses mock.MatchedBy with a predicate function for the LogEntry argument"},
{"id": "5.2", "text": "The predicate checks Level == 'error'"},
{"id": "5.3", "text": "The predicate checks that Message contains 'timeout' (using strings.Contains or similar)"},
{"id": "5.4", "text": "Uses mock.Anything for the context argument"},
{"id": "5.5", "text": "Calls AssertExpectations at the end"}
]
},
{
"id": 6,
"name": "mock-retry-different-returns",
"description": "Tests knowledge of chaining .Once() calls to return different values per call for retry testing",
"prompt": "I need to test that my Go HTTP client retries on failure. The client calls Fetcher.Fetch(url string) ([]byte, error). First call should return a timeout error, second call should succeed with some data. How do I set up this mock?",
"trap": "Model may not know how to return different values per call and instead use a single Return() that applies to all calls",
"assertions": [
{"id": "6.1", "text": "Sets up first On().Return() with an error and .Once()"},
{"id": "6.2", "text": "Sets up second On().Return() with success data and .Once()"},
{"id": "6.3", "text": "The two expectations are on the same method with the same arguments"},
{"id": "6.4", "text": "Calls AssertExpectations to verify both calls happened"}
]
},
{
"id": 7,
"name": "suite-lifecycle-and-launcher",
"description": "Tests that suite requires a launcher function (TestXxxSuite) and understands the lifecycle order",
"prompt": "Convert these flat Go tests into a testify suite. The tests share a database connection setup and cleanup. There are 3 test functions that all need a fresh mock store before each test.\n\n```go\nfunc TestCreateUser(t *testing.T) { ... }\nfunc TestDeleteUser(t *testing.T) { ... }\nfunc TestListUsers(t *testing.T) { ... }\n```",
"trap": "Model may create the suite struct and test methods but forget the launcher function (func TestXxxSuite(t *testing.T) { suite.Run(t, new(Suite)) }), causing zero tests to run",
"assertions": [
{"id": "7.1", "text": "Creates a suite struct embedding suite.Suite"},
{"id": "7.2", "text": "Uses SetupTest (not SetupSuite) for per-test mock store initialization"},
{"id": "7.3", "text": "Includes a launcher function: func TestXxxSuite(t *testing.T) with suite.Run()"},
{"id": "7.4", "text": "Test methods are named TestXxx (starting with Test) on the suite receiver"},
{"id": "7.5", "text": "Uses SetupSuite or TearDownSuite for the shared database connection (one-time setup)"}
]
},
{
"id": 8,
"name": "suite-require-syntax",
"description": "Tests that suite methods use s.Require().NotNil() syntax for require behavior, since s.NotNil() is assert-style",
"prompt": "In my testify suite test method, I need to check that a database connection is not nil before proceeding. If it's nil, the test should stop immediately. How do I do a require-style assertion inside a suite?",
"trap": "Model may use s.NotNil() thinking it acts like require, but suite methods default to assert behavior. Must use s.Require().NotNil() for fail-fast",
"assertions": [
{"id": "8.1", "text": "Uses s.Require().NotNil() (not just s.NotNil()) for fail-fast behavior"},
{"id": "8.2", "text": "Explains that s.NotNil() and similar suite methods behave like assert (continue on failure)"},
{"id": "8.3", "text": "Shows that s.Require() returns a require-style assertion object"}
]
},
{
"id": 9,
"name": "pointer-comparison-trap",
"description": "Tests awareness that is.Equal(ptr1, ptr2) compares addresses, not values",
"prompt": "I have two *User pointers pointing to different structs with the same field values. My test `assert.Equal(t, user1, user2)` is failing. Both users have Name='Alice' and Age=30. What's wrong?",
"trap": "Model may suggest various debugging approaches without identifying the core issue: Equal on pointers compares addresses",
"assertions": [
{"id": "9.1", "text": "Identifies that assert.Equal on pointers compares memory addresses, not struct values"},
{"id": "9.2", "text": "Recommends dereferencing the pointers (e.g., assert.Equal(t, *user1, *user2)) or using EqualExportedValues"},
{"id": "9.3", "text": "Mentions EqualExportedValues as an alternative for comparing only exported fields"}
]
},
{
"id": 10,
"name": "eventually-with-rich-assertions",
"description": "Tests knowledge of EventuallyWithT for async polling with multiple rich assertions (not just bool)",
"prompt": "I need to test an async job processor. After submitting a job, I need to poll until the job status is 'completed' AND the result count is greater than 0. The polling should timeout after 10 seconds. How do I write this test with testify?",
"trap": "Model may use Eventually with a simple bool function, which only checks one condition and loses assertion error messages. EventuallyWithT allows multiple rich assertions.",
"assertions": [
{"id": "10.1", "text": "Uses EventuallyWithT (not just Eventually) for rich assertions"},
{"id": "10.2", "text": "The callback receives *assert.CollectT (or similar collect parameter)"},
{"id": "10.3", "text": "Multiple assertions are made inside the callback (status check AND result count check)"},
{"id": "10.4", "text": "Uses assert.NoError/assert.Equal with the CollectT parameter inside the callback, not with t"},
{"id": "10.5", "text": "Specifies timeout (10s) and polling interval as separate parameters"}
]
},
{
"id": 11,
"name": "testifylint-recommendation",
"description": "testifylint catches testify-specific mistakes that generic linters miss; model should recommend it over manual code review for testify patterns",
"prompt": "Our team's test code review keeps catching the same testify mistakes:\n\n1. `assert.Equal(t, err, ErrNotFound)` instead of `assert.ErrorIs(t, err, ErrNotFound)`\n2. `assert.Equal(t, got, want)` where expected/actual are swapped\n3. Using `assert.NoError(t, err)` instead of `require.NoError(t, err)` before dereferencing a pointer\n4. `assert.Equal(t, true, someCondition)` instead of `assert.True(t, someCondition)`\n\nOur lead says: 'These are all discipline issues — we should just review more carefully and add examples to our style guide.' Is there a better automated solution?",
"trap": "The lead's position (careful review + style guide) sounds reasonable for a small team. The model should recognize that testifylint catches all four of these patterns automatically, making manual review for them unnecessary. Without the skill, the model may agree with the lead or only suggest generic linters like staticcheck.",
"assertions": [
{"id": "11.1", "text": "Recommends testifylint specifically — explains that it is designed to catch exactly the patterns described (not just generic Go linters like staticcheck or golangci-lint defaults)"},
{"id": "11.2", "text": "Pushes back on the lead's 'review more carefully' approach — automated linting is more reliable than manual discipline for mechanical patterns"},
{"id": "11.3", "text": "Confirms testifylint catches at least two of the four described patterns: wrong argument order (expected/actual swap) and assert/require misuse (using assert before pointer dereference)"}
]
}
]
testify/mock — Reference
Mock interfaces to isolate the unit under test. Embed mock.Mock, implement methods with m.Called(), and always verify with AssertExpectations(t).
Quick example
type MockSender struct { mock.Mock }
func (m *MockSender) Send(ctx context.Context, to string, msg Message) error {
return m.Called(ctx, to, msg).Error(0)
}
func TestOrderService_Place(t *testing.T) {
is := assert.New(t)
m := new(MockSender)
m.On("Send", mock.Anything, "buyer@example.com", mock.AnythingOfType("Message")).Return(nil)
err := NewOrderService(m).Place(context.Background(), order)
is.NoError(err)
m.AssertExpectations(t)
}Defining a mock
type NotificationSender interface {
Send(ctx context.Context, to string, msg Message) error
BatchSend(ctx context.Context, recipients []string, msg Message) (int, error)
}
type MockNotificationSender struct { mock.Mock }
func (m *MockNotificationSender) Send(ctx context.Context, to string, msg Message) error {
return m.Called(ctx, to, msg).Error(0)
}
func (m *MockNotificationSender) BatchSend(ctx context.Context, recipients []string, msg Message) (int, error) {
args := m.Called(ctx, recipients, msg)
return args.Int(0), args.Error(1)
}Argument matchers
// mock.Anything — matches any value
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil)
// mock.AnythingOfType — matches by type name
m.On("Send", mock.Anything, mock.AnythingOfType("string"), mock.Anything).Return(nil)
// mock.MatchedBy — custom predicate
m.On("Send", mock.Anything, mock.MatchedBy(func(to string) bool {
return strings.HasSuffix(to, "@example.com")
}), mock.Anything).Return(nil)Call modifiers
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once() // exactly 1 call
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil).Times(3) // exactly 3 calls
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil).Maybe() // optional
// Side effects
m.On("Send", mock.Anything, mock.Anything, mock.Anything).
Run(func(args mock.Arguments) {
msg := args.Get(2).(Message)
t.Logf("mock received: %s", msg.Subject)
}).Return(nil)Different returns per call
// First call returns error, second succeeds (retry testing)
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("timeout")).Once()
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil).Once()Removing expectations
call := m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(nil)
call.Unset()
m.On("Send", mock.Anything, mock.Anything, mock.Anything).Return(errors.New("fail"))Verification
m.AssertExpectations(t) // verify all expectations
m.AssertCalled(t, "Send", mock.Anything, "buyer@example.com", mock.Anything) // specific call made
m.AssertNotCalled(t, "BatchSend", mock.Anything, mock.Anything, mock.Anything) // specific call NOT made
m.AssertNumberOfCalls(t, "Send", 2) // exact call countRelated skills
How it compares
Pick golang-stretchr-testify when agents generate testify tests; use stdlib-only testing guidance when testify is not a project dependency.
FAQ
Why does golang-stretchr-testify prefer require over assert for preconditions?
golang-stretchr-testify teaches that require stops the test immediately on failure. Using assert for NoError or NotNil lets execution continue and can nil-pointer panic on later assert.Equal calls when parsing fails.
What testify mistake does the JSON config eval catch?
golang-stretchr-testify's assert-vs-require-precondition eval asks agents to parse JSON, verify no error, confirm config is not nil, then check Port 8080, Host localhost, and Debug false—catching assert used where require is required.
Is Golang Stretchr Testify safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.