Standard package for Go unit testing: package testing
Package testing has in standard library since 2009. Convention of writing unit test in Go lang is: In file foo.go
, will have file foo_test.go
in same directory/folder. In file foo.go
has method BlaBla()
, and in foo_test.go
has method TestBlaBla()
accordingly.
I have file div.go
has content
package table import ( "errors" "fmt"
) func Divide(x, y int8) (*string, error) { if y == 0 { return nil, errors.New("cannot divide by 0") } r := float64(x) / float64(y) result := fmt.Sprintf("%.2f", r) return &result, nil
}
For unit testing, has file div_test.go
has content
package table_test import ( "errors" "testing" "github.com/donhuvy/Test-Driven-Development-in-Go/chapter04/table" "github.com/stretchr/testify/assert"
) func TestDivide(t *testing.T) { tests := map[string]struct { x, y int wantErr error want string }{ "pos x, pos y": {x: 8, y: 4, want: "2.00"}, "neg x, neg y": {x: -4, y: -8, want: "0.50"}, "equal x, y": {x: 4, y: 4, want: "1.00"}, "max x, pos y": {x: 127, y: 2, want: "63.50"}, "min x, pos y": {x: -128, y: 2, want: "-64.00"}, "zero x, pos y": {x: 0, y: 2, want: "0.00"}, "pos x, zero y": {x: 10, y: 0, wantErr: errors.New("cannot divide by 0")}, "zero x, zero y": {x: 0, y: 0, wantErr: errors.New("cannot divide by 0")}, "max x, max y": {x: 127, y: 127, want: "1.00"}, "min x, min y": {x: -128, y: -128, want: "1.00"}, } for name, rtc := range tests { tc := rtc t.Run(name, func(t *testing.T) { t.Parallel() x, y := int8(tc.x), int8(tc.y) r, err := table.Divide(x, y) if tc.wantErr != nil { assert.Equal(t, tc.wantErr, err) return } assert.Nil(t, err) assert.Equal(t, tc.want, *r) }) }
}
In this example, I used only Go standard library (supported by package testing
).
Run unit testing with verbose information
Command for unit test running
firerose@firerose-desktop:~/Documents/github/Test-Driven-Development-in-Go$ go test -run TestDivide ./chapter04/table/ -v
Result
--- PASS: TestDivide/max_x,_pos_y (0.00s) --- PASS: TestDivide/pos_x,_pos_y (0.00s) --- PASS: TestDivide/pos_x,_zero_y (0.00s) --- PASS: TestDivide/zero_x,_zero_y (0.00s) --- PASS: TestDivide/zero_x,_pos_y (0.00s) --- PASS: TestDivide/max_x,_max_y (0.00s) --- PASS: TestDivide/neg_x,_neg_y (0.00s) --- PASS: TestDivide/equal_x,_y (0.00s)
PASS
ok github.com/donhuvy/Test-Driven-Development-in-Go/chapter04/table 0.002s
*testing.Parallel()
create parallel flows for unit testing in concurrency.
Third-party library support Go lang unit testing
With supporting from package github.com/strectchr/testify
, *assert.Nil()
for assertion Nil
value. *assert.Equal()
for assertion of equalitation.
assert.Equal
receive 3 parameters likes this, one and first parameter is *testing
, 2 next parameters are variable and value of variable:
assert.Equal(t, tc.wantErr, err)
assert.Nil()
receive 2 parameters likes this
assert.Nil(t, err)
Third-party libraries support Go lang unit testing
- Testify: https://github.com/stretchr/testify (as mentioned above)
- Mockery https://github.com/vektra/mockery Generate skeleton/simple source code for Go lang unit testing. On top of generated files, has comment header
// Code generated by mockery v2.26.1. DO NOT EDIT.
In source code, you don't see declaring mockery in go.mod
, it is tool installed to host machine.
Comand set Go to path
firerose@firerose-desktop:~/Downloads/go/bin$ pwd
/home/firerose/Downloads/go/bin
firerose@firerose-desktop:~/Downloads/go/bin$ export PATH=/home/firerose/Downloads/go/bin:$PATH
firerose@firerose-desktop:~/Downloads/go/bin$ echo $PATH
/home/firerose/Downloads/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
firerose@firerose-desktop:~/Downloads/go/bin$ go version
go version go1.20.4 linux/amd64
firerose@firerose-desktop:~/Downloads/go/bin$
Install Mockery by command
go install github.com/vektra/mockery/v2@v2.26.1