Go Testing & Benchmark Skill
Table-driven test and fuzz scaffolding for agents - a cookbook-style Agent Skill for Go 1.26 test generation from acceptance criteria.
Search across all documentation pages
Table-driven test and fuzz scaffolding for agents - a cookbook-style Agent Skill for Go 1.26 test generation from acceptance criteria.
Produces test scaffolds: table-driven t.Run subtests, httptest handler cases, fuzz F.Add seeds, and benchmark stubs - with go test verification commands, not production code rewrites.
| Input | Why |
|---|---|
| Acceptance criteria | Maps to test case names |
| Package under test | Import path, exported API |
| Error types / sentinels | errors.Is expectations |
| HTTP handlers? | httptest.NewRecorder scaffold |
| Concurrency in code? | Add -race to verification |
*_test.go scaffold with table slice and subtestsFuzzXxx with corpus seedsBenchmarkXxx with b.Loop (Go 1.24+ style) or classic loopgo test ./pkg/..., go test -race, go test -fuzz=FuzzParse -fuzztime=30stime.Sleep for synchronization - use channels, synctest, or interfaces.t.Parallel() documented per case.-update flag pattern per team policy.Quick-reference recipe card - copy-paste ready.
func TestParseID(t *testing.T) {
tests := []struct {
name string
in string
want string
wantErr bool
}{
{name: "valid", in: "abc-123", want: "abc-123"},
{name: "empty", in: "", wantErr: true},
{name: "spaces", in: " ", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseID(tt.in)
if tt.wantErr {
if err == nil {
t.Fatal("expected error")
}
return
}
if err != nil {
t.Fatalf("unexpected: %v", err)
}
if got != tt.want {
t.Fatalf("got %q want %q", got, tt.want)
}
})
}
}go test ./internal/parse/... -count=1
go test -race ./internal/parse/... # if package uses goroutinesWhen to reach for this skill:
TestEverything functionAC:
- Valid UUID returns normalized form
- Invalid UUID returns ErrInvalid
- Empty input returns ErrEmptyEach bullet becomes t.Run name and table row.
func TestGetUserHandler(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(getUser))
t.Cleanup(srv.Close)
resp, err := http.Get(srv.URL + "/users/1")
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("status %d", resp.StatusCode)
}
}httptest.NewRecorder for unit scopefunc FuzzParseID(f *testing.F) {
f.Add("abc-123")
f.Add("")
f.Fuzz(func(t *testing.T, in string) {
_, _ = ParseID(in) // must not panic; document invariants
})
}go test -fuzz=FuzzParseID -fuzztime=30s ./internal/parse/func BenchmarkParseID(b *testing.B) {
for b.Loop() {
_, _ = ParseID("abc-123")
}
}go test -bench=BenchmarkParseID -benchmem ./internal/parse/ -count=5** testify / cmp**: if team uses github.com/stretchr/testify, skill imports require per ADR.
Otherwise stdlib-only assertions keep deps minimal.
Examples (ExampleXxx): for godoc-verified snippets - see Examples as Executable Documentation.
Coverage: go test -cover ./... for report; skill does not chase 100% on generated scaffold.
Build tags: integration tests behind //go:build integration - skill separates fast unit table from slow IT.
/ breaks -run regex - use safe names.tt := tt before t.Parallel().| Approach | When |
|---|---|
| Manual TDD | Experienced author pair programming |
| Code coverage gates only | Misses edge cases |
| Property-based (rapid) | Complex invariants |
| This skill | Fast AC-to-subtest mapping with agents |
No. Extend with table cases or new files. Flag duplication instead of replacing human-written tests.
Only when team ADR or sibling packages already use it. Default stdlib testing for new scaffolds.
Unit scaffolds only unless inputs specify testcontainers ADR. Link to team IT doc instead.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 16, 2026