本文首發於個人博客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/*
複製代碼