Golang Go语言 test 常见套路(2)

Golang Go语言 test 常见套路(2)

上回聊到,golang 里面写一个简单的测试函数,和 benchmark 函数,如何检测测试代码覆盖度。 这回聊下如何编写 http server 测试代码。如果写过 API 服务的童鞋都知道。 测试服务端代码要先起个服务,再运行客户端代码。有没有办法和 go test 方法结合再一起,可以很快乐的编写服务端测试代码呢?

标准库服务端测试代码

package main

import ( “fmt” “io/ioutil” “log” “net/http” “net/http/httptest” )

func main() { // 启动一个测试服务 ts := httptest.NewServer( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, “Hello, client”) })) defer ts.Close()

// 关键一步, 客户端完全使用标准套路,注意:url 使用 ts.URL 就行
res, err := http.Get(ts.URL)
if err != nil {
    log.Fatal(err)
}   
greeting, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
    log.Fatal(err)
}   

fmt.Printf("%s", greeting)

}

gin 框架测试代码

func TestShouldBindXML(t *testing.T) {
    var d, d2 data
    router := func() *gin.Engine {
        router := gin.Default()
    router.POST("/test.xml", func(c *gin.Context) {
        var d3 data
        err := c.ShouldBindXML(&d3)
        assert.NoError(t, err)
        c.XML(200, d3)
    })
    return router
}()

// 这里是 gin 和 http 标准库的区别,需要拿到 gin.Engine 的 ServeHTTP 函数
ts := httptest.NewServer( http.HandlerFunc(router.ServeHTTP))
defer ts.Close()

g := New(nil)

d.Id = 3
d.Data = "test data"

code := 200

err := g.POST(ts.URL + "/test.xml").SetXML(&d).BindXML(&d2).Code(&code).Do()

assert.NoError(t, err)
assert.Equal(t, code, 200)
assert.Equal(t, d, d2)

}

基于 func(w http.ResponseWriter, r *http.Request) 编写测试代码

这个方法应用场景在编写一些库的时候会用到,只想模拟一个服务端跑 http handle 函数,里面可以设置 http header 等返回属性。然后客户端直接获得*http.Response 对象操作。可以理解为这是一个很薄薄的服务端测试写法

func TestHeaderDecode(t *testing.T) {
    h := headerDecode{}
type tHeader struct {
    Limit      int           `header:"limit"`
    F64        float64       `header:"f64"`
    F32        float32       `header:"f32"`
    CreateTime time.Time     `header:"createTime" time_format:"unixNano"`
    UnixTime   time.Time     `header:"unixTime" time_format:"unix"`
    Duration   time.Duration `header:"duration"`
}

var theader tHeader

// 和正常的服务端回调函数一样
okFunc := func(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("limit", "1000")
    w.Header().Add("f64", "64")
    w.Header().Add("f32", "32.1")
    w.Header().Add("createTime", "1562400033000000123")
    w.Header().Add("unixTime", "1562400033")
    w.Header().Add("duration", "1h1s")
}

// 主要构造出 http.Request 对象
req := httptest.NewRequest("GET", "http://example.com/foo", nil)
// 构造出 http.ResponseWriter 对象
w := httptest.NewRecorder()
//执行回调函数
okFunc(w, req)
//构造出*http.Response 对象
resp := w.Result()

// todo array slice
assert.NoError(t, h.Decode(resp, &theader))

}

我的 github 地址

https://github.com/guonaihong/gout


更多关于Golang Go语言 test 常见套路(2)的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

支持,谢谢分享

更多关于Golang Go语言 test 常见套路(2)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢分享

喜欢就好,后面我会把内容整理好,做成 gitbook,方便查看。

喜欢就好。后面还会分享 go channel 相关技巧。

在Golang(Go语言)中,编写测试代码是确保代码质量和功能正确性的重要手段。以下是Go语言测试中常见的一些套路和技巧,继续我们的探讨:

  1. 使用testing: Go标准库中的testing包提供了编写和运行测试的基础设施。通过定义一个以Test为前缀的函数,并使用t *testing.T类型的参数,你可以轻松编写测试用例。

  2. 表格驱动测试: 对于需要测试多个输入输出的场景,使用表格驱动测试可以极大地简化代码。通过定义一个包含测试数据的表格,并在循环中运行每个测试用例,可以提高代码的可读性和可维护性。

  3. Mock依赖: 在测试中,有时需要模拟(mock)外部依赖(如数据库、HTTP服务等)。可以使用第三方库(如go-mock)来创建mock对象,以便在测试中控制这些依赖的行为。

  4. 基准测试: 除了单元测试,Go还支持基准测试(benchmark),用于测量代码的性能。通过定义一个以Benchmark为前缀的函数,并使用b *testing.B类型的参数,你可以编写基准测试用例。

  5. 测试覆盖率: 使用go test -cover命令可以生成测试覆盖率报告,了解哪些代码被测试覆盖,哪些没有。这有助于发现潜在的未测试代码路径。

  6. 持续集成: 将测试集成到持续集成(CI)流程中,可以确保每次代码变更都经过自动化测试,从而提高代码质量。

掌握这些套路和技巧,将帮助你更有效地编写和运行Go语言测试,确保代码的稳定性和可靠性。

回到顶部