skills/go-tdd-baby-steps/SKILL.md
TDD with baby steps for Go. Use when writing tests, doing TDD, practicing red-green-refactor, or when test cycles feel too large and risky. Also use when the user asks about incremental test development, test-first workflow, or wants help breaking a feature into small testable steps. Covers table-driven tests, testify, t.Run subtests, t.Helper, transformation priority premise, and incremental test progression.
npx skillsauth add gonzaloserrano/gopilot go-tdd-baby-stepsInstall 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.
Test-Driven Development using the smallest possible increments, with Go idioms.
These laws create a tight feedback loop: write a tiny test, watch it fail, write just enough code to pass.
Each cycle should take ~2 minutes. If longer, the step is too big.
If stuck or code is getting messy:
Never debug longer than the cycle itself. Revert instead.
Build up the test table incrementally — each row adds ONE behavior.
func TestParseAmount(t *testing.T) {
tests := []struct {
name string
input string
want int
wantErr bool
}{
{name: "empty string", input: "", want: 0, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseAmount(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
Production code (fake it):
func ParseAmount(s string) (int, error) {
return 0, errors.New("empty")
}
Add one row, generalize production code:
{name: "single digit", input: "5", want: 5},
func ParseAmount(s string) (int, error) {
if s == "" {
return 0, errors.New("empty input")
}
return strconv.Atoi(s)
}
{name: "negative number", input: "-3", want: -3},
{name: "leading zeros", input: "007", want: 7},
{name: "non-numeric", input: "abc", wantErr: true},
Each row forces at most one production code change.
Use t.Run for progression and t.Helper for shared assertions:
func assertStack(t *testing.T, s *Stack, wantLen int, wantEmpty bool) {
t.Helper()
assert.Equal(t, wantLen, s.Len())
assert.Equal(t, wantEmpty, s.IsEmpty())
}
func TestStack(t *testing.T) {
t.Run("new stack is empty", func(t *testing.T) {
s := NewStack()
assertStack(t, s, 0, true)
})
t.Run("push one element", func(t *testing.T) {
s := NewStack()
s.Push(42)
assertStack(t, s, 1, false)
})
t.Run("pop returns last pushed", func(t *testing.T) {
s := NewStack()
s.Push(42)
got, err := s.Pop()
require.NoError(t, err)
assert.Equal(t, 42, got)
assertStack(t, s, 0, true)
})
t.Run("pop empty stack returns error", func(t *testing.T) {
s := NewStack()
_, err := s.Pop()
require.Error(t, err)
})
}
Each t.Run block is a baby step — one new behavior per subtest.
Prefer simpler transformations:
if)Choose the transformation that requires the least code change.
development
Go programming language skill for writing idiomatic Go code, code review, error handling, testing, concurrency, security, and program design. Use when writing, reviewing, debugging, or asking about Go code — even if the user doesn't explicitly mention 'Go best practices'. Also use when: reviewing Go PRs, debugging Go tests, fixing Go errors, designing Go APIs, implementing security-sensitive code, handling user input, authentication, sessions, cryptography, building resource-oriented gRPC APIs with Google AIP standards, configuring golangci-lint, setting up structured logging with slog, or any question about Go idioms and patterns. Covers table-driven tests, error wrapping, goroutine patterns, interface design, generics, iterators, stdlib patterns up to Go 1.26, OWASP security practices, and Google AIP (API Improvement Proposals) with einride/aip-go for pagination, filtering, ordering, field masks, and resource names.
tools
Detect and fix Go error handling antipatterns across a codebase. Use when auditing error handling, fixing double-handled errors, removing log-and-return patterns, cleaning up log-and-wrap helpers, or when the user asks to analyze error handling hygiene, find error handling violations, or ensure errors are handled exactly once. Covers detection patterns, classification of true vs false positives, fix strategies for interior vs boundary code, and verification steps.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------