Implementation of unit testing using Go

  • 2020-09-28 08:55:55
  • OfStack

Introduction to the

In daily development, testing is indispensable.

The Go standard library includes a testing framework called testing that can be used for both unit and performance testing.

It is integrated with the command go test.

The test file is named after the suffix _test.go and is usually in the same package as the file under test.

Unit testing

The format of unit tests is as follows:


func TestAbs(t *testing.T) {
 got := Abs(-1)
 if got != 1 {
  t.Errorf("Abs(-1) = %d; want 1", got)
 }
}

Create 1 file es30EN_ES31en.go in util directory, add 1 unit test:


package util

import "testing"

//  Normal test 
func TestGenShortID(t *testing.T) {
 shortID, err := GenShortID()
 if shortID == "" || err != nil {
 t.Error("GenShortID failed")
 }
}

Then, run go ES38en-ES39en./util/ in the root directory. The test results are as follows:


root@592402321ce7:/workspace# go test -v ./util/
=== RUN  TestGenShortID
--- PASS: TestGenShortID (0.00s)
PASS
ok   tzh.com/web/util    0.006s

The performance test

The performance test results are as follows:


func BenchmarkHello(b *testing.B) {
 for i := 0; i < b.N; i++ {
  fmt.Sprintf("hello")
 }
}

Add performance tests in util_test.go:


//  The performance test 
func BenchmarkGenShortID(b *testing.B) {
 for i := 0; i < b.N; i++ {
 GenShortID()
 }
}

The results of the run are as follows (avoid running normal test functions using --run=none, as it is not possible for function names to match none in 1):


root@592402321ce7:/workspace# go test -v -bench="BenchmarkGenShortID$" --run=none ./util/
goos: linux
goarch: amd64
pkg: tzh.com/web/util
BenchmarkGenShortID-2       507237       2352 ns/op
PASS
ok   tzh.com/web/util    1.229s

This means that the average running time of GenShortID() is 2352 nanoseconds.

Performance analysis

When running tests, you can specify 1 parameter to generate the performance file profile.


-blockprofile block.out
  Write a goroutine blocking profile to the specified file
  when all tests are complete.
  Writes test binary as -c would.

-blockprofilerate n
  Control the detail provided in goroutine blocking profiles by
  calling runtime.SetBlockProfileRate with n.
  See 'go doc runtime.SetBlockProfileRate'.
  The profiler aims to sample, on average, one blocking event every
  n nanoseconds the program spends blocked. By default,
  if -test.blockprofile is set without this flag, all blocking events
  are recorded, equivalent to -test.blockprofilerate=1.

-coverprofile cover.out
  Write a coverage profile to the file after all tests have passed.
  Sets -cover.

-cpuprofile cpu.out
  Write a CPU profile to the specified file before exiting.
  Writes test binary as -c would.

-memprofile mem.out
  Write an allocation profile to the file after all tests have passed.
  Writes test binary as -c would.

-memprofilerate n
  Enable more precise (and expensive) memory allocation profiles by
  setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
  To profile all memory allocations, use -test.memprofilerate=1.

-mutexprofile mutex.out
  Write a mutex contention profile to the specified file
  when all tests are complete.
  Writes test binary as -c would.

-mutexprofilefraction n
  Sample 1 in n stack traces of goroutines holding a
  contended mutex.

Use the following command to generate profile for CPU:


go test -v -bench="BenchmarkGenShortID$" --run=none -cpuprofile cpu.out ./util/

Under the current directory, the cpu.out file and util.test file should be generated.

Observe time-consuming operations using the following command:


#  Enter interactive mode 
go tool pprof cpu.out
top

After installing Graphviz, a visual analysis diagram can be generated.


apt install graphviz
go tool pprof -http=":" cpu.out

Test coverage


package util

import "testing"

//  Normal test 
func TestGenShortID(t *testing.T) {
 shortID, err := GenShortID()
 if shortID == "" || err != nil {
 t.Error("GenShortID failed")
 }
}

0

Use the -ES104en = ES105en.out option to count test coverage. Use go tool ES109en-ES110en = ES111en. out to see more detailed test coverage results.
Count the test coverage for each function.

conclusion

Testing is a very important part of development. It is used to ensure the quality of software.

The code for the current section

As version v0.15.0


Related articles: