Tests in Go
Explore how to use Go's testing features such as subtests and table-driven tests to write clean and maintainable test code. Understand various testing options including coverage reporting and concurrency detection to improve test reliability and organization.
We'll cover the following...
Go has some fantastic features for tests that are worth mentioning.
Subtests
Subtests help us write more structured test code. Let’s use an example to understand this:
For the rest of the lesson, we’ll rely on this production function for writing tests. The NewPerson function has two branches to cover:
- The happy one is when we provide a valid
age. - The bad one is when we pass an invalid
age.
With that being said, we have to write two test functions that we’ll call TestNewPerson_WithValidAge and TestNewPerson_WithNotValidAge. Hopefully, subtests provide us with a better approach. Let’s see this in the code below:
package subtests
import "testing"
func TestNewPerson(t *testing.T) {
t.Run("MustReturnPerson_WhenAValidAgeIsPassed", func(t *testing.T) {
age := 18
got, err := NewPerson(age)
if err != nil {
t.Errorf("err not expected but got %q", err.Error())
}
if got == nil {
t.Fatal("got expected to be not nil")
}
if got.age != age {
t.Errorf("age expected to be %d but got %d", age, got.age)
}
})
t.Run("MustReturnErr_WhenANotValidAgeIsPassed", func(t *testing.T) {
age := -5
expectedErr := "age cannot be less than 0"
got, err := NewPerson(age)
if err == nil {
t.Fatal("err not expected to be nil")
}
if err.Error() != expectedErr {
t.Errorf("expected err was %q but got %q", expectedErr, err.Error())
}
if got != nil {
t.Error("got expected to be nil")
}
})
}
Thanks to the t.Run function, we’re able to create a parent-child structure in our test code. In fact, the ...