golang-stretchr-testify
samber/cc-skills-golang
Comprehensive guide to stretchr/testify for readable assertions, mocks, and test suites in Go.
What is golang-stretchr-testify?
stretchr/testify extends Go's testing package with readable assertions, mock support, and suite lifecycle management. Use it when writing tests that need clear failure messages, creating mocks to isolate units under test, or organizing tests with shared setup/teardown. Apply when the codebase imports github.com/stretchr/testify.
- Write readable assertions with assert and require packages, choosing failure behavior (continue vs. stop)
- Create and verify mocks with argument matchers, call modifiers, and expectation verification
- Organize related tests into suites with SetupTest/TearDownTest lifecycle hooks
- Compare complex types with JSONEq, ElementsMatch, InDelta, and other specialized assertions
- Poll asynchronously with Eventually and EventuallyWithT for testing concurrent or delayed operations
- Detect and walk error chains with ErrorIs and ErrorAs for robust error testing
How to install golang-stretchr-testify
npx skills add https://github.com/samber/cc-skills-golang --skill golang-stretchr-testify- Go installed and configured
- github.com/stretchr/testify imported in test files
- Basic familiarity with Go's testing package and *testing.T
How to use golang-stretchr-testify
- 1.Choose assert.New(t) for verifications that continue on failure, or require.New(t) for preconditions that must pass
- 2.Write assertions using the core methods (Equal, NoError, Contains, etc.) with expected value first
- 3.For mocks, embed mock.Mock in your mock struct, use m.Called() in methods, and call AssertExpectations(t) after the test
- 4.For suites, embed suite.Suite, implement SetupTest/TearDownTest, write TestXxx methods, and call suite.Run(t, new(YourSuite))
- 5.Use advanced assertions like JSONEq, Eventually, or ElementsMatch for complex comparisons and async operations
- 6.Run testifylint to catch common mistakes like swapped argument order or missing mock verification
Use cases
- Writing unit tests with clear, self-documenting assertions that show all failures at once
- Mocking interfaces to isolate the code under test and verify call expectations
- Setting up test suites with shared fixtures and lifecycle management across multiple test methods
- Testing JSON APIs by comparing responses with whitespace and key-order independence
- Verifying async operations like job completion or message delivery with polling assertions
- Go engineers writing unit and integration tests
- Developers creating mocks to isolate components
- Teams organizing test suites with shared setup/teardown logic
- Code reviewers auditing test quality and testify usage patterns
golang-stretchr-testify FAQ
Use require for preconditions (setup, error checks) where continuing would panic or produce misleading failures. Use assert for verifications where you want to see all failures at once. Never mix randomly in the same test.
You must call AssertExpectations(t) after the test to verify mock expectations. Without it, expectations are silently ignored and the test passes.
Use is.JSONEq(expectedJSON, actualJSON) which parses both strings and compares the resulting objects, ignoring formatting differences.
Equal uses DeepEqual and requires exact type match. EqualValues converts both values to a common type first, useful for comparing int and int64 or similar numeric types.
Use is.Eventually(func() bool { ... }, timeout, interval) for simple boolean checks, or is.EventuallyWithT(func(c *assert.CollectT) { ... }, timeout, interval) for rich assertions with error handling.
Full instructions (SKILL.md)
Source of truth, from samber/cc-skills-golang.
name: golang-stretchr-testify description: "Comprehensive guide to stretchr/testify for Golang testing. Covers assert, require, mock, and suite packages in depth. Use when writing tests with testify, creating mocks, setting up test suites, or choosing between assert and require. Covers testify assertions, mock expectations, argument matchers, call verification, suite lifecycle, and advanced patterns like Eventually, JSONEq, and custom matchers. Apply when the codebase imports github.com/stretchr/testify." user-invocable: true license: MIT compatibility: Designed for Claude Code or similar AI coding agents, and for projects using Golang. metadata: author: samber version: "1.2.1" openclaw: emoji: "✅" homepage: https://github.com/samber/cc-skills-golang requires: bins: - go - gotests install: - kind: go package: github.com/cweill/gotests/...@latest bins: [gotests] skill-library-version: "1.11.1" allowed-tools: Read Edit Write Glob Grep Bash(go:) Bash(golangci-lint:) Bash(git:) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(gotests:) AskUserQuestion
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 tests
Example
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. Useis.ErrorIsto walk the chain- Swapped argument order — testify assumes
(expected, actual). Swapping produces backwards diffs assertfor guards — test continues after failure and panics on nil dereference. Userequire- 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
Related skills
More from samber/cc-skills-golang and the wider catalog.
golang-code-style
Go code style conventions for clarity, control flow, and readability—line breaking, variable declarations, and when comments help.
golang-error-handling
Idiomatic Go error handling: wrapping, inspection, structured logging, and production-grade error tracking.
golang-performance
Go performance optimization patterns: identify bottlenecks with profiling, then apply the right fix.
golang-design-patterns
Idiomatic Go design patterns: functional options, constructors, error handling, resource lifecycle, graceful shutdown, and resilience.
golang-testing
Production-ready Go tests with table-driven patterns, testify integration, parallel execution, fuzzing, and leak detection.
golang-security
Security best practices and vulnerability prevention for Go code—injection, crypto, secrets, and authentication.