5 Testing Tips in Go

Mert Akkaya
Star Gazers
Published in
3 min readFeb 22, 2021

Before saying anything about tests in Go, I must say that, there are already some great posts on the internet about testing in Go, written earlier. In this blog post I just aim to share own experiences with a bit repeating what have written before and also a listing some useful libraries & resources.

1. Table Driven Tests

Table driven tests convention is a real, “Why couldn’t I think that before” solution, especially if you’re coming from a different language. Unit tests are actually quite similar to each other and table driven thinking is great to form the tests. It looks something like this:

Example take from Dave Cheney’s blog post. Table driven tests has some advantages by default. They’re self-descriptive first of all, besides giving names to the tests the input and the wanted data tells much about the tests. And it’s pretty easier to add new ones too.

Here’s a great library to use with your favorite IDE. You can select the unit you wanted and it can automatically generate a table-driven test structure.

https://github.com/cweill/gotests

2. Test Units, Units are Packages in Go

In the Go’s coding structure every unit needs to be separated into a different package. To test “unit”s, you need to test the packages. The best way to testing a package is using them as clients. So test your package’s public API. That’s how people use them. Force yourself as a developer who misuses the functions.

Separate Testing Package

Generally tests are added to the Go projects with _test.go file naming convention. But separating test packages with an additional testing package has its own advantages, too. First of all, in order to forcing yourself as an external user, you’ll not have access to the unexported variables / functionalities. Additionally it may help on prevention of cylic dependencies between packages.

3. Testdata & Golden Files

As we’ve talked about table driven tests, defining the input data may create unnecessary crowding of test code. To keeping the tests readable testdata directory can be very helpful. The Go tool, automatically ignore the testdata directory, so it’s ideal to place the data here.

With Golden files additionally, you may want to store the expected outcomes of you tests. Defining an external flag to update the golden files is common to manage the changed outputs easily. With this way your test code might stay still but the returned data can be changed and easily tracked with a file change review.

4. Make Them Fast

When tests are being added to the projects, they might became larger and larger and harder to maintain & run. Especially when it comes to integration tests, they might require some infrastructure to build up, or depend on something else to wait etc.

Build Tags for Separation

Using Go’s build tags enables you to run the tests separately. Adding the file’s first line the below code will help the Go tool to tag them as integration.

// +build integration

With this kind of separation when it’s called

go test ./...

integration tests won’t run. Instead the command below will be needed.

go test -tags=integration ./...
https://medium.com/better-programming/the-test-pyramid-80d77535573

Keeping the testing pyramid in shape is also critical when managing the tests.

Update: An alternative to separation via flags is checking environment variables on tests as mentioned on Peter Bourgon’s blog post. Which seems like a better convention.

Other Testing Flags

Take a look at Go’s Testing Flags. Using t.Parallel() will allow you to identify the tests which can run on parallel. The flags such as -failfast, -short, -timeout may be helpful to managing testing performance. Running tests with -p option also might help on debugging, it can also be used on building.

5. Mocking & Interface Pollution

With the mocking libraries, defining interfaces is the easiest way to writing tests. It’s pretty easy to design the code with unnecessary interface implementations. So, do not export interfaces to the packages unless you really need them. Rakyll’s blog post summarizes it all well.

--

--