Go Language Practical Notes (21) | Go Unit Test

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

What is unit testing

Believe that we are programmers, the unit test is not unfamiliar. Unit tests are generally used to test our code logic with no problems and there is no running as we expect to ensure code quality.

Most unit tests are tests of a function method to ensure that no problems or problems can be predicted by us as much as possible. To achieve this, we can use a variety of means, logic, simulation of different scenarios for testing.

Here we package main define a function Add to find the sum of two numbers, and then we use the unit test for the summation logic test.

Main.go

123
func ADD  int) int  {return a+b}

Main_test.go

12345678
func Testadd (t *testing. T)  {sum: = Add (1,2)if3 {t.Log ("The result is OK"Else {t.fatal ("The result is Wrong")}}

Then we can see the test results by running in the project directory of the terminal go test -v .

123456
➜  Test -v=== RUN   testadd---pass:testadd (0.00s)        main_test.go:26:the result is Okpassok      Flysnow.org/hello       0.007s

There are test success pass marks and print out the results we want. More about go test the usage of the previous written go development tool http://www.flysnow.org/2017/03/08/go-in-action-go-tools.html, here do not elaborate.

The go language provides us with a test framework to help us make unit testing easier, but using this framework requires the following rules:

    1. The go file containing the unit test code must _test.go end, and the Go Language test tool will only recognize files that match this rule
    2. The first part of the unit test file name is _test.go preferably the file name of the go file where the method being tested, as in the example main_test.go , because the test Add function, in the main.go file
    3. The function name of the unit test must Test begin with a function that can be exported publicly
    4. The signature of the test function must receive a testing.T pointer to the type and cannot return any values
    5. The function name is best test+ the method function name to be tested, as in the example, this is the TestAdd function that represents the test. Add

Following the above rules, we can easily write unit tests, the focus of unit testing is to test the logic of the code, scenarios, so as to test comprehensively, to ensure the code quality logic.

Table Group Test

There is also a unit test method called a table group test, which is very similar to the basic unit test, except that it is a set of unit tests consisting of several different inputs and outputs.

For example, in the last example, we tested 1+2 , if we add 3+4 , and so on 9+2 , there are several inputs, and there are several output, this one-time test many of the input and output scenarios of the test, is the table group test.

123456789101112131415
func Testadd (t *testing. T)  {sum: = Add (1,2)if3 {t.Log ("The result is OK"Else {t.fatal ("The result is wrong")}sum=add (3,4)if7 {T. Log ("The result is OK"orelse {t.fatal ("Theresult is wrong")}}

Impersonation Call

Unit testing is the principle of the function you are testing, not affected by the environment, such as network access, because sometimes when we run unit testing, and there is no network, then can not let the unit test because of this failure? So it is necessary to simulate network access at this time.

For analog network access, the standard library provides a httptest package that allows us to simulate the network invocation of HTTP, as an example of how to use it.

First we create a function to process the HTTP request and register the route

 12345678910111213141516171819202122 
package  commonimport  ( "Net/http"   "Encoding/json" ) func  Span class= "title" >routes   ()   {http. Handlefunc ( "/sendjson" , Sendjson)}func  sendjson   (rw http. Responsewriter,r *http. Request)   {u: = struct  {Name string }{name:< Span class= "string" > "Zhang San" ,}RW. Header (). Set ( "Content-type" , ) rw. Writeheader (http. Statusok) JSON. Newencoder (rw). Encode (U)} 

The

is very simple, here is a /sendjson API, and when we access this API, we return a JSON string. Now we're testing this API service, but we can't start the service all the time, so we're going to use the external terminal's network access request to the API.

 1234567891011121314151617 
 func  init  Span class= "params" > ()   {Common. Routes ()}func  testsendjson   (t *testing. T)   {req,err:=http. Newrequest (http. Methodget, "/sendjson" , nil ) if  err!=nil  {t.fatal ()}rw:=httptest. Newrecorder () http. Defaultservemux.servehttp (rw,req) log. Println ( "code:" , RW. Code) log. Println (, RW. Body.string ())} 

Running this unit test, you can see the results of our access to the /sendjson API, and we did not start any HTTP service to achieve the goal. The main use of this is httptest.NewRecorder() to create a response http.ResponseWriter that simulates the real service side, which is triggered by the calling http.DefaultServeMux.ServeHTTP method.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

There is also a way to simulate a call, which is to actually impersonate a server on the test machine and then make the call test.

1234567891011121314151617181920212223242526272829303132333435
 func mockserver() *httptest. Server {//api Call handler functionSendjson: = func(rw http. Responsewriter, R *http. Request) {u: =struct{Namestring}{name:"Zhang San",}RW. Header (). Set ("Content-type","Application/json") RW. Writeheader (http. Statusok) JSON. Newencoder (rw). Encode (U)}//Adapter ConversionreturnHttptest. NewServer (http. Handlerfunc (Sendjson))} func testsendjson(t *testing. T) {//Create a simulated serverServer: = Mockserver ()deferServer. Close ()//get the address of the request destined to the analog serverResq, Err: = http. Get (server. URL)ifErr! =Nil{T.fatal ("Create get Failed")}deferResq. Body.close () log. Println ("Code:", Resq. StatusCode) JSON, err: = Ioutil. ReadAll (Resq. Body)ifErr! =Nil{log. Fatal (Err)}log. Printf ("body:%s\n", JSON)}

The simulation server is created using a httptest.NewServer function that receives an http.Handler interface that processes API requests.
The code example uses the hander adapter pattern, http.HandlerFunc is a function type, implements the http.Handler interface, here is the coercion type conversion, is not a function call, more information about this adapter, you can refer to a previous article I wrote: interface type function,/HTTP Www.flysnow.org/2016/12/30/golang-function-interface.html.

This creates the analog server, listens to the native IP 127.0.0.1 , the port is random. Then we send a GET request, no longer sent /sendjson to, but to simulate the server's address server.URL , the rest is the same as the access to the normal URL, print out the results.

Test coverage

We try to simulate more scenarios to test the different situations of our code, but sometimes we do have the code to forget the test, and we need to test coverage as a reference.

The code of the Unit test, which triggers the number of lines of code in the code to be run to, is called test coverage, and code coverage is not necessarily exact, but can be used as a reference to help us measure the gap between our projected coverage, go test tools, Provides us with the ability to measure test coverage.

Main.go

12345678910111213
func Tag  int)  {Switch tag {case1: FMT. Println ("Android")case2: FMT. Println ("Go")case3: FMT. Println ("Java")default: FMT. Println ("C")}}

Main_test.go

12345
func Testtag (t *testing. T)  {tag (1) tag (2)}

Now we use the go test tool to run unit tests, unlike the previous few times, we want to show the test coverage, so we need to add a parameter -coverprofile , so the complete command go test -v -coverprofile=c.out is:, is the -coverprofile specified generated coverage file, in the example c.out , We'll use this file in a minute. Now we look at the terminal output, which already has a coverage.

1234567
= = = RUN   testtagandroidgo---pass:testtag (0.00s) passcoverage:60.0% of Statementsok      Flysnow.org/hello       0.005s

coverage: 60.0% of statements, 60% of the test coverage is not yet up to 100%, so let's see if the code has not been tested. This requires that the test coverage file we just generated c.out generate a test coverage report. The build report has the tools that go provides for us, and we go tool cover -html=c.out -o=tag.html can generate a tag.html test coverage report with the name of the HTML format, with detailed information that tells us which line of code was tested and which line of code was not tested.

As you can see, the lines of code marked green have been tested, the red ones have not been tested, there are 2 rows, and now we can refine my unit test code based on the code logic that is not tested.

1234567
func Testtag (t *testing. T)  {tag (1) tag (2) tag (3) tag (6)}

Unit test perfect as above code, and then run the unit test, you can see the test coverage is already 100%, done.

"Go language Combat" reading notes, not to be continued, welcome to sweep code attention flysnow_org to the public or website http://www.flysnow.org/, the first time to see follow-up notes. If you feel helpful, share it with your friends and thank you for your support.

Related Article

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.