Why should you write tests?

Programming is not an easy task, write test is neither, but part of the software development process is writing tests. Testing our code is a good way to ensure quality and improve reliability, Introducing Go, 2016. When we talk about testing, we’re implicitly referring to automated testing, it’s the practice of writing small programs that check that code behaves as expected for defined entries, The Go Programming Language, 2016]book-the-go-programming-language.

How are tests written in Golang?

The Golang standard library testing package provides support for writing automated tests. A file with the suffix _test.go must exist, for example, to test sum.go, a sum_test.go file created.

Inside this file with suffix _test.go the test functions are defined, with the signature func TestFuncName(t *testing.T), where the parameter t is a reference to the type testing.T, imported from the testing package, the prefix Test is a requirement in the function name, to test the function Sum(x, y) result of the math package, we can create a test function with the following signature, func TestSum(t *testing.T).

func TestSum(t *testing.T) {
    x := 1
    y := 2
    expected := 3
    result := math.Sum(x, y)

    if result != expected {
        t.Errorf(
            "Expected that %d+%d is %d, but actual take %d",
            x, y, expected, result)
    }
}

In Go, it is common to use a test table to define test cases, a struct is created, abstracting all inputs and expected output, likes in the sum test, there would be two numbers to be added, and the expected result of the sum.

Instead of calling the sum function, once, and validating its result, using a test table, a loop is defined to go through the entire table, calling the function several times.

func TestSum(t *testing.T) {
    testTable := []struct {
        x int
        y int
        expected int
    }{
        {1, 1, 2},
        {0, 1, 1},
        {0, 0, 0},
        {0, -1, -1},
        {-1, -1, -2},
    }

    for _, test := range testTable {
        result := math.Sum(test.x, text.y)
        if result != tabela.expected {
            t.Errorf(
                "Expected that %d+%d is %d, but actual take %d",
                test.x, test.y, test.expected, result)
        }
    }
}

WARNING: Go is very strict when naming a package, the only exception for compound names is the _test suffix, as in math_test package, so anyone using the math package will not have visibility of the test functions.

When everything goes as expected, there was no error, the tests are said to have passed, so in Go, if you don’t call any method t.Fail() or t.Error() or Errorf() to format the error, if none of these functions are invoked, the tests will pass.

If you prefer to use an assertion line of reasoning, there is a package called testify, which provides helper functions validations, and comparisons.

How to run tests in Golang?

The $go test tool checks all files ending with _test.go for test functions, generates a temporary core package that uses it properly, runs the tests, reports the results, and then cleans them up, The Go Programming Language, 2016.

$ go test ./...

?   	example.com/test	[no test files]
ok  	example.com/test/math	0.001s

If the tests do not pass, a FAIL message will be displayed, showing the name of the failed test function, and if any message’s error has been implemented will show it, explaining the reasons for the error, will also appear in the output of the stdout. terminal.

$ go test ./...

--- FAIL: TestSum (0.00s)
    sum_test.go:25: Expected that 1+1 is 2, but actual take 4
    sum_test.go:25: Expected that 0+1 is 1, but actual take 3
    sum_test.go:25: Expected that 0+0 is 0, but actual take 2
    sum_test.go:25: Expected that 0+-1 is -1, but actual take 1
    sum_test.go:25: Expected that -1+-1 is -2, but actual take 0
FAIL
FAIL	example.com/test/math	0.001s
FAIL

Conclusions!

Using test tables is more complex than writing multiple test functions to cover possible scenarios, but it reduces the code’s amount.

You don’t need any packages outside the standard library to write tests in Golang, the testing package provides what you need. The testify package can be used in more complex cases, with more validations, and to work better with an error message and log formatting.

References