mcpField
G
go-testing

go-testing

github.com/autumnsgroveTesting & quality671 installsUpdated 5d ago
Repository

About go-testing

A Go testing skill for developers writing and running tests. It covers idiomatic test patterns alongside benchmarks and fuzzing.

Key features

  1. 01Table-driven tests and subtests
  2. 02Test helpers and cleanup
  3. 03Interface-based dependency mocks
  4. 04HTTP handler tests
  5. 05Benchmarks and fuzz tests

Use cases

  1. 01Writing tests for Go packages
  2. 02Testing HTTP handlers
  3. 03Benchmarking or fuzzing Go code

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/autumnsgrove/lattice --skill go-testing

After installing, type/go-testingin Claude Code to confirm it loaded.

Details

From the project README

Go Testing Skill

When to Activate

Activate this skill when:

  • Writing Go unit tests
  • Creating table-driven tests
  • Working with test helpers and fixtures
  • Mocking dependencies via interfaces
  • Running benchmarks or fuzz tests

Quick Commands

# Run all tests
go test ./...

# Verbose output
go test -v ./...

# Run specific test
go test -run TestUserCreate

# With coverage
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Run benchmarks
go test -bench=. ./...

# Race detector
go test -race ./...

Basic Test Structure

// math_test.go
package math

import "testing"

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    expected := 5

    if result != expected {
        t.Errorf("Add(2, 3) = %d; want %d", result, expected)
    }
}

Table-Driven Tests (Idiomatic Go)

func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive numbers", 2, 3, 5},
        {"negative numbers", -1, -1, -2},
        {"mixed signs", -1, 5, 4},
        {"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)
            }
        })
    }
}

Subtests and Parallel Execution

func TestAPIEndpoints(t *testing.T) {
    tests := []struct {
        name     string
        endpoint string
        status   int
    }{
        {"health", "/health", 200},
        {"users", "/api/users", 200},
    }

    for _, tt := range tests {
        tt := tt // capture range variable
        t.Run(tt.name, func(t *testing.T) {
            t.Parallel() // run in parallel
            // test logic
        })
    }
}

Test Helpers

func assertEqual(t *testing.T, got, want int) {
    t.Helper() // marks as helper for line numbers
    if got != want {
        t.Errorf("got %d; want %d", got, want)
    }
}

func assertNoError(t *testing.T, err error) {
    t.Helper()
    if err != nil {
        t.Fatalf("unexpected error: %v", err)
    }
}

Setup and Teardown

func TestDatabase(t *testing.T) {
    // Setup
    db := setupTestDB(t)

    // Teardown (runs after test)
    t.Cleanup(func() {
        db.Close()
    })

    // Test code
    user, err := db.CreateUser("[email protected]")
    assertNoError(t, err)
}

Mocking with Interfaces

// Define interface for dependencies
type UserRepository interface {
    FindByID(id string) (*User, error)
    Save(user *User) error
}

// Mock implementation
type MockUserRepo struct {
    FindByIDFunc func(id string) (*User, error)
}

func (m *MockUserRepo) FindByID(id string) (*User, error) {
    return m.FindByIDFunc(id)
}

// Test with mock
func TestUserService_GetUser(t *testing.T) {
    mock := &MockUserRepo{
        FindByIDFunc: func(id string) (*User, error) {
            return &User{ID: "123", Email: "[email protected]"}, nil
        },
    }

    service := &UserService{repo: mock}
    user, err := service.GetUser("123")

    assertNoError(t, err)
    assertEqual(t, user.ID, "123")
}

HTTP Handler Testing

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestHealthHandler(t *testing.T) {
    req := httptest.NewRequest("GET", "/health", nil)
    rr := httptest.NewRecorder()

    handler := http.HandlerFunc(HealthHandler)
    handler.ServeHTTP(rr, req)

    if rr.Code != http.StatusOK {
        t.Errorf("status = %d; want %d", rr.Code, http.StatusOK)
    }
}

Benchmarks

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(2, 3)
    }
}

// Run: go test -bench=. -benchmem

Directory Structure

project/
├── internal/
│   ├── user/
│   │   ├── user.go
│   │   └── user_test.go
│   └── api/
│       ├── handler.go
│       └── handler_test.go
└── test/
    └── integration/
        └── api_test.go

Test Function Signatures

func TestXxx(t *testing.T)      // Regular test
func BenchmarkXxx(b *testing.B) // Benchmark
func ExampleXxx()               // Example (docs)
func FuzzXxx(f *testing.F)      // Fuzz test

Related Resources

See AgentUsage/testing_go.md for complete documentation including:

  • Fuzz testing patterns
  • Build tags for test types
  • TestMain for package-level setup
  • Coverage in CI

Comments

Markdown supported