最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Go語(yǔ)言開(kāi)發(fā)自動(dòng)化API測(cè)試工具詳解

 更新時(shí)間:2024年03月08日 10:58:30   作者:程序設(shè)計(jì)實(shí)驗(yàn)室  
這篇文章主要為大家詳細(xì)介紹了如何使用Go語(yǔ)言開(kāi)發(fā)自動(dòng)化API測(cè)試工具,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考下

前言

上一篇文章說(shuō)到我還開(kāi)發(fā)了一個(gè)獨(dú)立的自動(dòng)測(cè)試工具,可以根據(jù) OpenAPI 的文檔來(lái)測(cè)試,并且在測(cè)試完成后輸出測(cè)試報(bào)告,報(bào)告內(nèi)容包括每個(gè)接口是否測(cè)試通過(guò)和響應(yīng)時(shí)間等。

這個(gè)工具我使用了 go 語(yǔ)言開(kāi)發(fā),主要是考慮到了 go 語(yǔ)言可以傻瓜式的實(shí)現(xiàn)交叉編譯,生成的可執(zhí)行文件直接上傳到服務(wù)器就可以執(zhí)行,非常方便。

PS: go 語(yǔ)言寫(xiě)起來(lái)是真的折磨!感覺(jué)語(yǔ)法有很多別扭的地方,不過(guò) build 的時(shí)候?qū)嵲谔?,根本無(wú)法拒絕

為了避免篇幅太長(zhǎng),本文先介紹用到的組件,詳細(xì)實(shí)現(xiàn)以及解析 OpenAPI 文檔生成測(cè)試配置的部分后續(xù)的文章再介紹。

網(wǎng)絡(luò)請(qǐng)求

標(biāo)準(zhǔn)庫(kù)中的 net/http 包提供了發(fā)送 HTTP 請(qǐng)求的功能,拿到數(shù)據(jù)之后,使用 json.Unmarshal 函數(shù)解析 JSON 數(shù)據(jù)。這個(gè)包相對(duì)比較低級(jí),對(duì)于簡(jiǎn)單的網(wǎng)絡(luò)請(qǐng)求,夠用,不過(guò)我還是想選擇更好用的組件。

Resty 是一個(gè)簡(jiǎn)單而強(qiáng)大的 Go HTTP 客戶端,具有鏈?zhǔn)?API,可以輕松地發(fā)送 HTTP 請(qǐng)求并處理 JSON 數(shù)據(jù)。它提供了豐富的功能,包括自動(dòng)重試、超時(shí)設(shè)置、請(qǐng)求和響應(yīng)日志等。您可以使用 Resty 來(lái)發(fā)送 GET、POST、PUT、DELETE 等各種類型的請(qǐng)求,并且它能夠自動(dòng)將響應(yīng)的 JSON 數(shù)據(jù)解析為 Go 結(jié)構(gòu)體。

現(xiàn)在出了 v2 版本,支持 HTTP/2、WebSocket、Cookie 操作,并提供了更加簡(jiǎn)潔和易用的 API 。

項(xiàng)目地址: https://github.com/go-resty/resty

使用起來(lái)還行

GET 方法

import 	"github.com/go-resty/resty/v2"

req := c.RestyClient.R().SetHeader("Authorization", "token "+c.AuthToken)

req.SetQueryParams(map[string]string{
  "year":  "2024",
})
resp, err = req.Get("path")

POST 方法

req.SetBody(map[string]string{
  "year":  "2024",
})
resp, err = req.Get("path")

SetBody 的參數(shù)是 interface{} 類型,可以傳入的類型比較豐富,我這里還是跟 GET 一樣傳了字典,實(shí)際上應(yīng)該傳 struct 比較多一些吧。

日志組件

我之前用的是 go 語(yǔ)言內(nèi)置的 log ,但似乎功能很少,也沒(méi)有日志等級(jí)啥的,這能叫日志庫(kù)嗎……

接著我找到了在 GitHub 上 star 很多的 logrus 庫(kù),不過(guò)感覺(jué)這是一個(gè)比較古老的庫(kù)了,不太好用,formatter 也沒(méi)找到好用的,看項(xiàng)目主頁(yè)的介紹發(fā)現(xiàn)這個(gè)庫(kù)已經(jīng)進(jìn)入退休狀態(tài)…

