Inline test helpers
Use inline test helpers to minimize indentation and have failures point out failed cases directly. Given a function calculating the double of an int.
// double returns the double of i if i is positive but never more than
// max int
func double(i int) (int, error) {
if i < 0 {
return 0, fmt.Errorf("double: i must be positive")
}
n := i * 2
if n < i {
return MAX, nil
}
return n, nil
}
const MAX int = int(^uint(0) >> 1)
The test would look like this.
func Test_double(t *testing.T) {
ok := func(input, exp int) {
t.Helper()
got, err := double(input)
if err != nil {
t.Error(err)
}
if got != exp {
t.Errorf("double(%v) returned %v, expected %v", input, got, exp)
}
}
// cases
ok(1, 2)
ok(3, 6)
ok(MAX, MAX)
bad := func(input, exp int) {
t.Helper()
_, err := double(input)
if err == nil {
t.Errorf("double(%v) should fail", input)
}
}
bad(-2, 4)
}
Keep it simple and use utmost two inlined helpers. Compared to
table-driven-tests inlined helpers declare the how
before the cases. If you have many cases, this style is more
readable as you first tell the reader the meaning of
"ok" and "bad".
Another positive benefit
of this style is values are not grouped in a testcase
variable. I.e. readability improves as the values are used
directly.
This style may be less readable if each case
requires many values, though it depends on the lenght of the
values combined.