MarketplaceSKILL.mdLeída en ef648e0
golang-testing
Go testing best practices including table-driven tests, test helpers, benchmarking, race detection, coverage analysis, and integration testing patterns. Use when writing or improving Go tests.
Resumen
Go Testing
This skill provides comprehensive Go testing patterns extending common testing principles with Go-specific idioms.
Testing Framework
Use the standard go test with table-driven tests as the primary pattern.
Table-Driven Tests
The idiomatic Go testing pattern:
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
wantErr bool
}{
{
name: "valid email",
email: "[email protected]",
wantErr: false,
},
{
name: "missing @",
email: "userexample.com",
wantErr: true,
},
{
name: "empty string",
email: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateEmail(tt.email)
if (err != nil) != tt.wantErr {
t.Errorf("ValidateEmail(%q) error = %v, wantErr %v",
tt.email, err, tt.wantErr)
}
})
}
}Benefits:
- Easy to add new test cases
- Clear test case documentation
- Parallel test execution with
t.Parallel() - Isolated subtests with
t.Run()
Test Helpers
Use t.Helper() to mark helper functions:
func assertNoError(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func assertEqual(t *testing.T, got, want interface{}) {
t.Helper()
if !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}Benefits:
- Correct line numbers in test failures
- Reusable test utilities
- Cleaner test code
Test Fixtures
Use t.Cleanup() for resource cleanup:
func testDB(t *testing.T) *sql.DB {
t.Helper()
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
t.Fatalf("failed to open test db: %v", err)
}
// Cleanup runs after test completes
t.Cleanup(func() {
if err := db.Close(); err != nil {
t.Errorf("failed to close db: %v", err)
}
})
return db
}
func TestUserRepository(t *testing.T) {
db := testDB(t)
repo := NewUserRepository(db)
// ... test logic
}Race Detection
Always run tests with the -race flag to detect data races:
go test -race ./...In CI/CD:
- name: Test with race detector
run: go test -race -timeout 5m ./...Why:
- Detects concurrent access bugs
- Prevents production race conditions
- Minimal performance overhead in tests
Coverage Analysis
Basic Coverage
go test -cover ./...Detailed Coverage Report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.outCoverage Thresholds
# Fail if coverage below 80%
go test -cover ./... | grep -E 'coverage: [0-7][0-9]\.[0-9]%' && exit 1Benchmarking
func BenchmarkValidateEmail(b *testing.B) {
email := "[email protected]"
b.ResetTimer()
for i := 0; i < b.N; i++ {
ValidateEmail(email)
}
}Run benchmarks:
go test -bench=. -benchmemCompare benchmarks:
go test -bench=. -benchmem > old.txt
# make changes
go test -bench=. -benchmem > new.txt
benchstat old.txt new.txtMocking
Interface-Based Mocking
type UserRepository interface {
GetUser(id string) (*User, error)
}
type mockUserRepository struct {
users map[string]*User
err error
}
func (m *mockUserRepository) GetUser(id string) (*User, error) {
if m.err != nil {
return nil, m.err
}
return m.users[id], nil
}
func TestUserService(t *testing.T) {
mock := &mockUserRepository{
users: map[string]*User{
"1": {ID: "1", Name: "Alice"},
},
}
service := NewUserService(mock)
// ... test logic
}Integration Tests
Build Tags
//go:build integration
// +build integration
package user_test
func TestUserRepository_Integration(t *testing.T) {
// ... integration test
}Run integration tests:
go test -tags=integration ./...Test Containers
func TestWithPostgres(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// Setup test container
ctx := context.Background()
container, err := testcontainers.GenericContainer(ctx, ...)
assertNoError(t, err)
t.Cleanup(func() {
container.Terminate(ctx)
})
// ... test logic
}Test Organization
File Structure
package/
├── user.go
├── user_test.go # Unit tests
├── user_integration_test.go # Integration tests
└── testdata/ # Test fixtures
└── users.jsonPackage Naming
// Black-box testing (external perspective)
package user_test
// White-box testing (internal access)
package userCommon Patterns
Testing HTTP Handlers
func TestUserHandler(t *testing.T) {
req := httptest.NewRequest("GET", "/users/1", nil)
rec := httptest.NewRecorder()
handler := NewUserHandler(mockRepo)
handler.ServeHTTP(rec, req)
assertEqual(t, rec.Code, http.StatusOK)
}Testing with Context
func TestWithTimeout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
err := SlowOperation(ctx)
if !errors.Is(err, context.DeadlineExceeded) {
t.Errorf("expected timeout error, got %v", err)
}
}Best Practices
- Use
t.Parallel()for independent tests - Use
testing.Short()to skip slow tests - Use
t.TempDir()for temporary directories - Use
t.Setenv()for environment variables - Avoid
init()in test files - Keep tests focused - one behavior per test
- Use meaningful test names - describe what's being tested
When to Use This Skill
- Writing new Go tests
- Improving test coverage
- Setting up test infrastructure
- Debugging flaky tests
- Optimizing test performance
- Implementing integration tests
Archivos 1 archivo
Instálala a mano
Deska ejecuta esto por ti, para cada agente que elijas. Para ejecutarlo tú en una terminal:
npx skills add affaan-m/ecc --skill golang-testingMás de affaan-m
- docker-patternsaffaan-mDocker and Docker Compose patterns for local development, container security, networking, volume strategies, and multi-service orchestration. Use when setting up containerized development environments or reviewing Docker configurations.4,800 instalaciones en skills.sh0
- security-reviewaffaan-mUse this skill when adding authentication, handling user input, working with secrets, creating API endpoints, or implementing payment/sensitive features. Provides comprehensive security checklist and patterns.4,800 instalaciones en skills.sh0
- backend-patternsaffaan-mBackend architecture patterns, API design, database optimization, and server-side best practices for Node.js, Express, and Next.js API routes. Use when building or reviewing Node.js, Express, or Next.js API routes and their data access.4,700 instalaciones en skills.sh0
- frontend-patternsaffaan-mFrontend development patterns for React, Next.js, state management, performance optimization, and UI best practices. Use when building or reviewing React or Next.js components, state, or render performance.4,700 instalaciones en skills.sh0
- coding-standardsaffaan-mBaseline cross-project coding conventions for naming, readability, immutability, and code-quality review. Use detailed frontend or backend skills for framework-specific patterns. Use when reviewing code quality or naming with no framework-specific skill that applies.4,500 instalaciones en skills.sh0