Instruction file imported from guastiDS/be-labs (
.github/instructions/testing.instructions.md). Copyright stays with the author.
Testing Guidelines
Write comprehensive, maintainable tests that provide confidence in code quality and functionality.
Test Organization
- Place test files next to the code they test with
_test.gosuffix - Use same package for white-box testing (access to unexported symbols)
- Use
_testpackage suffix for black-box testing (external API testing) - Group related tests in the same file
- Organize test files to mirror source code structure
Test Structure
- Use table-driven tests for testing multiple scenarios
- Name tests descriptively:
Test_FunctionName_Scenario_ExpectedResult - Use subtests with
t.Run()for better organization and isolation - Follow Arrange-Act-Assert pattern in test structure
- Keep test functions focused on single functionality
Test Data and Fixtures
- Create test fixtures for complex setup scenarios
- Use meaningful test data that represents real-world scenarios
- Avoid hardcoded values in favor of named constants
- Clean up test data using
t.Cleanup()or defer statements - Use temporary directories and files for file system tests
HTTP API Testing
- Test HTTP handlers using
httptest.ResponseRecorder - Test both success and error response scenarios
- Validate response status codes, headers, and body content
- Test different HTTP methods and request formats
- Use
httptest.Serverfor integration testing
Database Testing
- Use separate test database or in-memory database for tests
- Clean up test data after each test
- Test database migrations and rollbacks
- Use transactions that can be rolled back for isolated tests
- Mock database interactions for unit tests when appropriate
Error Testing
- Test all error conditions and edge cases
- Verify error messages and error types
- Test error handling in different layers (handler, service, repository)
- Use error injection to test error propagation
- Test timeout and cancellation scenarios
Mock and Test Doubles
- Use interfaces to enable easy mocking
- Create mocks for external dependencies (APIs, databases)
- Keep mocks simple and focused on test scenarios
- Verify mock interactions when testing behavior
- Use dependency injection for testable designs
Test Coverage and Quality
- Aim for high test coverage but focus on quality over quantity
- Test critical business logic thoroughly
- Include integration tests for important workflows
- Test performance-critical code with benchmarks
- Run tests with race detector enabled (
go test -race)
Test Helpers
- Mark helper functions with
t.Helper()for better error reporting - Create reusable test utilities for common setup
- Use
testing.TBinterface for functions used in tests and benchmarks - Share test helpers in
internal/testutilpackage when appropriate
Benchmarking
- Write benchmarks for performance-critical code
- Use
testing.Bfor benchmark functions - Run benchmarks to establish performance baselines
- Profile benchmark results to identify bottlenecks
- Compare benchmark results before and after optimizations