它讓我 Check out, for example, ZerologZap, and Apex.

Logrus is in maintenance-mode. We will not be introducing new features. It's simply too hard to do in a way that won't break many people's projects, which is the last thing you want from your Logging library (again...).

項(xiàng)目地址: https://github.com/sirupsen/logrus

所以,最終還是用了 uber 的日志庫(kù) go.uber.org/zap

logrus 使用 & 配置

雖然后面換了 zap ,還是記錄一下關(guān)于 logrus 的使用。

項(xiàng)目主頁(yè)上列舉的幾個(gè)第三方 formatter 我基本都試用了,就這個(gè) nested-logrus-formatter 比較好用。

以下配置實(shí)現(xiàn)了同時(shí)輸出日志到控制臺(tái)和文件。

import (
  nested "github.com/antonfisher/nested-logrus-formatter"
  "github.com/sirupsen/logrus"
  "os"
)

func initLogger() *os.File {
  logger.SetLevel(logrus.DebugLevel)
  logger.SetReportCaller(true)
  logger.SetFormatter(&nested.Formatter{})

  // 創(chuàng)建一個(gè)文件作為日志輸出
  file, err := os.OpenFile("logfile.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  if err != nil {
    logger.Fatalf("無(wú)法打開(kāi)日志文件: %v", err)
  }

  // 創(chuàng)建一個(gè)多寫(xiě)入器,將日志同時(shí)輸出到控制臺(tái)和文件
  mw := io.MultiWriter(os.Stdout, file)

  // 添加 Hook 到 Logger 中
  logger.Out = mw

  return file
}

func main() {
  file := initLogger()
  defer func(file *os.File) {
    err := file.Close()
    if err != nil {
      fmt.Println(err)
    }
  }(file)
}

zap 使用 & 配置

zap 比起 logrus 好用多了,開(kāi)箱即用,搭配 zapcore 可以配置多個(gè)輸出,也可以設(shè)置按日志大小分割文件,還可以對(duì)接其他日志收集平臺(tái)啥的,基本做到了現(xiàn)代日志組件的水平了…

一樣是實(shí)現(xiàn)了同時(shí)輸出日志到控制臺(tái)和文件。

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

func buildLogger() *zap.SugaredLogger {
  config := zap.NewProductionEncoderConfig()
  config.EncodeTime = zapcore.ISO8601TimeEncoder
  consoleEncoder := zapcore.NewConsoleEncoder(config)
  fileEncoder := zapcore.NewJSONEncoder(config)
  logFile, _ := os.OpenFile("./log-test-zap.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 06666)

  tee := zapcore.NewTee(
    zapcore.NewCore(fileEncoder, zapcore.AddSync(logFile), zap.DebugLevel),
    zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), zap.DebugLevel),
  )
  var zapLogging = zap.New(
    tee,
    zap.AddCaller(),
    zap.AddStacktrace(zapcore.ErrorLevel),
  )

  var logger = zapLogging.Sugar()
  return logger
}

func main() {
  logger := buildLogger()
  defer logger.Sync()
}

swagger 組件

這里我試著用了一下 go swagger

項(xiàng)目地址: https://github.com/go-swagger/go-swagger

這個(gè)可以使用 scoop 安裝

scoop install go-swagger

用著一般,沒(méi)有 swagger code generator 好用。

就沒(méi)繼續(xù)探索下去了。

PS: Jetbrains 系的 IDE 里有幾成 swagger code generator 工具,功能非常強(qiáng)大,可以生成各種代碼。

不過(guò)我還是自己實(shí)現(xiàn)了OpenAPI 文檔解析(比較靈活),所以暫時(shí)還沒(méi)用上這個(gè)強(qiáng)大的工具。

Excel 導(dǎo)出

Excel 操作我用的是這個(gè) github.com/xuri/excelize/v2

