0xDEADBEEF

Home Projects AboutRSS

Go test your tests in Go with go test

  • go
  • testing

Today, we are going to talk about something that is boring… but necessary; tests.

But you are probably tired of reading blog posts that talk about “Why testing is important”, “Why your thing should have tests”, and “Top 5 reasons you should adopt test-driven development”. So, instead of writing about the usual “You need tests because it will blah your blah with blah because of blah”, I want to talk about something else; how to make writing tests not suck as much.

Here are some tips and tricks I picked up while writing tests for fac.

1. Current Testing Directory

Here is a fun fact; when you run go test for a package, the test binary will be run within the package being tested.

Allow me to demonstrate. Assume your project directory is setup like this

project
└── server
    ├── server.go
    └── server_test.go

And your server_test.go looks like this

package server

import (
	"os"
	"testing"
)

func TestCoolServerStuff(t *testing.T) {
	wd, _ := os.Getwd()
	t.Log(wd)
}

If you run this from your root project directory, you will get the following output

pwd
/Users/mikechoi/src/go/src/github.com/mkchoi212/project

➜ go test -v
=== RUN   TestCoolServerStuff
--- PASS: TestCoolServerStuff (0.00s)
          server_test.go:10: github.com/mkchoi212/project/server
PASS
ok        github.com/mkchoi212/project/server        0.007s

Notice that the log says github.com/mkchoi212/project/server and not whatever pwd said.

2. testdata is ignored

According to this Go documentation,

Directory and file names that begin with “.” or “_” are ignored by the go tool, as are directories named “testdata”.

So, if you need mock files to test something - such as response.json for your networking functions - you can place it in package_directory/testdata/response.json. Now, you can easily load the mock files like so

func TestServerResponse(t *testing.T) {
    if json, err := os.Open("testdata/response.json"); err != nil {
        doStuffWithNetworkResponse(json)
        t.Log("🎉")
    }
}

Notice that we are able to simple say testdata/response.json because of #1.

3. testhelper

This is a simple concept but is very helpful when writing tests in Go. When writing code in Go, you probably have written thousands of lines of code that look like this

if data, err := doSomethingCool(); err != nil {
    doMoreCoolThingsHere(data)
}

The trouble is that this is what 80% of statements you are going to tests are going to look like. After all, you are testing if something either didn’t return an error, is equal to something, and or didn’t crap out. Eventually, your testsuite will get filled with if data, err := ....; err != nil statements. So, the brilliant solution to this is to make helper functions.

Instead of writing the code you saw previously with bunch of if-statements, you can now write the following.

func TestCoolThing(t *testing.T) {
    data, err := doSomethingCool()
    // Awesome
    testhelper.Ok(t, err)
    
    otherData, err := doSomethingAmazing()
    testhelper.Ok(t, err)

    // This is really useful as well
    testhelper.Equals(t, data, otherData)	
}

And if a test fails for some reason, the helper functions will print out the error messages in red and pin-point the location where the test failed.

3. go test tricks

Here are some additional tips and tricks you can use while using go test.

Test all packages in project directory

./... is the magic argument.

➜ go test
ok      github.com/mkchoi212/project              [no test files]

➜ go test ./...
ok      github.com/mkchoi212/project              [no test files]
ok      github.com/mkchoi212/project/server       0.012s
ok      github.com/mkchoi212/project/testhelper   [no test files]

Ignore package while testing

You might need this when you don’t necessarily need to test something or because you just want a higher code coverage percentage 😄

Notice testhelper is not being tested any more

➜ go test `go list ./... | grep -v 'testhelper'`
ok      github.com/mkchoi212/project              [no test files]
ok      github.com/mkchoi212/project/server       0.012s

Code coverage statistics

➜ go test --cover
PASS
coverage: 100.0% of statements
ok      github.com/mkchoi212/project/server  0.011s