Files
build-web-application-with-…/en/eBook/11.3.md
2014-05-10 18:05:31 +08:00

164 lines
7.3 KiB
Markdown

# 11.3 Write test cases
Development process in which a very important point is to test, how do we ensure the quality of code, how to ensure that each function is run, the results are correct, and how to ensure that write out the code performance is good, we know that the focus of the unit test program is to find a logic error in design or implementation, the problem early exposure to facilitate the positioning of the problem solved, and performance testing focuses on program design found some problems, so that the program can be online in the case of high concurrency can keep stability. This section will take this series of questions to explain how the Go language to implement unit testing and performance testing.
Go language comes with a lightweight testing framework `testing` and comes with `go test` command to implement unit testing and performance testing, `testing` framework and other similar language testing framework, you can be based on this framework to write test cases for the corresponding function can also be written based on the framework of the corresponding pressure test, then let's look at how to write eleven.
## How to write test cases
Since `go test` command can only be executed under a corresponding directory of all files, so we are going to create a new project directory `gotest`, so that all of our code and test code are in this directory.
Next, we create two files in the directory below: gotest.go and gotest_test.go
1. Gotest.go: The document which we have created a package, which has a function in a division operation:
<pre>package gotest
import (
"errors"
)
func Division(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("Divisor can not be 0")
}
return a / b, nil
}</pre>
2. Gotest_test.go: This is our unit test files, but keep the following principles:
- File names must be `_test.go` end, so in the implementation of `go test` will be executed when the appropriate code
- You have to import `testing` this package
- All test cases functions must be the beginning of `Test`
- Test case will follow the source code written in the order execution
- Test function `TestXxx()` argument is `testing.T`, we can use this type to record errors or test status
- Test format: `func TestXxx(t * testing.T)`, `Xxx` section can be any combination of alphanumeric, but can not be the first letter lowercase letters [az], for example, `Testintdiv` wrong function name.
- Function by calling `testing.T` a `Error`, `Errorf`, `FailNow`, `Fatal`, `FatalIf` method, the test is not passed, calling `Log` test method is used to record the information.
Here is our test code:
package gotest
import (
"testing"
)
func Test_Division_1(t *testing.T) {
// try a unit test on function
if i, e := Division(6, 2); i != 3 || e != nil {
// If it is not as expected, then the error
t.Error("division function tests do not pass ")
} else {
// record some of the information you expect to record
t.Log("first test passed ")
}
}
func Test_Division_2(t *testing.T) {
t.Error("just do not pass")
}
We perform in the project directory `go test`, it will display the following information:
--- FAIL: Test_Division_2 (0.00 seconds)
gotest_test.go: 16: is not passed
FAIL
exit status 1
FAIL gotest 0.013s
From this result shows the test does not pass, because in the second test function we wrote dead do not pass the test code `t.Error`, then our first case of how a function performs like it ? By default, execute `go test` is not displayed test information, we need to bring arguments `go test-v`, this will display the following information:
=== RUN Test_Division_1
--- PASS: Test_Division_1 (0.00 seconds)
gotest_test.go: 11: first test passed
=== RUN Test_Division_2
--- FAIL: Test_Division_2 (0.00 seconds)
gotest_test.go: 16: is not passed
FAIL
exit status 1
FAIL gotest 0.012s
The above output shows in detail the process of this test, we see that the test function 1 `Test_Division_1` test, and the test function 2 `Test_Division_2` test fails, finally concluded that the test is not passed. Next we modified the test function 2 the following code:
func Test_Division_2(t *testing.T) {
// try a unit test on function
if _, e := Division(6, 0); e == nil {
// If it is not as expected, then the error
t.Error("Division did not work as expected.")
} else {
// record some of the information you expect to record
t.Log("one test passed.", e)
}
}
Then we execute `go test-v`, the following information is displayed, the test passes:
=== RUN Test_Division_1
--- PASS: Test_Division_1 (0.00 seconds)
gotest_test.go: 11: first test passed
=== RUN Test_Division_2
--- PASS: Test_Division_2 (0.00 seconds)
gotest_test.go: 20: one test passed. divisor can not be 0
PASS
ok gotest 0.013s
## How to write stress test
Stress testing is used to detect function ( method ) performance, and writing unit functional testing method similar are not mentioned here, but need to pay attention to the following points:
- Pressure test must follow the following format, where XXX can be any combination of alphanumeric, but can not be the first letter lowercase letters
func BenchmarkXXX (b *testing.B){...}
- `Go test` does not default to perform stress tests of function, if you want to perform stress tests need to bring arguments `-test.bench`, syntax: `-test.bench =" test_name_regex "`, such as `go test-test. bench = ". *" ` all of the stress test indicates the test function
- In the pressure test, please remember to use the loop body `testing.BN`, so that the test can be normal operation
- File name must end with `_test.go`
Here we create a stress test file webbench_test.go, the code is as follows:
package gotest
import (
"testing"
)
func Benchmark_Division(b *testing.B) {
for i := 0; i < bN; i++ { // use bN for looping
Division(4, 5)
}
}
func Benchmark_TimeConsumingFunction(b *testing.B) {
b.StopTimer() // call the function to stop the stress test time count
// Do some initialization work, such as reading file data, database connections and the like,
// So we test these times do not affect the performance of the function itself
b.StartTimer() // re- start time
for i := 0; i < b.N; i++ {
Division(4, 5)
}
}
We execute the command `go test-file webbench_test.go-test.bench =". * "`, You can see the following results:
PASS
Benchmark_Division 500000000 7.76 ns/ op
Benchmark_TimeConsumingFunction 500000000 7.80 ns/ op
ok gotest 9.364s
The above results show that we did not perform any `TestXXX` unit test functions, the results show only a function of stress tests carried out, the first show `Benchmark_Division` executed 500 million times the average execution time is 7.76 ns, the second shows the `Benchmark_TimeConsumingFunction` executed 500 million each, the average execution time is 7.80 ns. Finally a show total execution time.
## Summary
On the face of unit testing and stress testing of learning, we can see the `testing` package is very lightweight, and write unit tests and stress test is very simple, with built-in `go test` command can be very convenient for testing, so every time we have finished modifying code, click go test execution can simply complete regression testing.
## Links
- [Directory](preface.md)
- Previous section: [Debugging by using GDB](11.2.md)
- Next section: [Summary](11.4.md)