Package test is the minimalist testing helper for Go.
Forked from earthboundkid/be, Inspired by Mat Ryer and Alex Edwards.
- Simple, readable and typesafe test assertions using generics
- Single file without dependencies for simple copy and paste into your project
- Fail fast by default but easily switch to relaxed with
test.Relaxed(t)
- Extend project specific test functions in
test
module when using copy-paste approach
You can use this package in two ways:
go get github.com/raeperd/test
- Copy the contents of test.go into your project. (e.g. internal/test/test.go)
- This file contains all the necessary code for the package and can be used without any dependencies.
- (optional)relaxed.go and debug.go is optional for niche use cases.
import "github.com/raeperd/test"
func TestExample(t *testing.T) {
want := 1
test.Equal(t, want, 2-1)
}
import "yourproject/internal/test"
func TestExample(t *testing.T) {
want := 1
test.Equal(t, want, 2-1)
}
test.Equal(t, "hello", "world") // bad
test.Equal(t, "goodbye", "goodbye") // good
test.NotEqual(t, "hello", "world") // good
test.NotEqual(t, "goodbye", "goodbye") // bad
test.DeepEqual(t, map[int]bool{1: true, 2: false}, map[int]bool{1: true, 2: false}) // good
test.DeepEqual(t, nil, []int{}) // bad
s := []int{1, 2, 3}
test.DeepEqual(t, []int{1, 2, 3}, s) // good
test.DeepEqual(t, []int{3, 2, 1}, s) // bad
var err error
test.Nil(t, err) // good
test.NotNil(t, err) // bad
err = errors.New("(O_o)")
test.Nil(t, err) // bad
test.NotNil(t, err) // good
test.Zero(t, 0)
test.Zero(t, time.Time{}.Local())
test.Zero(t, []string(nil))
test.NotZero(t, []string{""})
test.NotZero(t, true)
type mytype string
var mystring mytype = "hello, world"
test.Contains(t, "hello, world", "world") // good
test.Contains(t, mystring, "world") // good
test.Contains(t, mystring, "World") // bad
test.Contains(t, []int{1, 2, 3, 4, 5}, 3) // good
test.Contains(t, []int{1, 2, 3, 4, 5}, 6) // bad
test.NotContains(t, "hello, world", "World") // good
test.NotContains(t, mystring, "World") // good
test.NotContains(t, mystring, "world") // bad
test.NotContains(t, []int{1, 2, 3, 4, 5}, 6) // good
test.NotContains(t, []int{1, 2, 3, 4, 5}, 3) // bad
test.True(t, o.IsValid())
test.True(t, len(pages) >= 20)
Tests usually should not fail. When they do fail, the failure should be repeatable. Therefore, it doesn't make sense to spend a lot of time writing good test messages. (This is unlike error messages, which should happen fairly often, and in production, irrepeatably.) Package test is designed to simply fail a test quickly and quietly if a condition is not met with a reference to the line number of the failing test. If the reason for having the test is not immediately clear from context, you can write a comment, just like in normal code. If you do need more extensive reporting to figure out why a test is failing, use test.DebugLog
or test.Debug
to capture more information.
Most tests just need simple equality testing, which is handled by test.Equal
(for comparable types), and test.DeepEqual
(which relies on reflect.DeepEqual
). Another common test is that a string or byte slice should contain or not some substring, which is handled by test.In
and test.NotIn
. Rather than package be providing every possible test helper, you are encouraged to write your own advanced helpers for use with test.True
, while package be takes away the drudgery of writing yet another simple func nilErr(t *testing.T, err) { ... }
.
Every tool in the be module requires a testing.TB
as its first argument. There are various clever ways to get the testing.TB implicitly, but package be is designed to be simple and explicit, so it's easiest to just always pass in a testing.TB the boring way.