v1.0.26 — 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.
From gopilotnpx claudepluginhub gonzaloserrano/gopilot --plugin gopilotThis skill uses the workspace's default tool permissions.
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.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.