Chapter 11 Unit Testing
- There are two effective ways to make software complexity manageable:
- Code needs to undergo a code review before it can be officially deployed
- automated test
- The testing techniques of the Go language are relatively low-level. It relies on a
go test
test command and a set of test functions written in a conventional way, and the test command can run these test functions
11.1go test
focus
go test
A command is a driver that tests code according to a certain convention and organization. Inside the package directory, all source files_test.go
with a suffix that are notgo build
part of the build package, they arego test
part of the tests.- In the *_test.go file, there are three types of functions:Test functions, benchmark functions, example functions。
- The test function isTestThe function prefixed with the function name is used to test whether some logical behavior of the program is correct;
go test
the command will call these test functions and report the test result asPASS
orFAIL
. - The benchmark function is based onBenchmarkFunctions prefixed with function names, which are used to measure the performance of some functions;
go test
the command will run the benchmark function multiple times to calculate an average execution time - Example function isTake ExampleFor functions prefixed with the function name, provide an example document whose correctness is guaranteed by the compiler
go test
The command will traverse the functions in all*_test.go
files that meet the above naming rules, and then generate a temporarymain
package to call the corresponding test function, then build and run, report the test results, and finally clean up the temporary files generated in the test.
11.2 Test functions
focus
- Every test function must import the testing package. The test function has the following signature:
func TestName(t *testing.T) {
// ...
}
- The name of the test function must start with Test, and the optional suffixMust start with a capital letter, where the t parameter is used to report test failures and additional log information:
func TestSin(t *testing.T) { /* ... */ }
func TestCos(t *testing.T) { /* ... */ }
func TestLog(t *testing.T) { /* ... */ }
go test
If the command does not specify a package with parameters, it will default to the package corresponding to the current directory (same asgo build
the command )go test -v
, the parameter-v
can be used to print the name and running time of each test functiongo test -run
, the parameter-run
corresponds to a regular expression, only the test function whose test function name is correctly matched by it willgo test
be run by the test command- The output of a failed test does not include
t.Errorf
the stack call information at the time of the call. Unlike assertions in other programming languages or testing frameworksassert
,t.Errorf
calls do not causepanic
exceptions or halt test execution - Can use
t.Fatal
ort.Fatalf
stop the current test function.goroutine
They must be called within the same test function
Common libraries and methods
(*testing.T).Error
(*testing.T).Errorf
11.2.1 Random testing
focus
- Random testing is to test the behavior of the exploration function by constructing a wider range of random inputs
- Two processing strategies help achieve the desired results:
- The first is to write another comparison function
- The second is to generate random input data that follows a specific pattern,
Common libraries and methods
time.Now().UTC().UnixNano()
rand.New(rand.NewSource(seed))
(*testing.T).Logf
11.2.2 Testing a command
focus
go test
Can be used to test executable programs, sincemain
the package can be imported as a package by the tester code. Note that the test code and production code are in the same package at this time.- For
main
packages, there are also correspondingmain
entry functions, but during testing,main
the package is justTestEcho
an ordinary package imported by the test function, andmain
the functions inside are not exported, but ignored.
11.2.3 White-box testing
focus
- Black-box testing only needs to test the documents and API behaviors exposed by the package, and the internal implementation is transparent to the test code
- White box testing (clear box) has access to the internal functions and data structures of the package
- Processing mode can be used to temporarily save and restore all global variables, including command-line flag parameters, debugging options, and optimization parameters; install and remove hook functions that cause production code to generate some debugging information; and some induce production code into certain Important state changes, such as timeouts, errors, and even some deliberately manufactured concurrent behaviors.
go test
The command does not execute multiple tests concurrently
Common libraries and methods
smtp.PlainAuth
smtp.SendMail
11.2.4 Extended test package
focus
- The problem of circular dependency can be solved by testing the extension package
- The extended test package can write tests more flexibly, especially integration tests (need to test the interaction between multiple components)
go list
command to view which Go source files in the corresponding directory of the package are product codes, which are in-package tests, and which test extension packages. Let's takefmt
the package as an example:GoFiles
Indicates the list of Go source files corresponding to the product code; that is,go build
the part of the command to be compiledTestGoFiles
Indicates the internal test code of the fmt package,_test.go
with the suffix file name- XTestGoFiles represents the test code belonging to the test extension package, that is, the fmt_test package
$ go list -f={
{.GoFiles}} fmt
[doc.go format.go print.go scan.go]
-----------------------------------
$ go list -f={
{.TestGoFiles}} fmt
[export_test.go]
-----------------------------------
$ go list -f={
{.XTestGoFiles}} fmt
[fmt_test.go scan_test.go stringer_test.go]
11.2.5 Writing Effective Tests
focus
- The test not only reports the specific function called, the meaning of its inputs and results; it also prints the actual returned value and the expected return value; and even if the assertion fails, it will continue to try to run more tests.
11.2.6 Unstable tests to avoid
focus
11.3 Test coverage
focus
- The number of codes of the tested function triggered by the test driver is called the test coverage
- Statement coverage refers to the proportion of the code that is run at least once in the test to the total number of codes.
go test
The test coverage tool integrated in the command can be used to measure the test coverage of the code and help us identify the gap between the test and our expectations.go tool cover
Show how to use coverage.go tool
command to run the underlying executable of the Go toolchain. These low-level executable programs are placed in$GOROOT/pkg/tool/${GOOS}_${GOARCH}
directories.go test -run=Coverage -coverprofile=c.out gopl.io/ch7/eval
go test -cover
generate summary-covermode=count
flag parameter, a counter will be inserted into each code block instead of a boolean flag. The number of executions of each block is recorded in the statistical results, which can be used to measure which hot codes are frequently executed.$ go tool cover -html=c.out
Printed the test log and generated an HTML report
11.4 Benchmarking
focus
- Benchmark test functions are written similarly to normal test functions, but with a
Benchmark为
prefix name and a*testing.B
parameter of a type;*testing.B
the parameter provides methods*testing.T
similar to and also have some additional methods related to performance measurement. It also provides an integerN
specifying the number of times the operation will perform the loop. - By default no benchmarks are run.
We need to manually specify the benchmark function to run via-bench
command line flags. This parameter is a regular expression used to match the name of the benchmark function to be executed, and the default value is empty. where“.”
the pattern will match all benchmark functions.go test -bench=.
-benchmem
The command line flag argument will include memory allocation statistics in the report
11.5 Anatomy
focus
- The CPU profiling file identifies the CPU time required for function execution. The currently running system thread will encounter an interruption event of the operating system every few milliseconds, and will record an analysis file every time it is interrupted and then resume normal operation.
- Heap analysis records the memory usage of the program. Each memory allocation operation will trigger the internal average memory allocation routine, and each 512KB memory request will trigger an event.
- Blocking analysis records the largest blocking operations of goroutines, such as system calls, pipeline sending and receiving, and acquiring locks. The analysis library will record the relevant operations of each goroutine when it is blocked.
$ go test -cpuprofile=cpu.out $ go test -blockprofile=block.out $ go test -memprofile=mem.out $ go tool pprof
- Benchmarks will include unit tests by default, here we use
-run=NONE
parameters to disable unit tests. (This part needs to refer to the introduction of the original text)
11.6 Example functions
focus
- Example functions have no function parameters and no return value.
- The Example function will be part of the package documentation.
- The example function serves three purposes:
- The main one is as documentation.
go test
The example function tests are also run when the tests are executed . The test results are// Output:
compared with the comments in the format inside the function to check if the results match.- Provide a realistic playing field.
I will not take notes for the next two sections, and ordinary Go programmers will not be able to use them for the time being.