一開(kāi)始沒(méi)注意,后面發(fā)現(xiàn)這個(gè)居然是奇安信開(kāi)源的…… 然后看了 qax-os 這個(gè) group ,發(fā)現(xiàn)開(kāi)源的幾個(gè)項(xiàng)目都是跟安全無(wú)關(guān)的,不務(wù)正業(yè)啊老哥!

沒(méi)有對(duì)比其他的,看著 star 挺多,上手就直接用了

感覺(jué)還行。

func exportTestReportsToExcel(testReports []*tester.Report, filename string) error {
  // 創(chuàng)建一個(gè)新的 Excel 文件
  f := excelize.NewFile()

  // 創(chuàng)建一個(gè)名為 "測(cè)試報(bào)告" 的工作表
  index, err := f.NewSheet("測(cè)試報(bào)告")
  if err != nil {
    return err
  }

  // 設(shè)置工作表列名
  f.SetCellValue("測(cè)試報(bào)告", "A1", "接口名稱")
  f.SetCellValue("測(cè)試報(bào)告", "B1", "接口路徑")
  f.SetCellValue("測(cè)試報(bào)告", "C1", "測(cè)試是否通過(guò)")
  f.SetCellValue("測(cè)試報(bào)告", "D1", "耗時(shí)(秒)")

  // 遍歷測(cè)試報(bào)告并在工作表中寫(xiě)入數(shù)據(jù)
  for i, report := range testReports {
    row := i + 2
    f.SetCellValue("測(cè)試報(bào)告", fmt.Sprintf("A%d", row), report.ApiName)
    f.SetCellValue("測(cè)試報(bào)告", fmt.Sprintf("B%d", row), report.ApiPath)
    f.SetCellValue("測(cè)試報(bào)告", fmt.Sprintf("C%d", row), func() string {
      if report.IsPassed {
        return "是"
      }
      return "否"
    }())
    f.SetCellValue("測(cè)試報(bào)告", fmt.Sprintf("D%d", row), report.Elapsed.Seconds())
  }

  // 設(shè)置活動(dòng)工作表
  f.SetActiveSheet(index)

  // 將 Excel 文件保存到磁盤(pán)
  err = f.SaveAs(filename)
  if err != nil {
    return err
  }

  return nil
}

吐槽

三元表達(dá)式

我很想吐槽 go 為啥沒(méi)有三元表達(dá)式,用匿名函數(shù)真的好繁瑣?。?!

據(jù)說(shuō)是因?yàn)橛X(jué)得三元表達(dá)式可以寫(xiě)出很多讓人看不懂的騷代碼,所以 go 不打算支持,因噎廢食啊

不過(guò)這難不倒我,可以寫(xiě)個(gè)函數(shù)來(lái)模擬,而且現(xiàn)在 go 似乎更新了泛型的功能,不用再拿 interface 來(lái)模擬

func If[T any](condition bool, trueVal, falseVal T) T {
  if condition {
    return trueVal
  }
  return falseVal
}

使用的時(shí)候就

result := If[string](report.IsPassed, "成功", "沒(méi)通過(guò)")

支持類型推導(dǎo),所以 [string] 也可以省略了。

這樣前面導(dǎo)出 Excel 的代碼里的匿名函數(shù)就可以改成這樣,簡(jiǎn)潔多了!

f.SetCellValue("測(cè)試報(bào)告", fmt.Sprintf("C%d", row), If(report.IsPassed, "是", "否"))

數(shù)組排序

本來(lái)也不算什么吐槽,屬于是挑刺了,go 的排序沒(méi)那么好用,但也不難用。

用匿名函數(shù)可以實(shí)現(xiàn)按字段排序,這倒是和 C 語(yǔ)言里用函數(shù)指針大同小異,不愧是帶 gc 的 C 語(yǔ)言

測(cè)試報(bào)告的數(shù)據(jù)結(jié)構(gòu)是這樣

// Report 測(cè)試報(bào)告
type Report struct {
  ApiName  string
  ApiPath  string
  IsPassed bool
  Elapsed  time.Duration
  Response *ApiResponse
}

我想對(duì) []*Report 數(shù)組排序,可以用 sort.Slice 方法

// 按照 Elapsed 屬性排序,從大到小
sort.Slice(testReports, func(i, j int) bool {
  return testReports[i].Elapsed > testReports[j].Elapsed
})

