Golang basics - Writing Unit Tests (Part 1)



1. Testing in Go


Go has a built-in testing command called go test and a package testing which combine to give a minimal but complete testing experience.

The standard tool-chain also includes benchmarking and statement-based code coverage similar to NCover (.NET) or Istanbul (Node.js).



1.2 Writing tests


Unit testing in Go is just as opinionated as any other aspect of the language like formatting or naming. The syntax deliberately avoids the use of assertions and leaves the responsibility for checking values and behaviour to the developer.

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

package main

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

func main() {
Sum(5, 5)
}

We then write our test in a separate file. The test file can be in a different package (and folder) or the same one (main). Here's a unit test to check addition:

package main

import "testing"

func TestSum(t *testing.T) {
total := Sum(5, 5)
if total != 10 {
t.Errorf("Sum was incorrect, got: %d, want: %d.", total, 10)
}
}



Characteristics of a Golang test function:

  • The first and only parameter needs to be t *testing.T
  • It begins with the word Test followed by a word or phrase starting with a capital letter.
    • (usually the method under test i.e. TestValidateClient)
  • Calls t.Error or t.Fail to indicate a failure (I called t.Errorf to provide more details)
    • t.Log can be used to provide non-failing debug information
  • Must be saved in a file named something_test.go such as: addition_test.go

If you have code and tests in the same folder then you cannot execute your program with go run *.go. I tend to use go build to create a binary and then I run that.

You may be more used to using the Assert keyword to perform checking, but the authors of The Go Programming Language make some good arguments for Go's style over Assertions.

When using assertions:

  • tests can feel like they're written in a different language (RSpec/Mocha for instance)
  • errors can be cryptic "assert: 0 == 1"
  • pages of stack traces can be generated
  • tests stop executing after the first assert fails - masking patterns of failure

There are third-party libraries that replicate the feel of RSpec or Assert. See also stretchr/testify.

Test tables

The concept of "test tables" is a set (slice array) of test input and output values. Here is an example for the Sum function:

package main

import "testing"

func TestSum(t *testing.T) {
tables := []struct {
x int
y int
n int
}{
{1, 1, 2},
{1, 2, 3},
{2, 2, 4},
{5, 2, 7},
}

for _, table := range tables {
total := Sum(table.x, table.y)
if total != table.n {
t.Errorf("Sum of (%d+%d) was incorrect, got: %d, want: %d.", table.x, table.y, total, table.n)
}
}
}

If you want to trigger the errors to break the test then alter the Sum function to return x * y.

$ go test -v
=== RUN TestSum
--- FAIL: TestSum (0.00s)
table_test.go:19: Sum of (1+1) was incorrect, got: 1, want: 2.
table_test.go:19: Sum of (1+2) was incorrect, got: 2, want: 3.
table_test.go:19: Sum of (5+2) was incorrect, got: 10, want: 7.
FAIL
exit status 1
FAIL github.com/alexellis/t6 0.013s

Share On Facebook ! Tweet This ! Share On Google Plus ! Pin It ! Share On Tumblr ! Share On Reddit ! Share On Linkedin ! Share On StumbleUpon !

0 Response to " Golang basics - Writing Unit Tests (Part 1)"

Posting Komentar