Golang — basic unit testing and benchmarking

yoshie
2 min readMar 28, 2022

Testing Package

Golang is well known for writing unit tests easily. It all thanks to the built-in package testing : https://pkg.go.dev/testing. In this package, we can write simple unit tests and benchmarks to not only keep the source code bug free but also monitor the performance.

Unit tests

File location

There’s a conventional pattern for the unit tests to behave. We usually have the test file sitting exactly the same directory as the source code lives. For example:

|____pbkdf2.go
|____pbkdf2_test.go

where pbkdf2_test.go will contain all the test cases that test functions in pbkdf2.go.

Package name

Although the test file lives in the same directory as the source code, we usually name the package differently. For example,

|____key
| |____pbkdf2_test.go
| |____pbkdf2.go

The package name of pbkdf2.go is package key , but the package name of pbkdf2_test.go we do package key_test.

Function definition

The function follows the naming pattern Test<source func name> (t *testing.T). For example, write

func TestPbkdf2(t *testing.T) {
...
key, err := Pbkdf2(...)
require.noErr(err)
...
}

if you have a source function called Pbkdf2. Use Assert or require package to make sure the test result is what you want.

**Noted that you can only test on exposed functions, because even if you use the same package name key for the test file, internally Golang still treat it as in a different package. You can not call function outside of the package if the function is not exposed.

Command

go test ./... or go test -run TestPbkdf2.

Benchmarks

Many of people know Golang unit testing, but few of them know Golang benchmarking. It’s also a built-in tool to help you monitor the source function performance.

Function location

benchmark functions lives in the same function pbkdf2_testing.go.

Example

func BenchmarkPbkdf2(b *testing.B) {
client := key.NewPbkdf2Client()
for n := 0; n < b.N; n++ {
client.GenerateKey([]byte("password"), 32)
}
}

We are using *testing.B here instead of *testing.T. It’s simple compared to unit testing, where you have to go through the function logic and verify your output result for a given scenario.

For benchmarking you only have to run the same function b.N times to get the average performance. According to the official package,

During benchmark execution, b.N is adjusted until the benchmark function lasts long enough to be timed reliably.

Command

Run

go test -bench . , and you will see output like this:

go test -bench .
goos: darwin
goarch: amd64
pkg: github.com/crypto-ys/key
cpu: Intel(R) Core(TM) i5-5250U CPU @ 1.60GHz
BenchmarkPbkdf2-4 829 1417222 ns/op
PASS
ok github.com/crypto-ys/key 1.624s

which means the function GenerateKey() takes about 1.41ms for each run.

Conclusion

This is just a simple introduction to get you started and make sure you follow all the conventions. There are many more advanced skills for you to explore and improve your application!

--

--

yoshie

A software engineer that plays yu-gi-oh. Main focus: Golang/AWS/Leetcode