Featured image of post 在actions中进行自动api测试

在actions中进行自动api测试

为了保证我们提交的代码不会影响到之前已有的api,我们可以考虑在外部对程序进行黑盒测试,结合postman和github action可以完全实现测试流程的自动化,

postman实现按流程测试

之前虽然一直有用postman,但是一直只停留在最基本的单个请求的构造与发送上,直到实习后才发现原来postman能做的远不止单个请求的发送,collection也远不止是把相关的请求放到一起那么简单。在一个collection集合下的所有请求都可以按照一个流程来执行,并共享一个变量的命名空间,而结合 pre-requestTests 两个tab下的脚本(postman内置了一个node运行环境),我们可以实现取出response中的参数并将其设置为集合变量或是全局变量,指定下一个请求,或者通过js构造并发送请求,以及对response中的值进行断言测试…… 关于这方面的介绍可以查看 postman的对应文档, 且脚本编写框的右侧也提供了不少的SNIPPETS。在我们写好了collection之后,还可以将其导出到一个json文件中,可以用于导入到其他的postman中进行测试或者是用于下文的actions自动测试。

另外,在测试断言时用到的语法可以参考 BDD Style

The BDD styles are expect and should. Both use the same chainable language to construct assertions, but they differ in the way an assertion is initially constructed. Check out the Style Guide for a comparison.

集合actions实现自动化测试

Newman is a command-line Collection Runner for Postman. 在action中我们需要用到Newman这个工具。

newman

为了能让测试顺利进行,在action中我们还需要做几件事情:

  1. 构建二进制程序
  2. 通过docker启动一个数据库
  3. 使用程序或者是sql文件初始化数据库填充测试数据
  4. 使用newman按照导出的测试集合进行测试

其中,mysql和newman都已经有现成的action了,填上参数即可使用,这里贴一下我们最终采用的一个workflow文件,删除了特定部分,但是也足以用作参考。

name: ci-api-test
on:
  pull_request:

permissions:
  contents: read
  # Optional: allow read access to pull request. Use with `only-new-issues` option.
  # pull-requests: read
jobs:
  golangci:
    name: API Test
    runs-on: ubuntu-latest
    env:
      GOPRIVATE: github.com/example
      GH_ACCESS_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
    steps:
      - uses: actions/checkout@v2

      - uses: mirromutth/mysql-action@v1.1
        with:
          # host port: 3800 # Optional, default value is 3306. The port of host
          # container port: 3307 # Optional, default value is 3306. The port of container
          character set server: "utf8mb4" # Optional, default value is 'utf8mb4'. The '--character-set-server' option for mysqld
          collation server: "utf8mb4_general_ci" # Optional, default value is 'utf8mb4_general_ci'. The '--collation-server' option for mysqld
          mysql version: "5.7" # Optional, default value is "latest". The version of the MySQL
          mysql database: "database" # Optional, default value is "test". The specified database which will be create
          mysql root password: "dbpassword" # Required if "mysql user" is empty, default is empty. The root superuser password
          # mysql user: 'developer' # Required if "mysql root password" is empty, default is empty. The superuser for the specified database. Can use secrets, too
          # mysql password: ${{ secrets.DatabasePassword }} # Required if "mysql user" exists. The password for the "mysql user"

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: 1.17

      # 构件中用到了私有库,所以需要制定token
      - name: Set token
        run: git config --global url.https://$GH_ACCESS_TOKEN@github.com/.insteadOf https://github.com/

      - name: Generate doc
        run: go generate -x

      - name: Init Mysql
        run: go run main.go initMigrateMysql --config configs/config.ci.yaml

      - name: Start service
        run: go run main.go serve --config configs/config.ci.yaml &

    # 使用前文导出的collection进行测试
      - name: Newman API Test
        uses: matt-ball/newman-action@v1.0.4
        with:
          collection: .postman/API.postman_collection.json
          envVar: '[{ "key": "host", "value": "localhost:9000" }, { "key": "scheme", "value": "http" }]'

之后,在每次有人提交pr的时候,action便会被触发,完成构建->初始化->api测试的流程,如果出现了破坏性的改动,测试也能及时告诉我们,不至于合并进主干后再回退,甚至是发布后还要热修复。

不过新增了自动化api测试后,也需要我们每个人在开发一个新的api时都要及时加上我们新增的api对应的测试。不过最简单的测试,只需要像下面这样:

pm.test("Check status ok", () => {
    let jsonData = pm.response.json()
    pm.expect(jsonData.code).to.eql(0,`${JSON.stringify(jsonData)}`)
})

测试结果

查看响应对象里面的code是否为0(我们规定-1时代表异常)即可。当然,一个完备的测试还应该包含更多的情况,比如错误的请求也应得到合适的处理,而非返回一个500错误。

comments powered by Disqus
本站访客数:
Built with Hugo
Theme Stack designed by Jimmy