Documentation
¶
Overview ¶
Package test is a minimalist test assertion helper library.
Philosophy ¶
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 be 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, like 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 test in the be package 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.
Example ¶
// mock *testing.T for example purposes t := test.Relaxed(&mockingT{}) 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 type mytype string var mystring mytype = "hello, world" 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, 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
Output: want: hello; got: world got: goodbye reflect.DeepEqual([]int(nil), []int{}) == false reflect.DeepEqual([]int{3, 2, 1}, []int{1, 2, 3}) == false got: <nil> got: (O_o) "World" not in "hello, world" 6 not in [1 2 3 4 5] "world" in "hello, world" 3 in [1 2 3 4 5]
Index ¶
- func Contains[H interface{ ... }, N comparable](t testing.TB, haystack H, needle N)
- func Debug(t testing.TB, f func())
- func DebugLog(t testing.TB, format string, args ...any)
- func DeepEqual[T any](t testing.TB, want, got T)
- func Equal[T comparable](t testing.TB, want, got T)
- func False(t testing.TB, value bool)
- func Nil(t testing.TB, v any)
- func NotContains[H interface{ ... }, N comparable](t testing.TB, haystack H, needle N)
- func NotEqual[T comparable](t testing.TB, bad, got T)
- func NotNil(t testing.TB, v any)
- func NotZero[T any](t testing.TB, value T)
- func Relaxed(t testing.TB) testing.TB
- func True(t testing.TB, value bool)
- func Zero[T any](t testing.TB, value T)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Contains ¶
func Contains[H interface{ ~string | []N }, N comparable](t testing.TB, haystack H, needle N)
Contains calls t.Fatalf if needle is not contained in haystack. H can be either a string type (including custom string types) or a slice of comparable type N. When H is a string type and N is any type, fmt.Sprintf is used to convert N to string for comparison. When H is a slice, N is same type as the slice elements for direct comparison.
func Debug ¶
Debug takes a callback that will only be run after the test fails.
Example ¶
// mock *testing.T for example purposes t := &mockingT{} // If a test fails, the callbacks will be replayed in LIFO order t.Run("logging-example", func(*testing.T) { x := 1 x1 := x test.Debug(t, func() { // record some debug information about x1 fmt.Println("x1:", x1) }) x = 2 x2 := x test.Debug(t, func() { // record some debug information about x2 fmt.Println("x2:", x2) }) test.Equal(t, x, 3) }) // If a test succeeds, nothing will be replayed t.Run("silent-example", func(*testing.T) { y := 1 y1 := y test.Debug(t, func() { // record some debug information about y1 fmt.Println("y1:", y1) }) y = 2 y2 := y test.Debug(t, func() { // record some debug information about y2 fmt.Println("y2:", y2) }) test.NotEqual(t, y, 3) })
Output: want: 2; got: 3 x2: 2 x1: 1
func DebugLog ¶
DebugLog records a message that will only be logged after the test fails.
Example ¶
// mock *testing.T for example purposes t := &mockingT{} // If a test fails, the logs will be replayed in LIFO order t.Run("logging-example", func(*testing.T) { x := 1 test.DebugLog(t, "x: %d", x) x = 2 test.DebugLog(t, "x: %d", x) test.Equal(t, x, 3) }) // If a test succeeds, nothing will be replayed t.Run("silent-example", func(*testing.T) { y := 1 test.DebugLog(t, "y: %d", y) y = 2 test.DebugLog(t, "y: %d", y) test.NotEqual(t, y, 3) })
Output: want: 2; got: 3 x: 2 x: 1
func DeepEqual ¶
DeepEqual calls t.Fatalf if want and got are different according to reflect.DeepEqual.
func Equal ¶
func Equal[T comparable](t testing.TB, want, got T)
Equal calls t.Fatalf if want != got.
func NotContains ¶
func NotContains[H interface{ ~string | []N }, N comparable](t testing.TB, haystack H, needle N)
NotContains calls t.Fatalf if needle is contained in haystack. For type of H, N see Contains
func NotEqual ¶
func NotEqual[T comparable](t testing.TB, bad, got T)
NotEqual calls t.Fatalf if got == bad.
func Relaxed ¶
Relaxed returns a testing.TB which replaces calls to t.FailNow, t.Fatal, and t.Fatalf with calls to t.Fail, t.Error, and t.Errorf respectively.
Example ¶
// mock *testing.T for example purposes t := &mockingT{} t.Run("dies on first error", func(*testing.T) { test.Equal(t, 1, 2) test.Equal(t, 3, 4) }) t.Run("shows multiple errors", func(*testing.T) { relaxedT := test.Relaxed(t) test.Equal(relaxedT, 5, 6) test.Equal(relaxedT, 7, 8) })
Output: want: 1; got: 2 want: 5; got: 6 want: 7; got: 8
Types ¶
This section is empty.