本文首发于个人博客node
在平常后端业务开发中,咱们常常会写一些 api,而后用 postman
测试下是否可用,可能就直接丢到线上去了。 然鹅这样作很是不严谨, 大部分状况下仍是须要对 api 进行测试,以保证可用性。 我在项目中用到的是 httpexpect, 跟 nodejs 中的 mocha 有一些相似。在这里就不对基本的单元测试作介绍了,你们翻翻 golang 入门指南之类的文档就能看到。git
httpexpect 是一个端对端 api 测试工具github
End-to-end HTTP and REST API testing for Go.golang
安装mongodb
go get -u -v github.com/gavv/httpexpect
复制代码
一个小例子express
package example
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gavv/httpexpect"
)
func TestFruits(t *testing.T) {
// 建立 http.Handler
handler := FruitsHandler()
// 运行 server
server := httptest.NewServer(handler)
defer server.Close()
// 建立 httpexpect 实例
e := httpexpect.New(t, server.URL)
// 测试api是否工做
e.GET("/test").
Expect().
Status(http.StatusOK).JSON().Array().Empty()
}
复制代码
支持 json 数据校验json
orange := map[string]interface{}{
"weight": 100,
}
// GET 建立一个橘子
e.PUT("/fruits/orange").WithJSON(orange).
Expect().
Status(http.StatusNoContent).NoContent()
// GET 而后获取, 并校验数据中是否含有 weight: 100
e.GET("/fruits/orange").
Expect().
Status(http.StatusOK).
JSON().Object().ContainsKey("weight").ValueEqual("weight", 100)
apple := map[string]interface{}{
"colors": []interface{}{"green", "red"},
"weight": 200,
}
// 建立一个苹果
e.PUT("/fruits/apple").WithJSON(apple).
Expect().
Status(http.StatusNoContent).NoContent()
// 获取这个苹果
obj := e.GET("/fruits/apple").
Expect().
Status(http.StatusOK).JSON().Object()
obj.Keys().ContainsOnly("colors", "weight")
// 对 返回数据逐一测试
obj.Value("colors").Array().Elements("green", "red")
obj.Value("colors").Array().Element(0).String().Equal("green")
obj.Value("colors").Array().Element(1).String().Equal("red")
obj.Value("colors").Array().First().String().Equal("green")
obj.Value("colors").Array().Last().String().Equal("red")
复制代码
链式调用函数用起来很顺手,其实内置函数还有不少, Object 数据类型有以下函数等等,知足各类测试须要。后端
ContainsKey
ContainsMap
Empty
Equal
Keys
NotContainsKey
复制代码
固然也支持其余场景的测试, 好比api
JSON Schema and JSON Path
JSON 模式Forms
表单URL construction
url 构造HTTP Headers
headerCookies
cookieRegular expressions
正则Subdomains and per-request URL
子 urlReusable builders
可重复使用Custom config
自定义Session support
session会话支持Use HTTP handler directly
重定向下面是一个依赖 gin 框架 api 项目使用 httpexpect 的例子。bash
package main
import (
"./engine"
)
func main() {
engine.GetMainEngine().Run(":4000")
}
复制代码
package engine
import (
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)
func GetMainEngine() *gin.Engine {
r := gin.New()
// db, store := database.Connect()
// logdb := database.ConnectLog()
// r.Use(sessions.Sessions("xxx", store))
// r.Use(corsMiddleware())
// r.Use(gin.Logger())
// r.Use(gin.Recovery())
// r.Use(requestLogger())
// 一堆自定义的 handler
routers.Init(r)
return r
}
复制代码
package test
import (
"net/http"
"testing"
)
var eng *httpexpect.Expect
func GetEngine(t *testing.T) *httpexpect.Expect {
gin.SetMode(gin.TestMode)
if eng == nil {
server := httptest.NewServer(engine.GetMainEngine())
eng = httpexpect.New(t, server.URL)
}
return eng
}
func TestArticles(t *testing.T) {
e := GetEngine(t)
e.GET("/api/v1/articles").
Expect().
Status(http.StatusOK).
JSON().Object().ContainsKey("data").Keys().Length().Ge(0)
}
复制代码
而后执行
go test -v -cover ...
复制代码
执行结果相似:
使用这个包,咱们能够对 restful 的每一个 api 都进行测试 😀, 更大程度地提高了代码质量。如下是个人 .travis.yml 配置。 不足之处,请批评指正!
language: go
services: mongodb
go:
- 1.9.2
- master
install: true
matrix:
allow_failures:
- go: master
fast_finish: true
notifications:
email: false
script:
- echo "script"
- go get -u -v github.com/gavv/httpexpect
- 其余自定义
- echo "add config file"
- cp config/config.example.yaml config/config.yaml
- echo "test"
- export GIN_MODE=test
- go test -v -cover test/*
复制代码