API のテストを自動化するなら Step CI が便利❗️
ちょうど導入するかどうか検証をしていて,とても良かったので紹介も兼ねてまとめたいと思う📝
Step CI は API として REST 以外に GraphQL や gRPC などもサポートしていて,実行方法としては CLI や GitHub Actions 以外に Jest など多くのサービスとの連携もサポートしている👏 また OpenAPI 仕様書からテストワークフローを自動生成する機能もある \( 'ω')/
セットアップ
Step CI CLI は Homebrew や npm を使って簡単にセットアップできる.Step CI はデフォルトだと使用状況データを収集するため,気になるなら環境変数 STEPCI_DISABLE_ANALYTICS
を設定しておくと良いと思う👌
$ brew install stepci $ export STEPCI_DISABLE_ANALYTICS=true $ stepci --version 2.6.7
Step CI を試す: 基本操作
今回はサンプルとして犬の画像をランダムに返してくれる RandomDog API を使って Step CI を試す🐶
Step CI では YAML でテストワークフローを定義する.書きやすく読みやすく良いと思う.以下のワークフローでは API の実行結果に対して3種類のチェックを実行している❗️
- Status Code
200
が返ってくること ✔ - Response Header
application/json; charset=utf-8
が返ってくること ✔ - Response の JSON 構造が正しいこと ✔
version: 1.1 name: RandomDog Check env: host: random.dog tests: example: steps: - name: GET request http: url: https://${{env.host}}/woof.json method: GET check: status: 200 headers: Content-Type: application/json; charset=utf-8 schema: type: object properties: url: type: string fileSizeBytes: type: integer required: - url - fileSizeBytes
stepci run
コマンドを実行すると PASS
と返ってくる👌
$ stepci run workflow1.yml PASS example ⏲ 1.257s ⬆ 0 bytes ⬇ 0 bytes Tests: 0 failed, 1 passed, 1 total Steps: 0 failed, 0 skipped, 1 passed, 1 total Time: 1.282s, estimated 1s CO2: 0.00003g Workflow passed after 1.282s Give us your feedback on https://step.ci/feedback
意図的に Status Code 500
を期待値にして実行すると FAIL
と返ってくる👌
テストが落ちたときの情報量が多いのはデバッグしやすくて助かる.
$ stepci run workflow1.yml FAIL example ⏲ 1.046s ⬆ 0 bytes ⬇ 0 bytes Summary ✕ GET request failed after 1.039s ● example › GET request Request HTTP GET https://random.dog/woof.json HTTP/1.1 Response HTTP/1.1 200 OK server: nginx/1.4.6 (Ubuntu) date: Sun 16 Jul 2023 13:17:01 GMT content-type: application/json; charset=utf-8 content-length: 91 connection: close x-powered-by: Express access-control-allow-origin: * access-control-allow-headers: Origin X-Requested-With Content-Type Accept access-control-allow-methods: GET etag: W/"5b-JQhIhZUD7lbzPPh8fSXWfgKfDSs" strict-transport-security: max-age=15768000 {"fileSizeBytes":75171,"url":"https://random.dog/b1a59f58-452a-4d97-82bb-a70d75c33090.JPG"} Checks Headers ✔ Content-Type: application/json; charset=utf-8 JSON Schema ✔ [object Object] Status ✕ 200 (expected 500) Tests: 1 failed, 0 passed, 1 total Steps: 1 failed, 0 skipped, 0 passed, 1 total Time: 1.403s, estimated 1s CO2: 0.00003g Workflow failed after 1.403s Give us your feedback on https://step.ci/feedback
Step CI を試す: パフォーマンスと SSL
Step CI では,API に対して「パフォーマンス」と「SSL」のチェックも実行できる.
API は継続的に動いているけど "あるタイミングからレスポンスが遅くなってしまっている" という場合や "SSL 証明書の更新を忘れている" という場合など,API レスポンス以外の観点までテストできて便利❗️
version: 1.1 name: RandomDog Check env: host: random.dog tests: example: steps: - name: GET request http: url: https://${{env.host}}/woof.json method: GET check: performance: firstByte: - lte: 200 total: - lte: 1000 ssl: valid: true signed: true daysUntilExpiration: - gte: 30
同じく stepci run
コマンドを実行すると PASS
と返ってくる👌
$ stepci run workflow2.yml PASS example ⏲ 0.989s ⬆ 0 bytes ⬇ 0 bytes Tests: 0 failed, 1 passed, 1 total Steps: 0 failed, 0 skipped, 1 passed, 1 total Time: 1.014s, estimated 1s CO2: 0.00003g Workflow passed after 1.014s Give us your feedback on https://step.ci/feedback
RandomDog API の SSL 証明書には Let's Encrypt が使われていて,(動作確認をしている日だと)有効期限 60日以上
を期待値にして実行すると FAIL
と返ってくる👌 ちなみに daysUntilExpiration
でエラーになると expected [object Object]
と表示されるのはちょっと微妙な気がする💨
$ stepci run workflow2.yml FAIL example ⏲ 0.969s ⬆ 0 bytes ⬇ 0 bytes Summary ✕ GET request failed after 0.969s ● example › GET request Request HTTP GET https://random.dog/woof.json HTTP/1.1 Response HTTP/1.1 200 OK server: nginx/1.4.6 (Ubuntu) date: Sun 16 Jul 2023 13:32:09 GMT content-type: application/json; charset=utf-8 content-length: 93 connection: close x-powered-by: Express access-control-allow-origin: * access-control-allow-headers: Origin X-Requested-With Content-Type Accept access-control-allow-methods: GET etag: W/"5d-jdBzoBmENWVOT0rkNffI3V7+CSY" strict-transport-security: max-age=15768000 {"fileSizeBytes":1439974,"url":"https://random.dog/8e05486e-bd82-4656-b77d-f7ae95281969.jpg"} Checks Performance ✔ firstByte: 194 ✔ total: 936 Certificate ✔ valid: true ✔ signed: true ✕ daysUntilExpiration: 34 (expected [object Object]) Tests: 1 failed, 0 passed, 1 total Steps: 1 failed, 0 skipped, 0 passed, 1 total Time: 1.331s, estimated 1s CO2: 0.00003g Workflow failed after 1.331s Give us your feedback on https://step.ci/feedback
Step CI を試す: テストデータとフェイクデータ
次は Step CI の「テストデータ」と「フェイクデータ」を試すため,Step CI のドキュメントにも載っている JSONPlaceholder API を使って POST リクエストを実行する❗️
テストデータ
Step CI では CSV のテストデータを用意してテストワークフローのパラメータとして使える.例えば今回は testdata.csv
として以下の CSV を用意した.
name,blog kakakakakku,https://kakakakakku.hatenablog.com/
すると YAML で ${{ testdata.name }}
や ${{ testdata.blog }}
のように定義できる.以下のワークフローでは POST リクエストのパラメータとしてテストデータから値を取得している👌 さらに check.jsonpath
を使ってレスポンスの値をテストしている.
version: 1.1 name: JSONPlaceholder Check env: host: jsonplaceholder.typicode.com resource: posts tests: example: testdata: file: testdata.csv steps: - name: POST request http: url: https://${{env.host}}/${{env.resource}} method: POST headers: Content-Type: application/json json: name: ${{ testdata.name }} blog: ${{ testdata.blog }} check: status: /^20/ jsonpath: $.name: - eq: kakakakakku - isString: true $.blog: - eq: https://kakakakakku.hatenablog.com/ - isString: true
実行すると PASS
と返ってくる👌
$ stepci run workflow3.yml PASS example ⏲ 0.507s ⬆ 0 bytes ⬇ 0 bytes Tests: 0 failed, 1 passed, 1 total Steps: 0 failed, 0 skipped, 1 passed, 1 total Time: 0.532s, estimated 1s CO2: 0.00003g Workflow passed after 0.532s Give us your feedback on https://step.ci/feedback
フェイクデータ
Step CI には Faker が組み込まれているため,テストデータをランダムに生成することもできる.以下のワークフローでは POST リクエストのパラメータで
${{ internet.userName | fake }}
と書くことで Faker の internet.userName
からフェイクデータを取得している👌
version: 1.1 name: JSONPlaceholder Check env: host: jsonplaceholder.typicode.com resource: posts tests: example: testdata: file: testdata.csv steps: - name: POST request http: url: https://${{env.host}}/${{env.resource}} method: POST headers: Content-Type: application/json json: name: ${{ internet.userName | fake }} check: status: /^20/ jsonpath: $.name: - eq: kakakakakku - isString: true
レスポンスとして name: kakakakakku
を期待するテストワークフローになっているため,Faker によってランダムに生成されたユーザー名だとテストは落ちてしまう.以下の例だと Verdie28
というユーザー名になっていた.
$ stepci run workflow4.yml FAIL example ⏲ 0.503s ⬆ 0 bytes ⬇ 0 bytes Summary ✕ POST request failed after 0.499s ● example › POST request Request HTTP POST https://jsonplaceholder.typicode.com/posts HTTP/1.1 Content-Type: application/json {"name":"Verdie28"} Response HTTP/1.1 201 Created date: Sun 16 Jul 2023 13:47:50 GMT content-type: application/json; charset=utf-8 content-length: 37 connection: close x-powered-by: Express x-ratelimit-limit: 1000 x-ratelimit-remaining: 997 x-ratelimit-reset: 1689515291 vary: Origin X-HTTP-Method-Override Accept-Encoding access-control-allow-credentials: true cache-control: no-cache pragma: no-cache expires: -1 access-control-expose-headers: Location location: http://jsonplaceholder.typicode.com/posts/101 x-content-type-options: nosniff etag: W/"25-S03dZwwrthzEz7DRUq+Sn1rFo2k" via: 1.1 vegur cf-cache-status: DYNAMIC report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=TWyG5TtvcoxyKpipwg4b7cKP1jVYhTp39K4PX9SqCe7cdV02sk3DWjk%2BGq9HY25iw%2BY8NbBMhDO65BUa%2F4RiXXaFQvcOWGLA8AOsmpgNWLKAAMHQXQ9Nn8%2FZBxCeruQ3dokzVWjvUOtHruuvKJiSrx95hab5GIW7qXjD"}]"group":"cf-nel""max_age":604800} nel: {"success_fraction":0"report_to":"cf-nel""max_age":604800} server: cloudflare cf-ray: 7e7ab3071ba680e4-NRT alt-svc: h3=":443"; ma=86400 { "name": "Verdie28", "id": 101 } Checks JSONPath ✕ $.name: Verdie28 (expected [object Object],[object Object]) Status ✔ 201 Tests: 1 failed, 0 passed, 1 total Steps: 1 failed, 0 skipped, 0 passed, 1 total Time: 0.879s, estimated 1s CO2: 0.00001g Workflow failed after 0.879s Give us your feedback on https://step.ci/feedback
GitHub Actions で Step CI を実行する
Step CI CLI で動作確認をしたら,今度は GitHub Actions で継続的に API のテストを実行したいと思う.Step CI は GitHub Actions をサポートしているため Step CI Action を使えば簡単に実行できる👏
以下のような GitHub Actions ワークフローを定義すれば OK❗️
name: step-ci on: push: branches: - master pull_request: branches: - master jobs: step-ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run Step CI uses: stepci/stepci@main with: workflow: workflow1.yml
まとめ
API のテストを自動化するなら Step CI が便利❗️
\( 'ω')/ もっと使っていくぞ〜
ちなみに今回は試さなかったけど Step CI には他にも機能があるので箇条書きにしておく👀
- OpenAPI 連携
- 負荷テスト
- Fuzz テスト(API に不正な値を与える)
- CO2 テスト(二酸化炭素排出量の計算?)
- など