Easy assertion helpers in Go

- go testing

One of the things I enjoy about Go is its standard library, which comes with batteries included. Sure, some packages (like flag) aren’t as powerful or ergonomic as the available alternatives but I’m generally willing to accept this in order to avoid dependencies.

Testing

The same also applies to Go’s built-in test support, the testing package. Let’s look at a typical test:

package example

import "testing"

func Add(a, b int) int {
	return a + b
}

func TestAdd(t *testing.T) {
	want := 6
	got := Add(4, 2)

	if got != want {
		t.Errorf("got %v, wanted %v", got, want)
	}
}

This is not too bad but gets a bit repetitive, so people often end up using external assertion libraries like testify. However, for most of my projects I try to avoid external dependencies as much as possible, because I don’t want to deal with upgrading them and similar headaches. Today it struck me that the generics (added in Go 1.18) make it easy to write useful assertion helpers without resorting to any libraries. Here’s a helper I added to one of my projects today:

func assertEqual[T comparable](t *testing.T, got, want T) {
	t.Helper()

	if got != want {
		t.Errorf("got %v, wanted %v", got, want)
	}
}

This equality assertion takes a type parameter T, which will be satisfied by any type satisfying the comparable interface defined in the universe block. Additionally it takes three positional parameters: the test case as well as the actual and desired values. The t.Helper() method ensures that failed assertions will be reported for the line where assertEqual is used, not the line inside the test helper function.

This is what the test looks like now:

package example

import "testing"

func Add(a, b int) int {
	return a + b
}

func TestAdd(t *testing.T) {
	want := 6
	got := Add(4, 2)

	assertEqual(t, got, want)

        // or simply
        // assertEqual(t, Add(4, 2), 6)
}

Not a big deal for a single test but noticeably nicer across an entire test suite.

Summary

Using Go’s new generics allowed me to refactor and simplify the test suite of a moderately complex project without having to add any external dependencies.

Feedback