Golang unit Testing and performance testing

Source: Internet
Author: User
Tags how to write test cases lowercase

The important point of the development program is the test, how we guarantee the quality of the code, how to ensure that each function is operational, the result is correct, and how to ensure that the written code performance is good, we know that the focus of unit testing is to find the design or implementation of logic errors, so that the problem early exposure, Easy to solve the problem, and the focus of performance testing is to find some programming problems, so that the online program can be high concurrency in the case can remain stable. This section will take this series of questions to explain how to implement unit and performance testing in the Go language.

The go language comes with a lightweight test framework testing and its own go test commands for unit testing and performance testing, and the testing framework is similar to a test framework in other languages, where you can write test cases for corresponding functions based on this framework. You can also write the appropriate stress test cases based on the framework, so let's take a look at how to write hit. How to write test cases

Since the Go Test command can only execute all the files in one of the corresponding directories, we will then create a new project directory Gotest so that all our code and test code are in this directory.

Next we create two files under this directory: Gotest.go and Gotest_test.go

Gotest.go: In this file we create a package with a function that divides the operation:

Package gotest

Import (
    "errors"
)

func Division (A, B float64) (float64, error) {
    if b = = 0 {
        Retu RN 0, errors. New ("Divisor cannot be 0")
    }

    return a/b, nil
}

Gotest_test.go: This is our unit test file, but keep in mind the following principles: The file name must be _test.go end, so that when the go test is executed to the corresponding code you must import testing this package All of the test case functions must be test-first tests are executed in the order in which they were written in the source code. The parameter of the test function testxxx () is testing. T, we can use this type to log errors or test the status Test format: Func testxxx (t *testing. T), the xxx section can be any combination of alphanumeric, but the first letter cannot be a lowercase letter [a-z], for example testintdiv is the wrong function name. function, by calling testing. T's error, Errorf, Failnow, Fatal, Fatalif method, indicates that the test does not pass, and calls the log method to log the information of the test.

Here is the code for our test case:

Package gotest

Import (
    "testing"
)

func test_division_1 (t *testing. T) {
    If I, E: = Division (6, 2); I! = 3 | | E! = NIL {//try A unit test on function
        t.error ("Division function test Failed")//if not as expected The error
    } else {
        t.Log ("first Test Passed")//record some information you expect to record
    }
}

func test_division_2 (t *testing. T) {
    t.error ("Just don't Pass")
}

We execute go test below the project directory and the following information is displayed:

---fail:test_division_2 (0.00 seconds)
    Gotest_test.go:16: does not pass
fail
exit status 1
fail    gotest  0.013s

From this result it is shown that the test did not pass, because in the second Test function we wrote dead the code T passed by the test. Error, what happens to our first function execution? By default, go test does not display the information passed by the tests, we need to bring the parameter Go test-v, which will display the following information:

= = = Run Test_division_1
---pass:test_division_1 (0.00 seconds)
    Gotest_test.go:11: The first test passed the
= = = Run Test_ Division_2
---fail:test_division_2 (0.00 seconds)
    Gotest_test.go:16: does not pass
fail
exit status 1
FAIL    gotest  0.012s

The above output shows the process of this test in detail, we see the test function 1test_division_1 test pass, and the test function 2test_division_2 test failed, and finally concluded that the test does not pass. Next we change the test function 2 to the following code:

Func test_division_2 (t *testing. T) {
    If _, E: = Division (6, 0), E = = Nil {//try A unit test on function
        t.error ("Division do not work as Expecte D. ") If not as expected then error
    } else {
        t.Log ("one Test passed.", e)//record some information you wish to record
    }
}   

Then we execute Go test-v, the following information is displayed, the test passed:

= = = Run Test_division_1
---pass:test_division_1 (0.00 seconds)
    Gotest_test.go:11: The first test passed the
= = = Run Test_ Division_2
---pass:test_division_2 (0.00 seconds)
    Gotest_test.go:20:one Test passed. Divisor cannot be 0
PASS
OK      gotest  0.013s
How to write a stress test

Stress tests are used to detect the performance of functions (methods), similar to the method of writing unit functional tests, which are not mentioned here, but note the following points:

The stress test case must follow the following format, where xxx can be a combination of any alphanumeric, but the first letter cannot be a lowercase letter

Func benchmarkxxx (b *testing. B) {...}

Go test does not perform the stress test function by default, if you want to perform a stress test with parameter-test.bench, syntax:-test.bench= "Test_name_regex", such as Go test-test.bench= ". *" Means testing all the stress test functions in the stress test case, remember to use testing in the loop body. B.N to allow the test to run correctly the file name must also end with _test.go

Here we create a new stress test file, Webbench_test.go, as shown below:

