This is a creation in Article, where the information may have evolved or changed.
Objective
Using the Go Test framework, and then think of JUnit, although already Junit5, the ugly degree is still.
Java out of time, there is not a lot of software engineering concept, language first out, so need to through different plug-ins slowly fill.
Go is very fortunate, out of time a lot of software engineering concept has been basically set down, can be added to the language features, go test is a lot easier, is worthy of the engineering of the language
Programs that need to be tested
We need to test the program file is called utils.go
, there is a method of string inversion Reverse
, the code is relatively simple, here do not repeat the
funcstringstring { r := []rune(s) for i, j := 0len(r)-1len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } returnstring(r)}
Unit Test
Go testing package can be based on the package into the test, meaning that the go test
default unit is the package scope, go test
can automatically execute the current package under all the func TestXxx(*testing.T)
format of the test method, XXX can be any letter, but the best and you need to test method one by one corresponding.
Create a new test file, _test.go
as the end of the file name, the best and need to test the file one by one corresponding, you can at a glance, these test files will not be packaged in the program to the final execution of files or libraries.
We create a new utlis_test.go
file:
func testreverse (t *testing. T) {if testing. Short () {T.skip () } cases: = []struct {in, want string } { { "Hello, World" , "Dlrow, Olleh" }, { "Hello, World" , "world, Olleh" }, { "" , },} for _, c: = range cases {got: = Reverse (c.in) if got! = c.want { T.errorf ( "Reverse (%q) = =%q, want%q" , c.in, got, C.want)}}}
The first if indicates that if there are -short
parameters, the test will be skipped, the following code is relatively easy to understand, judging the output input is consistent, the above test method go test
can be directly run by the command
Sample validation
Another way to test it is to use the sample validator, to do an example in the go language is very simple, say goodbye to write a sample program has to write a lot of main methods of the Times, the format to start with example, the execution go test
of the time will automatically execute these examples, to note that, After example, you need to follow the defined variables, otherwise you vet
will get an error.
It is also important to note that auto trim is ignored, and the space comparison before and after is omitted.
func ExampleReverse() { fmt.Println(Reverse("Hello, 世界")) // Output: 界世 ,olleH}
You can verify that the output is consistent with what you want, and in some cases, such as multi-threaded, the output order is random, which is also considered by go,
func ExampleReverse() { fmt.Println(Reverse("Hello, world")) fmt.Println(Reverse("Hello, 世界")) // Unordered Output: 界世 ,olleH // dlrow ,olleH // AA}
Used Unordered Output
to represent unordered output
Benchmark Test
Benchmark test to Benchmark
prefix, must be executed b.N
once, such a test is a control, b.N
the value is the system according to the actual situation to adjust, so as to ensure the stability of the test.
b.ResetTimer()
The previous processing will not be placed in the execution time and will not be output to the report, so you can do some things that are not planned as test reports before
The benchmark is not executed by default, and he needs to add -bench
parameters such asgo test -bench .
func BenchmarkReverse(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { Reverse("s string") }}
Benchmarks can also turn on parallel testing, which requires the execution of b.RunParallel(func(pb *testing.PB)
methods, which by default will be tested in parallel with the number of logical CPUs.
Personal opinion only write parallel test is OK, if you want to non-parallel can specify the number of CPUs is 1, for examplego test -bench . -cpu 1
func BenchmarkReverseParallel(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { Reverse("s string") } })}
Sub-test and sub-benchmark test
You can also T
B
turn on sub-tests and sub-benchmarks with the Run method, which can be managed by sharing common settings and resource cleanup.
Each sub-test has a unique name, separated by a parent test, that /
uniquely represents it, and when it runs, it uses the -run regexp
specified test and -bench regexp
specifies the benchmark to .
represent all.
Another feature is that all sub-tests are completed, the parent test is complete, and all the tests are parallel, so that you can put together some actions that need to be done synchronously for group testing.
func TestTeardownParallel(t *testing.T) { // This Run will not return until the parallel tests finish. t.Run("group"func(t *testing.T) { t.Run("Test1", parallelTest1) t.Run("Test2", parallelTest2) t.Run("Test3", parallelTest3) }) // <tear-down code>}
Main test
There is also a place to do some initialization is the main test, the code is relatively simple.
Note that the Testmain is run in the main coprocessor and m.Run()
will not be executed until the runtime is started.
func TestMain(m *testing.M) { fmt.Println("init") os.Exit(m.Run())}
With the jsoniter of the drip.
Are you going to cheat on the benchmark for KPI testing?
It's important to be able to write benchmark tests, not to be lame.
Come and see my benchmark test.
typeColorgroupstruct{IDintNamestringColors []string}varGroup = colorgroup{ID:1, Name:"Reds", Colors: []string{"Crimson","Red","Ruby","Maroon"},}funcBenchmarkstdjson (b *testing. B) {B.runparallel (func(Pb *testing. PB) { forPb. Next () {b, err: = json. Marshal (Group)ifErr! =Nil{FMT. Println (b)}})}funcBenchmarkiterjson (b *testing. B) {B.runparallel (func(Pb *testing. PB) { forPb. Next () {b, err: = Jsoniter. Marshal (Group)ifErr! =Nil{FMT. Println (b)}})}
Test results: