Testing packages

In Go it is customary to write (unit) tests for your package. Writing testsinvolves the testing package and the program go test.Both have excellent documentation.

The go test program runs all the test functions. Without any defined tests forour even package, go test yields:

  1. % go test
  2. ? even [no test files]

Let us fix this by defining a test in a test file. Test files reside in thepackage directory and are named _test.go. Those test files are just likeother Go programs, but go test will only execute the test functions. Each testfunction has the same signature and its name should start withTest: func TestXxx(t testing.T) .

When writing test you will need to tell go test whether a test wassuccessful or not. A successful test function just returns. Whenthe test fails you can signal this with the followingfunctions. These are the most important ones (see go doc testing or go help testfunc for more):

  • func (t *T) Fail(), Fail marks the test function as having failed butcontinues execution.

  • func (t *T) FailNow(), FailNow marks the test function as having failedand stops its execution. Any remaining tests in this file are skipped, andexecution continues with the next test.

  • func (t *T) Log(args …interface{}), Log formats its arguments usingdefault formatting, analogous to Print(), and records the text in the errorlog.

  • func (t *T) Fatal(args …interface{}), Fatal is equivalent to Log()followed by FailNow().

Putting all this together we can write our test. First we pick a name:even_test.go. Then we add the following contents:

  1. package even 1
  2. import "testing" 2
  3. func TestEven(t *testing.T) { 3
  4. if !Even(2) {
  5. t.Log("2 should be even!")
  6. t.Fail()
  7. }
  8. }

A test file belongs to the current 1 package. This is not only convenient, butalso allows tests of unexported functions and structures. We then 2 import thetesting package. And finally the test we want to execute. The code here 3should hold no surprises: we check if the Even function works OK. And now, themoment we have been waiting for executing the test.

  1. % go test
  2. ok even 0.001s

Our test ran and reported ok. Success! If we redefine our test function, wecan see the result of a failed test:

  1. // Entering the twilight zone
  2. func TestEven(t *testing.T) {
  3. if Even(2) {
  4. t.Log("2 should be odd!")
  5. t.Fail()
  6. }
  7. }

We now get:

  1. FAIL even 0.004s
  2. --- FAIL: TestEven (0.00 seconds)
  3. 2 should be odd!
  4. FAIL

And you can act accordingly (by fixing the test for instance).

Writing new packages should go hand in hand with writing (some)documentation and test functions. It will make your code better and itshows that you really put in the effort.

The Go test suite also allows you to incorporate example functions which serveas documentation and as tests. These functions need to start with Example.

  1. func ExampleEven() {
  2. if Even(2) {
  3. fmt.Printf("Is even\n")
  4. }
  5. // Output: 1
  6. // Is even
  7. }

Those last two comments lines 1 are part of the example, go test uses thoseto check the generated output with the text in the comments. If there isa mismatch the test fails.