
Golang Testing
- 38 installs
- 4 repo stars
- Updated April 11, 2026
- 89jobrien/steve
golang-testing is a Claude Code skill that writes Go tests using table-driven patterns, interface mocking, testify, Testcontainers integration tests, and benchmarks.
About
golang-testing is a Claude Code skill for testing Go applications. A developer uses it to write table-driven unit tests, mock dependencies via interfaces, run integration tests with Testcontainers, and benchmark performance-critical code. It provides Go examples for testify assertions and test organization.
- Writes table-driven Go tests with error cases
- Interface-based mocking and testify assertions
- Integration tests with Testcontainers and benchmarks
Golang Testing by the numbers
- 38 all-time installs (skills.sh)
- Ranked #50 of 98 Go skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
golang-testing capabilities & compatibility
- Capabilities
- go testing · unit testing · mocking · integration testing
- Use cases
- testing
- Pricing
- Free
What golang-testing says it does
Comprehensive Go testing patterns including table-driven tests, mocking, integration testing, benchmarks, and test organization.
Integration Tests with Testcontainers
npx skills add https://github.com/89jobrien/steve --skill golang-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 38 |
|---|---|
| repo stars | ★ 4 |
| Last updated | April 11, 2026 |
| Repository | 89jobrien/steve ↗ |
What it does
Write unit, integration, and benchmark tests for Go code.
Who is it for?
Go developers writing unit, integration, and benchmark tests with mocking.
Skip if: Testing in languages other than Go.
When should I use this skill?
You are writing unit, integration, or benchmark tests for Go code.
What you get
Produces table-driven Go tests, interface mocks, testify assertions, and Testcontainers integration tests.
- Go unit tests
- mock implementations
- integration tests
By the numbers
- 6 use cases from unit tests to benchmarks
Files
Golang Testing
This skill provides guidance on comprehensive testing strategies for Go applications including unit tests, integration tests, benchmarks, and test organization.
When to Use This Skill
- When writing unit tests for Go code
- When creating table-driven tests
- When mocking dependencies with interfaces
- When writing integration tests with test containers
- When benchmarking performance-critical code
- When organizing test suites and fixtures
Table-Driven Tests
Basic Pattern
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive numbers", 2, 3, 5},
{"negative numbers", -2, -3, -5},
{"mixed numbers", -2, 3, 1},
{"zeros", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
}
})
}
}With Error Cases
func TestDivide(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
wantErr bool
errString string
}{
{"valid division", 10, 2, 5, false, ""},
{"divide by zero", 10, 0, 0, true, "division by zero"},
{"negative result", -10, 2, -5, false, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := Divide(tt.a, tt.b)
if tt.wantErr {
if err == nil {
t.Fatalf("expected error, got nil")
}
if !strings.Contains(err.Error(), tt.errString) {
t.Errorf("error = %v; want containing %q", err, tt.errString)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result != tt.expected {
t.Errorf("Divide(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected)
}
})
}
}Interface-Based Mocking
Define Interfaces
// repository.go
type UserRepository interface {
FindByID(ctx context.Context, id string) (*User, error)
Save(ctx context.Context, user *User) error
}
type EmailSender interface {
Send(ctx context.Context, to, subject, body string) error
}Create Mock Implementations
// mocks/user_repository.go
type MockUserRepository struct {
FindByIDFunc func(ctx context.Context, id string) (*User, error)
SaveFunc func(ctx context.Context, user *User) error
}
func (m *MockUserRepository) FindByID(ctx context.Context, id string) (*User, error) {
if m.FindByIDFunc != nil {
return m.FindByIDFunc(ctx, id)
}
return nil, nil
}
func (m *MockUserRepository) Save(ctx context.Context, user *User) error {
if m.SaveFunc != nil {
return m.SaveFunc(ctx, user)
}
return nil
}Use in Tests
func TestUserService_GetUser(t *testing.T) {
expectedUser := &User{ID: "123", Name: "John"}
repo := &MockUserRepository{
FindByIDFunc: func(ctx context.Context, id string) (*User, error) {
if id == "123" {
return expectedUser, nil
}
return nil, ErrNotFound
},
}
service := NewUserService(repo)
t.Run("existing user", func(t *testing.T) {
user, err := service.GetUser(context.Background(), "123")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if user.Name != expectedUser.Name {
t.Errorf("got name %q; want %q", user.Name, expectedUser.Name)
}
})
t.Run("non-existing user", func(t *testing.T) {
_, err := service.GetUser(context.Background(), "456")
if !errors.Is(err, ErrNotFound) {
t.Errorf("got error %v; want ErrNotFound", err)
}
})
}Testify Assertions
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestWithTestify(t *testing.T) {
// assert continues on failure
assert.Equal(t, 5, Add(2, 3), "addition should work")
assert.NotNil(t, result)
assert.Len(t, items, 3)
assert.Contains(t, slice, item)
assert.True(t, condition)
assert.NoError(t, err)
assert.ErrorIs(t, err, ErrNotFound)
// require stops test on failure
require.NoError(t, err, "setup must succeed")
require.NotNil(t, config)
}Integration Tests with Testcontainers
import (
"context"
"testing"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/modules/postgres"
)
func TestUserRepository_Integration(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test in short mode")
}
ctx := context.Background()
// Start PostgreSQL container
pgContainer, err := postgres.Run(ctx,
"postgres:15-alpine",
postgres.WithDatabase("testdb"),
postgres.WithUsername("test"),
postgres.WithPassword("test"),
)
require.NoError(t, err)
defer pgContainer.Terminate(ctx)
// Get connection string
connStr, err := pgContainer.ConnectionString(ctx, "sslmode=disable")
require.NoError(t, err)
// Connect and run migrations
db, err := sql.Open("postgres", connStr)
require.NoError(t, err)
defer db.Close()
runMigrations(db)
// Create repository and test
repo := NewUserRepository(db)
t.Run("save and find user", func(t *testing.T) {
user := &User{ID: "123", Name: "John", Email: "john@example.com"}
err := repo.Save(ctx, user)
require.NoError(t, err)
found, err := repo.FindByID(ctx, "123")
require.NoError(t, err)
assert.Equal(t, user.Name, found.Name)
})
}Test Fixtures
Setup/Teardown Pattern
func TestMain(m *testing.M) {
// Global setup
setup()
code := m.Run()
// Global teardown
teardown()
os.Exit(code)
}
func setup() {
// Initialize test database, load fixtures, etc.
}
func teardown() {
// Clean up resources
}Per-Test Setup
func setupTest(t *testing.T) (*UserService, func()) {
t.Helper()
db := setupTestDB(t)
repo := NewUserRepository(db)
service := NewUserService(repo)
cleanup := func() {
db.Close()
}
return service, cleanup
}
func TestUserService(t *testing.T) {
service, cleanup := setupTest(t)
defer cleanup()
// Run tests using service
}Benchmarks
func BenchmarkFibonacci(b *testing.B) {
for i := 0; i < b.N; i++ {
Fibonacci(20)
}
}
func BenchmarkFibonacciParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Fibonacci(20)
}
})
}
// With sub-benchmarks
func BenchmarkSort(b *testing.B) {
sizes := []int{100, 1000, 10000}
for _, size := range sizes {
b.Run(fmt.Sprintf("size-%d", size), func(b *testing.B) {
data := generateData(size)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sort.Ints(data)
}
})
}
}Testing HTTP Handlers
func TestHandler_GetUser(t *testing.T) {
// Setup mock service
service := &MockUserService{
GetUserFunc: func(ctx context.Context, id string) (*User, error) {
return &User{ID: id, Name: "John"}, nil
},
}
handler := NewHandler(service)
t.Run("success", func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/users/123", nil)
rec := httptest.NewRecorder()
handler.GetUser(rec, req)
assert.Equal(t, http.StatusOK, rec.Code)
var response User
err := json.NewDecoder(rec.Body).Decode(&response)
require.NoError(t, err)
assert.Equal(t, "John", response.Name)
})
t.Run("not found", func(t *testing.T) {
service.GetUserFunc = func(ctx context.Context, id string) (*User, error) {
return nil, ErrNotFound
}
req := httptest.NewRequest(http.MethodGet, "/users/999", nil)
rec := httptest.NewRecorder()
handler.GetUser(rec, req)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
}Test Organization
File Structure
/internal
/user
user.go
user_test.go # Unit tests
user_integration_test.go # Integration tests (build tag)
testdata/ # Test fixtures
users.jsonBuild Tags for Integration Tests
//go:build integration
package user
func TestIntegration(t *testing.T) {
// Integration test code
}Run with: go test -tags=integration ./...
Coverage
# Generate coverage
go test -coverprofile=coverage.out ./...
# View in browser
go tool cover -html=coverage.out
# Check coverage percentage
go test -cover ./...Best Practices
1. Test behavior, not implementation - Focus on inputs and outputs 2. One assertion per test - Keep tests focused and clear 3. Use t.Helper() - Mark helper functions for better error reporting 4. Parallel tests - Use t.Parallel() for independent tests 5. Descriptive names - TestUserService_CreateUser_WithInvalidEmail 6. Test edge cases - Empty inputs, nil values, boundary conditions 7. Keep tests fast - Use mocks, skip slow tests with -short 8. Avoid test pollution - Each test should be independent
Related skills
FAQ
What test patterns does it cover?
Table-driven tests, interface-based mocking, testify assertions, Testcontainers integration tests, and benchmarks.
How does it mock dependencies?
It defines interfaces and creates mock implementations with function fields to control behavior.