相比之下還是 cs 的 Linq 舒服啊

testReports.Sort((a, b) => a - b);

小結(jié)

就這樣吧,很簡(jiǎn)單的一個(gè)小工具,因?yàn)檫€處在 go 的小白階段,每用一個(gè)新的庫(kù)都會(huì)記錄一下。

參考資料

uber的Go日志庫(kù)zap使用詳解 -Golang日志操作庫(kù)zap的使用詳解

以上就是使用Go語(yǔ)言開(kāi)發(fā)自動(dòng)化API測(cè)試工具詳解的詳細(xì)內(nèi)容,更多關(guān)于Go自動(dòng)化API測(cè)試工具的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go?json自定義Unmarshal避免判斷nil示例詳解

    Go?json自定義Unmarshal避免判斷nil示例詳解

    這篇文章主要為大家介紹了Go?json自定義Unmarshal避免判斷nil示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Go 語(yǔ)言中的命令行參數(shù)概述

    Go 語(yǔ)言中的命令行參數(shù)概述

    本文給大家介紹Go語(yǔ)言中的命令行參數(shù)概述,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-10-10
  • golang等待觸發(fā)事件的實(shí)例

    golang等待觸發(fā)事件的實(shí)例

    這篇文章主要介紹了golang等待觸發(fā)事件的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go語(yǔ)言基礎(chǔ)入門(mén)應(yīng)用簡(jiǎn)介及常用命令

    Go語(yǔ)言基礎(chǔ)入門(mén)應(yīng)用簡(jiǎn)介及常用命令

    這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)入門(mén)應(yīng)用簡(jiǎn)介及常用命令,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11
  • golang channel讀取數(shù)據(jù)的幾種情況

    golang channel讀取數(shù)據(jù)的幾種情況

    本文主要介紹了golang channel讀取數(shù)據(jù)的幾種情況,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Go語(yǔ)言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練

    Go語(yǔ)言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練

    這篇文章主要介紹了Go語(yǔ)言與gRPC的完美結(jié)合實(shí)戰(zhàn)演練,gRPC(Remote?Procedure?Call)是一種遠(yuǎn)程過(guò)程調(diào)用技術(shù),通過(guò)壓縮和序列化數(shù)據(jù)來(lái)優(yōu)化網(wǎng)絡(luò)通信,可以顯著提高服務(wù)調(diào)用的性能和效率
    2024-01-01
  • Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn)

    Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn)

    這篇文章主要介紹了Golang在Mac、Linux、Windows下如何交叉編譯的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Go1.21新增maps包的用法詳解

    Go1.21新增maps包的用法詳解

    maps?包提供了幾個(gè)非常有用的用于操作?map?類型(任何類型的?map)的函數(shù),本文為大家整理了部分函數(shù)的具體用法,感興趣的小伙伴可以了解一下
    2023-08-08
  • go語(yǔ)言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐

    go語(yǔ)言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐

    MQTT是一個(gè)基于客戶端-服務(wù)器的消息發(fā)布/訂閱傳輸協(xié)議。本文主要介紹了go語(yǔ)言實(shí)現(xiàn)mqtt協(xié)議的實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • web項(xiàng)目中g(shù)olang性能監(jiān)控解析

    web項(xiàng)目中g(shù)olang性能監(jiān)控解析

    這篇文章主要為大家介紹了web項(xiàng)目中g(shù)olang性能監(jiān)控詳細(xì)的解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04

最新評(píng)論

蚌埠市| 肇州县| 凌海市| 遂宁市| 沅陵县| 德昌县| 葫芦岛市| 寿光市| 大悟县| 东丽区| 措美县| 红原县| 张家口市| 滁州市| 上思县| 清徐县| 特克斯县| 兰坪| 彰武县| 上虞市| 聂荣县| 西城区| 宁海县| 浙江省| 即墨市| 芦溪县| 成都市| 遵义市| 京山县| 佛山市| 梧州市| 阜南县| 图片| 正定县| 台北县| 乌鲁木齐市| 满城县| 汽车| 黄山市| 璧山县| 鄂尔多斯市|