Updated: 2017-11-27 01:41:46 CST +08

Golang testing and httptest Package

Test Full Command Example

  • Test
go test -run=Prime -v -timeout 100ms -short -parallel 2 cnet/ctcp
  • Coverage
go test -cover -covermode set -coverpkg bufio,net -coverprofile cover.out cnet/ctcp
  • Open a web browser displaying annotated source code by coverage profile
go tool cover -html=cover.out

TestMain

func TestMain(m *testing.M)
  • When TestMain function in package, every test will execute TestMain before test running.
  • TestMain could be used to setup something before a testing run and teardown something after testing finish.
    • setup:
    • export environment variable
    • presetting some testing data
      • database
      • session
      • cache
      • etc…
    • teardown:
    • clear data or environment variable produces by testing

Example

func TestMain(m *testing.M) {
    setup()
    v := m.Run() // run testing
    teardown()
    os.Exit(v)
}

func setup() {
    fmt.Println("before testing")
}

func teardown() {
    fmt.Println("after testing")
}

t.Log() and t.Logf()

func TestFunc(t *testing.T) {
    t.Log("Print Something")
    t.Logf("Print %s", str)
}
  • t.Log() and t.Logf() only print when testing is FAIL in normal mode
  • If you wanna print log when testing PASS, use go test -v to print t.Log() and t.Logf()

httptest: End to End HTTP Testing

package net/http/httptest

Package httptest provides utilities for HTTP testing.

Example

main.go

func nameHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "%s", "dinolai")
}

func router() *http.ServeMux {
    h := http.NewServeMux()
    h.HandleFunc("/name", nameHandler)
    return h
}

func main() {
    http.ListenAndServe(":8080", router())
}

main_test.go

  • Testing from handler

    func TestNameHandler(t *testing.T) {
        tests := []struct {
            name string
            want string
        }{
            {"string", "dinolai"},
        }
    
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                req, _ := http.NewRequest("GET", "", nil)
                w := httptest.NewRecorder()
                nameHandler(w, req)
    
                got := w.Body.String()
                if got != tt.want {
                    t.Errorf("Got %s, Want %s", got, tt.want)
                }
            })
        }
    }
    
    
  • Test from Router

    func TestFromRouter(t *testing.T) {
        tests := []struct {
            name string
            uri  string
            want string
        }{
            {"name", "/name", "dinolai"},
        }
    
        ts := httptest.NewServer(router())
        defer ts.Close()
    
        for _, tt := range tests {
            t.Run(tt.name, func(t *testing.T) {
                url := ts.URL + tt.uri
                resp, _ := http.Get(url)
                respBody, _ := ioutil.ReadAll(resp.Body)
                resp.Body.Close()
    
                got := string(respBody)
                if got != tt.want {
                    t.Errorf("Got %s, Want %s", got, tt.want)
                }
            })
        }
    }
    

Ignore File from Test Coverage

Use Build Tag

  • add tags on the top of file, must have the line break between tags and package.

    //+build !test
    
    package main
    
    func main() {
        // codes
    }
    
  • add -tags flag when test with coverage

    $ go test -cover -tags test
    ok      github.com/dinos80152/golang-lab/main    0.142s  coverage: 100% of statements
    

Reference