Package gotest

Import (
    "testing"
)

func benchmark_division (b *testing. B) {
    for I: = 0; i < B.N; i++ {//use B.N for looping 
        Division (4, 5)
    }
}

func Benchmark_timeconsumi Ngfunction (b *testing. b) {
    b.stoptimer ()//Call this function to stop the time count of the stress test

    //Do some initialization work, such as reading the file data, database connection and so on,
    //so that these times do not affect the performance of our test function

    b . Starttimer ()//Restart time for
    I: = 0; i < B.N; i++ {
        Division (4, 5)}
}

We execute the command go test-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 the pressure test function, the first shows that the benchmark_division executed 500 million times, The average execution time for each time is 7.76 nanoseconds, and the second shows that the benchmark_timeconsumingfunction executes 500000000, and the average execution time for each time is 7.80 nanoseconds. The last bar shows the total execution time.

We execute the command go test-test.bench= ". *"-count=5, you can see the following results: (using-count can specify how many times to execute)

PASS
benchmark_division-2                 300000000             4.60 ns/op
benchmark_division-2                 300000000             4.57 ns/op
benchmark_division-2                 300000000             4.63 ns/op
benchmark_division-2                 300000000             4.60 ns/op
benchmark_division-2                 300000000             4.63 ns/op
benchmark_timeconsumingfunction-2    300000000             4.64 ns/op
Benchmark_timeconsumingfunction-2    300000000             4.61 ns/op
benchmark_timeconsumingfunction-2    300000000             4.60 ns/op
benchmark_timeconsumingfunction-2    300000000             4.59 ns/op
Benchmark_ TimeConsumingFunction-2    300000000             4.60 ns/op
OK      _/home/diego/gowork/src/app/testing    18.546s

Go test-run= file name-bench=bench name-cpuprofile= production cprofile file name folder

Example:

There is a popcnt folder under Testbenchmark, and there are files in popcnt popcunt_test.go

➜  testbenchmark ls
popcnt

Popcunt_test.go's Asking price content:

Ackage popcnt

Import (
    "testing"
)

Const M1 = 0x5555555555555555
const m2 = 0x3333333333333333
Const M4 = 0x0f0f0f0f0f0f0f0f
Const H01 = 0x0101010101010101

func popcnt (x UInt64) UInt64 {
    X-= (x >& Gt 1) & m1
    x = (x & m2) + ((x >> 2) & m2)
    x = (x + (x >> 4)) & M4
    return (x * h01) >>
benchmarkpopcnt}

func (b *testing.  B) {for
    I: = 0; i < B.N; i++ {
        x: = i
        X-= (x >> 1) & m1
        x = (x & m2) + ((x >> 2) & m2)
        x = (x + (x >> 4)) & M4
        _ = (x * h01) >> (+)}
}

Then run go test-bench= ". *"-cpuprofile=cpu.profile./popcnt

➜  Testbenchmark Go test-bench= ". *"-cpuprofile=cpu.profile./popcnt testing:warning:no
tests to run
pass< C3/>benchmarkpopcnt-8    1000000000             2.01 ns/op
OK      app/testbenchmark/popcnt    2.219s
➜  Testbenchmark ll Total
6704
drwxr-xr-x  5 Diego  5  6 13:57.
Drwxr-xr-x  3 Diego  staff      102  5  6 11:12.
-rw-r--r--  1 Diego  staff     5200  5  6 13:57 cpu.profile
drwxr-xr-x  4 Diego  Staff      136  5  6 11:47 popcnt
-rwxr-xr-x  1 Diego  staff  3424176  5  6 13:57 Popcnt.test
➜  Testbenchmark

Production Cpu.profile asking price and Popcnt.test file

➜  testbenchmark ll Total
6704
drwxr-xr-x  5 Diego  5  6 13:57.
Drwxr-xr-x  3 Diego  staff      102  5  6 11:12.
-rw-r--r--  1 Diego  staff     5200  5  6 13:57 cpu.profile
drwxr-xr-x  3 Diego  Staff      102  5  6 14:01 popcnt
-rwxr-xr-x  1 Diego  staff  3424176  5  6 13:57 Popcnt.test
➜  Testbenchmark
Go tool pprof popcnt.test cpu.profile Enter interactive mode
➜testbenchmark Go tool pprof popcnt.test cpu.profile Entering Interactive mode (type ' help ' for Commands) (PPROF) Top 1 880ms of 1880ms Total (100%) flat flat% sum% cum cum% 1790ms 95.21% 95.21% 1790ms 95.21% app/ Testbenchmark/popcnt. benchmarkpopcnt 90ms 4.79% 100% 90ms 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.