使用Go语言开发自动化API测试工具详解

2024-04-18 0 765
目录
  • 前言
  • 网络请求
  • 日志组件
    • logrus 使用 & 配置
    • zap 使用 & 配置
  • swagger 组件
    • Excel 导出
      • 吐槽
        • 三元表达式
        • 数组排序
      • 小结
        • 参考资料

          前言

          上一篇文章说到我还开发了一个独立的自动测试工具,可以根据 OpenAPI 的文档来测试,并且在测试完成后输出测试报告,报告内容包括每个接口是否测试通过和响应时间等。

          这个工具我使用了 go 语言开发,主要是考虑到了 go 语言可以傻瓜式的实现交叉编译,生成的可执行文件直接上传到服务器就可以执行,非常方便。

          PS: go 语言写起来是真的折磨!感觉语法有很多别扭的地方,不过 build 的时候实在太爽了,根本无法拒绝

          为了避免篇幅太长,本文先介绍用到的组件,详细实现以及解析 OpenAPI 文档生成测试配置的部分后续的文章再介绍。

          网络请求

          标准库中的net/http包提供了发送 HTTP 请求的功能,拿到数据之后,使用json.Unmarshal函数解析 JSON 数据。这个包相对比较低级,对于简单的网络请求,够用,不过我还是想选择更好用的组件。

          Resty 是一个简单而强大的 Go HTTP 客户端,具有链式 API,可以轻松地发送 HTTP 请求并处理 JSON 数据。它提供了丰富的功能,包括自动重试、超时设置、请求和响应日志等。您可以使用 Resty 来发送 GET、POST、PUT、DELETE 等各种类型的请求,并且它能够自动将响应的 JSON 数据解析为 Go 结构体。

          现在出了 v2 版本,支持 HTTP/2、WebSocket、Cookie 操作,并提供了更加简洁和易用的 API 。

          项目地址:https://github.com/go-resty/resty

          使用起来还行

          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的参数是interface{}类型,可以传入的类型比较丰富,我这里还是跟 GET 一样传了字典,实际上应该传struct比较多一些吧。

          日志组件

          我之前用的是 go 语言内置的 log ,但似乎功能很少,也没有日志等级啥的,这能叫日志库吗……

          接着我找到了在 GitHub 上 star 很多的 logrus 库,不过感觉这是一个比较古老的库了,不太好用,formatter 也没找到好用的,看项目主页的介绍发现这个库已经进入退休状态…

          它让我 Check out, for example,Zerolog,Zap, andApex.

          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…).

          项目地址:https://github.com/sirupsen/logrus

          所以,最终还是用了 uber 的日志库go.uber.org/zap

          logrus 使用 & 配置

          虽然后面换了 zap ,还是记录一下关于 logrus 的使用。

          项目主页上列举的几个第三方 formatter 我基本都试用了,就这个nested-logrus-formatter比较好用。

          以下配置实现了同时输出日志到控制台和文件。

          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{})

          // 创建一个文件作为日志输出
          file, err := os.OpenFile(\”logfile.log\”, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
          if err != nil {
          logger.Fatalf(\”无法打开日志文件: %v\”, err)
          }

          // 创建一个多写入器,将日志同时输出到控制台和文件
          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 好用多了,开箱即用,搭配 zapcore 可以配置多个输出,也可以设置按日志大小分割文件,还可以对接其他日志收集平台啥的,基本做到了现代日志组件的水平了…

          一样是实现了同时输出日志到控制台和文件。

          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

          项目地址:https://github.com/go-swagger/go-swagger

          这个可以使用 scoop 安装

          scoop install go-swagger

          用着一般,没有 swagger code generator 好用。

          就没继续探索下去了。

          PS: Jetbrains 系的 IDE 里有几成 swagger code generator 工具,功能非常强大,可以生成各种代码。

          不过我还是自己实现了OpenAPI 文档解析(比较灵活),所以暂时还没用上这个强大的工具。

          Excel 导出

          Excel 操作我用的是这个github.com/xuri/excelize/v2

          一开始没注意,后面发现这个居然是奇安信开源的…… 然后看了 qax-os 这个 group ,发现开源的几个项目都是跟安全无关的,不务正业啊老哥!

          没有对比其他的,看着 star 挺多,上手就直接用了

          感觉还行。

          func exportTestReportsToExcel(testReports []*tester.Report, filename string) error {
          // 创建一个新的 Excel 文件
          f := excelize.NewFile()

          // 创建一个名为 \”测试报告\” 的工作表
          index, err := f.NewSheet(\”测试报告\”)
          if err != nil {
          return err
          }

          // 设置工作表列名
          f.SetCellValue(\”测试报告\”, \”A1\”, \”接口名称\”)
          f.SetCellValue(\”测试报告\”, \”B1\”, \”接口路径\”)
          f.SetCellValue(\”测试报告\”, \”C1\”, \”测试是否通过\”)
          f.SetCellValue(\”测试报告\”, \”D1\”, \”耗时(秒)\”)

          // 遍历测试报告并在工作表中写入数据
          for i, report := range testReports {
          row := i + 2
          f.SetCellValue(\”测试报告\”, fmt.Sprintf(\”A%d\”, row), report.ApiName)
          f.SetCellValue(\”测试报告\”, fmt.Sprintf(\”B%d\”, row), report.ApiPath)
          f.SetCellValue(\”测试报告\”, fmt.Sprintf(\”C%d\”, row), func() string {
          if report.IsPassed {
          return \”是\”
          }
          return \”否\”
          }())
          f.SetCellValue(\”测试报告\”, fmt.Sprintf(\”D%d\”, row), report.Elapsed.Seconds())
          }

          // 设置活动工作表
          f.SetActiveSheet(index)

          // 将 Excel 文件保存到磁盘
          err = f.SaveAs(filename)
          if err != nil {
          return err
          }

          return nil
          }

          吐槽

          三元表达式

          我很想吐槽 go 为啥没有三元表达式,用匿名函数真的好繁琐啊!!

          据说是因为觉得三元表达式可以写出很多让人看不懂的骚代码,所以 go 不打算支持,因噎废食啊

          不过这难不倒我,可以写个函数来模拟,而且现在 go 似乎更新了泛型的功能,不用再拿 interface 来模拟

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

          使用的时候就

          result := If[string](report.IsPassed, \”成功\”, \”没通过\”)

          支持类型推导,所以[string]也可以省略了。

          这样前面导出 Excel 的代码里的匿名函数就可以改成这样,简洁多了!

          f.SetCellValue(\”测试报告\”, fmt.Sprintf(\”C%d\”, row), If(report.IsPassed, \”是\”, \”否\”))

          数组排序

          本来也不算什么吐槽,属于是挑刺了,go 的排序没那么好用,但也不难用。

          用匿名函数可以实现按字段排序,这倒是和 C 语言里用函数指针大同小异,不愧是带 gc 的 C 语言

          测试报告的数据结构是这样

          // Report 测试报告
          type Report struct {
          ApiName string
          ApiPath string
          IsPassed bool
          Elapsed time.Duration
          Response *ApiResponse
          }

          我想对[]*Report数组排序,可以用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);

          小结

          就这样吧,很简单的一个小工具,因为还处在 go 的小白阶段,每用一个新的库都会记录一下。

          参考资料

          uber的Go日志库zap使用详解 -Golang日志操作库zap的使用详解

          以上就是使用Go语言开发自动化API测试工具详解的详细内容,更多关于Go自动化API测试工具的资料请关注悠久资源网其它相关文章!

          您可能感兴趣的文章:

          • Go工具链之代码测试神器go test详解
          • Golang之模糊测试工具的使用
          • Golang日志操作库zap的使用详解

          收藏 (0) 打赏

          感谢您的支持,我会继续努力的!

          打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
          点赞 (0)

          悠久资源 Golang 使用Go语言开发自动化API测试工具详解 https://www.u-9.cn/jiaoben/golang/187143.html

          常见问题

          相关文章

          发表评论
          暂无评论
          官方客服团队

          为您解决烦忧 - 24小时在线 专业服务