go測試庫之apitest

2023-05-06 06:00:28

前言

使用go語言做開發差不多快一年了,主要用來寫後端Web服務,從一開始吐槽他的結構體,比如建立個複雜的JSON格式資料,那是相當的痛苦。還有 err 處理寫的巨麻煩。

當然,go 也有爽的地方,建立個線協程簡直太簡單了。

到後來慢慢接受,覺得效率還行,因為是靜態強型別語言,在修改完專案程式碼之後,反而很有信心(如果出現低階的型別錯誤,直接編譯出錯了),相比 Python 就要反覆檢查兩邊,對修改的程式碼總時心裡發虛。

go語言測試相關的東西都不咋地,比如自帶的測試框架相比較 pytest 那是相當的簡陋。今年開始給後端寫單元測試(其實應該叫介面測試),發現 apitest庫 眼前一亮。採用鏈式呼叫,和 HttpRunner 3.x 的鏈式呼叫頗有幾分相似。

  • HttpRunner 3.x
# httprunner 3.x 
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase


class TestCaseTestCase(HttpRunner):

    config = Config("basic test config").base_url("http://127.0.0.1:8000/api")

    teststeps = [
        Step(
            RunRequest(" test_add_event_all_null")
            .post("/add_event/")
            .with_data({"eid": "", "limit": "", "address": "", "start_time": ""})
            .validate()
            .assert_equal("body.status", 10021)
            .assert_equal("body.message", "parameter error")
        )
    ]


if __name__ == "__main__":
    TestCaseTestCase().test_start()

apitest 測試庫

一個簡單且可延伸的行為測試庫。

測試庫: https://github.com/steinfletcher/apitest jsonpath庫: github.com/steinfletcher/apitest-jsonpath

  • 簡單的get介面
package api

import (
 "net/http"
 "testing"
 "time"

 "github.com/steinfletcher/apitest"
)

func Client() http.Client {
 cli := &http.Client{
  Timeout: time.Second * 10,
 }
 return *cli
}

func TestGetSample(t *testing.T) {
 cli := Client()
 apitest.New().
    EnableNetworking(&cli).
  Get("http://httpbin.org/get").
  Expect(t).
  Status(http.StatusOK).
  End()
}

New(): 建立一個新的API測試。

EnableNetworking(): EnableNetworking為提供的使用者端啟用網路,需要一個 http.Clinet。

Get(): 傳送get 請求,需要一個URL。

Expect(): Expect將請求規範標記為完整。

Status(): 斷言http狀態。http.StatusOK = 200

End(): End執行測試,將結果返回給呼叫者。

  • get介面帶引數
import (
  ...
 jsonpath "github.com/steinfletcher/apitest-jsonpath"
)

...

func TestGetParams(t *testing.T) {
 cli := Client()
 apitest.New().
  EnableNetworking(&cli).
  Intercept(func(req *http.Request) {
   req.URL.RawQuery = "id=1&name=jack"
  }).
  Get("http://httpbin.org/get").
  Expect(t).
  Assert(
   jsonpath.Contains(`$.args.id`, "1")).
  Assert(
   jsonpath.Equal(`$.args.name`, "jack")).
  End()
}

req.URL.RawQuery: 用於定義get請求引數。

Assert() ,方法用於斷言。

jsonpath 提供了斷言方法,Contains判斷包含,Equal判斷相等。

  • post介面Form-data引數
...

func TestPostFormData(t *testing.T) {
 cli := Client()
 apitest.New().
  EnableNetworking(&cli).
  Post("http://httpbin.org/post").
  FormData("key1", "value1").
  FormData("key2", "value2").
  Expect(t).
  Assert(
   jsonpath.Chain().
    Equal(`$.form.key1`, "value1").
    Equal(`$.form.key2`, "value2").
    End()).
  End()
}

FormData() 用於設定form-Data格式的引數。

jsonpath 提供的斷言同樣支援鏈式呼叫。

  • post介面JSON引數
...

func TestPostJson(t *testing.T) {
 cli := Client()
 apitest.New().
  EnableNetworking(&cli).
  Post("http://httpbin.org/post").
  JSON(`{"message": "hi"}`).
  Expect(t).
  Assert(
   jsonpath.Chain().
    Contains(`$.data`, "message").
    Contains(`$.data`, "hi").
    End()).
  End()
}

JSON() 用於設定JSON()請求方法。

apitest 評價

官網:https://apitest.dev/

apitest 在完成http介面測試方面還是非常方便的,如果你被 go語言的 http 庫蹂躪過一段時間之後感觸更深;怎麼說了,比如你經常被老闆PUA,突然有一天老闆居然當面表揚了你,大概就這種感覺。