Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
affaan-m avatar

Golang Testing

  • 1.4k installs
  • 238k repo stars
  • Updated August 5, 2026
  • affaan-m/ecc

This is a copy of golang-testing by affaan-m - installs and ranking accrue to the original listing.

golang-testing is a Claude Code skill that generates idiomatic Go tests using table-driven patterns, benchmarks, fuzzing, and RED-GREEN-REFACTOR TDD for developers who need production-grade go test coverage in Go modules

About

golang-testing is an ECC-origin skill that teaches and generates Go testing patterns aligned with the standard go test toolchain. It centers on table-driven tests as the primary idiom, with guidance for test helpers, benchmarking, race detection, coverage analysis, integration testing, and fuzzing. The skill activates on Go source files matched by globs for **/*.go, go.mod, and go.sum, making it repo-aware during test authoring sessions. Developers reach for golang-testing when writing new Test functions, improving flaky suites, or applying TDD cycles in Go services and CLIs. Patterns extend general testing principles with Go-specific conventions such as subtests, parallel flags, and helper hygiene so generated tests read like idiomatic production code rather than generic templates.

  • Implements the RED-GREEN-REFACTOR TDD cycle in Go
  • Supports table-driven tests, subtests, benchmarks and fuzzing
  • Produces both test files and coverage reports
  • Follows idiomatic Go testing practices
  • Works for new functions, existing code and performance-critical paths

Golang Testing by the numbers

  • 1,411 all-time installs (skills.sh)
  • +86 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/affaan-m/ecc --skill golang-testing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs1.4k
repo stars238k
Last updatedAugust 5, 2026
Repositoryaffaan-m/ecc

How do you write idiomatic table-driven Go tests?

Generate idiomatic Go tests following table-driven tests, benchmarks, fuzzing and the RED-GREEN-REFACTOR TDD cycle.

Who is it for?

Go developers adding or refactoring tests in modules with .go, go.mod, and go.sum files who want standard-library testing idioms.

Skip if: Non-Go projects or teams that only need frontend or Python test generation without the go test toolchain.

When should I use this skill?

User writes or improves Go tests, asks for table-driven tests, benchmarks, fuzzing, race detection, or TDD in Go.

What you get

Go test files with table-driven cases, benchmarks, fuzz targets, and integration test scaffolding.

  • *_test.go files
  • Benchmark functions
  • Fuzz test targets

By the numbers

  • Repo globs target 3 path patterns: **/*.go, go.mod, and go.sum

Files

SKILL.mdMarkdownGitHub ↗

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:   "user@example.com",
            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.out

Coverage Thresholds

# Fail if coverage below 80%
go test -cover ./... | grep -E 'coverage: [0-7][0-9]\.[0-9]%' && exit 1

Benchmarking

func BenchmarkValidateEmail(b *testing.B) {
    email := "user@example.com"

    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        ValidateEmail(email)
    }
}

Run benchmarks:

go test -bench=. -benchmem

Compare benchmarks:

go test -bench=. -benchmem > old.txt
# make changes
go test -bench=. -benchmem > new.txt
benchstat old.txt new.txt

Mocking

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.json

Package Naming

// Black-box testing (external perspective)
package user_test

// White-box testing (internal access)
package user

Common 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

1. Use `t.Parallel()` for independent tests 2. Use `testing.Short()` to skip slow tests 3. Use `t.TempDir()` for temporary directories 4. Use `t.Setenv()` for environment variables 5. Avoid `init()` in test files 6. Keep tests focused - one behavior per test 7. 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

Related skills

FAQ

What testing pattern does golang-testing prioritize?

golang-testing prioritizes table-driven tests with the standard go test runner. Tests use a slice of named cases and t.Run subtests, which is the idiomatic Go pattern for exhaustive input coverage.

Which files trigger golang-testing?

golang-testing activates on Go repositories matched by globs for **/*.go, go.mod, and go.sum. The ECC metadata scopes the skill to Go modules during test authoring and review tasks.

Testing & QAbackendtesting

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.