harness/plugins/common/claude/skills/go-test-debug/SKILL.md
Debug complex Go test failures — flaky tests, race conditions, deadlocks, panics, timeouts, nil pointer dereferences. Systematic error-first diagnosis workflow.
npx skillsauth add popoffvg/dotfiles go-test-debugInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Systematic workflow for AI agents to diagnose and fix Go test failures. Optimized for token-efficient debugging — read errors first, isolate fast, fix with evidence.
Skip for simple failures - fix immediately if:
Use full workflow for:
NEVER read production code before reading error message. Reading order:
git diff for recent changesCRITICAL: If no specific test name is given, run the full package test first and save the output to a file before doing anything else. This raw output is the single most important artifact — it contains error messages, stack traces, and line numbers that guide the entire debugging process.
# When specific test is NOT known — save output for analysis
go test -v -count=1 ./package/... 2>&1 | tee /tmp/test-output.txt
# Then find failing tests from saved output
grep -E "^--- FAIL:" /tmp/test-output.txt
Once the failing test is identified, re-run it isolated:
go test -v -count=1 -run TestName ./package/...
Flags explained:
-v — show all output including t.Log-count=1 — bypass test cache (cached results show (cached) — stale data during debugging)-run — isolate the specific test; subtests use /: -run "TestFoo/case_name"For machine-parseable output when failure is complex:
go test -json -count=1 -run TestName ./package/... 2>&1 | jq 'select(.Action == "fail")'
Read the output and classify into one of these categories:
| Category | Signature in output | Jump to |
|---|---|---|
| Build error | [build failed], undefined:, cannot use | references/categories.md § Build Errors |
| Assertion failure | expected X, got Y, Not equal:, got X want Y | references/categories.md § Assertion Failures |
| Panic / nil pointer | panic:, nil pointer dereference, stack trace | references/categories.md § Panics |
| Race condition | WARNING: DATA RACE | references/categories.md § Race Conditions |
| Timeout / deadlock | test timed out, all goroutines are asleep | references/categories.md § Timeouts |
| Flaky test | Passes sometimes, fails other times | references/categories.md § Flaky Tests |
| Environment / fixtures | no such file, connection refused, env var missing | references/categories.md § Environment Issues |
Run checks in order:
go build ./... — does it compile?go vet ./... — static analysis issues?go test -v -count=1 -run TestSpecific ./package/... — specific testgo test -race -count=1 ./package/... — race conditions?Check what changed recently — the bug is almost always in the diff:
git diff HEAD~3 -- ./package/
git log --oneline -5 -- ./package/
go test -v -run TestFoo ./package/... # see all subtests
go test -v -run "TestFoo/failing_case" ./package/... # isolate one case
Spaces in subtest names become _ in the regex. Find the case struct in test code by matching the name field.
Before debugging logic, verify the test isn't failing due to environment:
TestMain(m *testing.M) setup/teardowntestdata/ directory for required fixturesos.Getenv / os.LookupEnv in test files//go:build integrationlocalhost:5432, :6379, etc.result, _ := Func().sync.Mutex, channels, atomic). Never use time.Sleep().WaitGroup counts, mutex ordering.# Verify the fix
go test -v -count=1 -run TestName ./package/...
# Run broader to catch regressions
go test -count=1 ./package/...
# Race check
go test -race -count=1 ./package/...
t.Logf()t.Logf() for temporary debug output — it only prints on failure or with -v, and stays cleant.Logf() doesn't give enough visibilitygo-debug skill for Delve workflowsfmt.Println in tests — use t.Logf() insteadTest failed
├── Doesn't compile? → go build ./... → fix compilation
├── Read error message → classify type:
│ ├── "expected X, got Y" → read test inputs → read function → check diff → fix code
│ ├── "panic:" → read stack trace top frame → go to file:line → find nil pointer → trace back
│ ├── "DATA RACE" → note two locations → identify shared var → add sync primitive
│ ├── "test timed out" → check goroutine states → find blocked chan/mutex → fix
│ ├── "no such file" / "connection refused" → check fixtures/env/TestMain
│ └── Intermittent → go test -count=100 -failfast → find non-determinism source
└── After fix: go test -v -count=1 + go test -race
# Essential debugging commands
go test -v -count=1 -run TestName ./pkg/... # isolated, no cache
go test -race -count=1 ./pkg/... # race detector
go test -count=100 -failfast -run TestX ./pkg/... # reproduce flaky
For detailed diagnosis per failure type, see references/categories.md
Eval checklist:
Test inputs:
Can change: diagnosis workflow steps, file reading order, isolation strategies, evidence gathering Cannot change: error-first principle (read errors before code), evidence-driven requirement Min sessions before eval: 5 Runs per experiment: 3
testing
Use when the user asks to create test sets, enumerate scenarios, generate edge cases, or draft a coverage matrix before implementation.
testing
Use when the user asks to review, audit, score, or validate test sets for missed cases before execution or merge.
tools
Test harness plugins in isolation using tmux panes. Runs MCP servers, unit tests, typecheck, and Claude plugin loading. Use when user says "test plugin", "check plugin", "run plugin tests", "validate plugin", or names a specific plugin to test.
development
Guide for designing integration and e2e tests using BDD (Behavior-Driven Development) methodology with Cucumber-style Given/When/Then scenarios. Use when writing or reviewing tests for any service, API, or component. Language-agnostic — covers scenario structure, step notation, assertion principles, async patterns, and common anti-patterns.