go-testslisted
Install: claude install-skill CasLubbers/code-design-skills
# Go tests
## Table-driven is the default
One test function, a slice of cases, a subtest per case. Adding coverage means adding a struct literal.
```go
func TestParseDuration(t *testing.T) {
tests := map[string]struct {
in string
want time.Duration
wantErr bool
}{
"seconds": {in: "30s", want: 30 * time.Second},
"compound": {in: "1h30m", want: 90 * time.Minute},
"zero": {in: "0", want: 0},
"empty": {in: "", wantErr: true},
"bad unit": {in: "5x", wantErr: true},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
t.Parallel()
got, err := ParseDuration(tc.in)
if tc.wantErr {
if err == nil { t.Fatal("want error, got nil") }
return
}
if err != nil { t.Fatalf("unexpected error: %v", err) }
if got != tc.want { t.Errorf("got %v, want %v", got, tc.want) }
})
}
}
```
A map keys cases by name and randomises order, which surfaces inter-case dependencies. Name cases after the behaviour, not `case1`. `t.Run` gives each one its own line in the output and lets you run one with `-run TestParseDuration/bad_unit`.
## Failure messages carry the values
The reader is looking at CI output, not your screen.
```go
// Good
t.Errorf("ParseDuration(%q) = %v, want %v", tc.in, got, tc.want)
// Bad — tells you nothing
t.Error("wrong result")
```
`t