DEV Community

Serhat Teker
Serhat Teker

Posted on • Originally published at tech.serhatteker.com on

Unit Testing Basics - Go

Go has a built-in testing command go test and a package testing which gives a minimal but complete testing flow.

Function to Test

Below there is an example method we want to test in the main package. We defined an exported function called Sum which takes two integers and adds them together.

// main.go
package main

import "fmt"

func Sum(x, y int) int {
    return x + y
}

func main() {
    sum := Sum(13, 29)
    fmt.Println("Sum is", sum)
}
Enter fullscreen mode Exit fullscreen mode

Test

In Go we write our tests in a separate file. The test file can be in a different package —and folder or in the same one —main. Here's our unit test for main.go:

// main_test.go
package main

import "testing"

func TestSum(t *testing.T) {
    sum := Sum(13, 29)
    if sum != 42 {
        t.Errorf("Sum not correct: got %d, want %d", sum, 42)
    }
}
Enter fullscreen mode Exit fullscreen mode

Main rules of Golang testing:

  • The first and only parameter needs to be t *testing.T
  • It begins with Test followed by a word starting with a capital letter: TestSum
  • Calls t.Error or t.Fail to show a failure
  • Tests must be saved in a file named *_test.go such as: sum_test.go

Run Tests

To run test(s), simply write:

$ go test
PASS
ok      github.com/serhatteker/unit-testing-basics  0.001s
Enter fullscreen mode Exit fullscreen mode

This picks up any files matching *_test.go.

In order to get verbose output use -v flag:

$ go test -v
=== RUN   TestSum
-------- PASS: TestSum (0.00s)
PASS
ok      github.com/serhatteker/unit-testing-basics  0.001s
Enter fullscreen mode Exit fullscreen mode

Table Driven Test

The concept of table driven test is a set —slice array, of test input (got) values and output (wanted) value:

// main_test.go
package main

import "testing"

func TestSum(t *testing.T) {
    tables := []struct {
        x int
        y int
        s int
    }{
        {13, 29, 42},
        {0, 9, 9},
        {1, 2, 3},
        {5, -2, 3},
    }

    for _, table := range tables {
        sum := Sum(table.x, table.y)
        if sum != table.s {
            t.Errorf("Sum of (%d+%d) not correct, got: %d, want: %d.", table.x, table.y, sum, table.s)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Coverage

The go test tool has built-in code coverage. To try it with above example type:

$ go test -cover
PASS
coverage: 33.3% of statements
ok      github.com/serhatteker/unit-testing-basics  0.001s
Enter fullscreen mode Exit fullscreen mode

Html Coverage Report

If you use the below two commands you generate coverage.html report that
visualises which parts of your program covered and not covered by the tests:

$ go test -cover -coverprofile=coverage.out
$ go tool cover -html=coverage.out -o coverage.html
Enter fullscreen mode Exit fullscreen mode

The generated report will be like:

unit testing basics golang

All done!

Discussion (0)