| name | writing-go-tests |
| description | Applies current Go testing best practices. Use when writing or modifying Go test files or advising on Go testing strategies. |
Go Testing Best Practices
This skill provides actionable testing guidelines. For detailed implementation patterns, code examples, rationale, and production system references, consult go-testing-best-practices.md.
When Working with Go Tests
Always apply these current best practices:
1. Test Organisation
- Place test files alongside source code using
*_test.go naming
- Use internal tests (same package) for unit testing unexported functions
- Use external tests (
package foo_test) for integration testing and examples
- Split test files by functionality when they exceed 500-800 lines (e.g.,
handler_auth_test.go, handler_validation_test.go)
2. Table-Driven Testing
- Prefer map-based tables over slice-based for automatic unique test names
- Use descriptive test case names that appear in failure output
- See detailed guide for complete pattern and examples
3. Concurrent Testing
- Use
testing/synctest for deterministic concurrent testing (Go 1.24+)
- This eliminates flaky time-based tests and runs in microseconds instead of seconds
- For traditional parallel tests, always call
t.Parallel() first in test functions
4. Assertions and Comparisons
- Use
cmp.Diff() from google/go-cmp for complex comparisons
- Standard library is sufficient for simple tests
- Testify is the dominant third-party framework when richer assertions are needed
5. Mocking and Test Doubles
- Favour integration testing with real dependencies over heavy mocking
- Use Testcontainers for database/service integration tests
- When mocking is necessary, prefer simple function-based test doubles over code generation
- Use interface-based design ("accept interfaces, return structs")
6. Coverage Targets
- Aim for 70-80% coverage as a practical target
- Focus on meaningful tests over percentage metrics
- Use
go test -cover and go tool cover -html for analysis
7. Test Fixtures
- Use
testdata directory for test fixtures (automatically ignored by Go toolchain)
- Implement golden file testing for validating complex output
- Use functional builder patterns for complex test data
8. Helpers and Cleanup
- Always mark helper functions with
t.Helper() for accurate error reporting
- Use
t.Cleanup() for resource cleanup (superior to defer in tests)
9. Benchmarking (Go 1.24+)
- Use
B.Loop() method as the preferred pattern (prevents compiler optimisations)
- Combine with
benchstat for statistical analysis
- Use
-benchmem for memory profiling
10. Naming Conventions
- Test functions:
Test*, Benchmark*, Fuzz*, Example* (capital letter after prefix)
- Use
got and want for actual vs expected values
- Use descriptive test case names in table-driven tests
Integration vs Unit Testing
- Separate tests by environment variable (preferred over build tags)
- See detailed guide for implementation pattern
Additional Reference Material
Load go-testing-best-practices.md when you need:
- Complete code examples for table-driven tests, mocking patterns, golden files, helpers, or benchmarks
- Detailed explanation of testing/synctest concurrent testing patterns
- Rationale behind why specific patterns are preferred over alternatives
- Production system examples and statistics (Kubernetes, Docker, Uber, Netflix, ByteDance)
- Context on testing framework choices (Testify, GoMock, Testcontainers)
- Comprehensive coverage strategies and tooling details
- Integration testing patterns with containerisation
The detailed guide contains full context, examples with explanations, and production-proven patterns. This SKILL.md provides the actionable rules to apply.
Key Principle
Focus on meaningful tests that validate behaviour rather than implementation. Pragmatic excellence over theoretical perfection.