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 地址
更多关于Golang Go语言 test 常见套路(2)的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢分享
喜欢就好,后面我会把内容整理好,做成 gitbook,方便查看。
喜欢就好。后面还会分享 go channel 相关技巧。
在Golang(Go语言)中,编写测试代码是确保代码质量和功能正确性的重要手段。以下是Go语言测试中常见的一些套路和技巧,继续我们的探讨:
-
使用
testing
包: Go标准库中的testing
包提供了编写和运行测试的基础设施。通过定义一个以Test
为前缀的函数,并使用t *testing.T
类型的参数,你可以轻松编写测试用例。 -
表格驱动测试: 对于需要测试多个输入输出的场景,使用表格驱动测试可以极大地简化代码。通过定义一个包含测试数据的表格,并在循环中运行每个测试用例,可以提高代码的可读性和可维护性。
-
Mock依赖: 在测试中,有时需要模拟(mock)外部依赖(如数据库、HTTP服务等)。可以使用第三方库(如
go-mock
)来创建mock对象,以便在测试中控制这些依赖的行为。 -
基准测试: 除了单元测试,Go还支持基准测试(benchmark),用于测量代码的性能。通过定义一个以
Benchmark
为前缀的函数,并使用b *testing.B
类型的参数,你可以编写基准测试用例。 -
测试覆盖率: 使用
go test -cover
命令可以生成测试覆盖率报告,了解哪些代码被测试覆盖,哪些没有。这有助于发现潜在的未测试代码路径。 -
持续集成: 将测试集成到持续集成(CI)流程中,可以确保每次代码变更都经过自动化测试,从而提高代码质量。
掌握这些套路和技巧,将帮助你更有效地编写和运行Go语言测试,确保代码的稳定性和可靠性。