API シナリオテストツール runn で E2E テストを実装する
API シナリオテストツール runn とは
今回は、API シナリオテストツールである runn について紹介します😉✨
runn の主な特徴
runn は Go 言語で実装されているツールで、主な特徴は以下です。
発音は「ラン エヌ」です。
- シナリオベースのテストツールとして機能
- Go 言語用のテストヘルパーパッケージとして機能
- ワークフロー自動化ツールとして機能
-
以下をサポート:
- HTTP リクエスト
- gRPC リクエスト
- DB クエリ
- Chrome DevTools Protocol
- SSH/ローカルコマンド実行
- HTTP リクエストテストに OpenAPI 文書に似た構文を使用
- 単一のバイナリファイル = CI (継続的インテグレーション)に適している
引用: k1LoW/runn: runn is a package/tool for running operations following a scenario.
そして、ロゴがめっちゃカッコ良いです...!!!
runn のインストール
Homebrew でインストールすることができます。
$ brew install k1LoW/tap/runn
その他のインストール方法はオフィシャルのページを参照ください。
E2E テストを書いてみる
runn を使うことで、バックエンド単体のE2Eテストをコード量を少なく書くことができます!
以下の TODO を扱う API の E2E テストを実装してみました。
runbook 全体
今回は 1 つのシナリオにまとめて、以下の API エンドポイントに関するテストを書いてみました。
/v1/hc
/v1/todos
desc: "Todo API test"
runners:
req:
endpoint: http://127.0.0.1:8080/v1
vars:
title: "My first todo!!!"
description: "This is a todo for test."
steps:
hc:
desc: "Health Check"
req:
/hc:
get:
body:
application/json: null
test: |
// Status code must be 204.
current.res.status == 204
hcPostgres:
desc: "Health Check Postgres"
req:
/hc/postgres:
get:
body:
application/json: null
test: |
// Status code must be 204.
current.res.status == 204
postTodo:
desc: "Create Todo"
req:
/todos:
post:
body:
application/json:
title: "{{ vars.title }}"
description: "{{ vars.description }}"
test: |
// Status code must be 201.
current.res.status == 201
bind:
todoId: current.res.body.id
getTodo:
desc: "Get Todo"
req:
/todos/{{ todoId }}:
get:
body:
application/json: null
test: |
// Status code must be 200.
current.res.status == 200
&& current.res.body.id == todoId
findTodo:
desc: "Find Todo"
req:
/todos:
get:
body:
application/json: null
test: |
// Status code must be 200.
current.res.status == 200
&& len(current.res.body.todos) > 0
findNewTodo:
desc: "Find New Todo"
req:
/todos?status=new:
get:
body:
application/json: null
test: |
// Status code must be 200.
current.res.status == 200
&& len(current.res.body.todos) > 0
putTodo:
desc: "Update Todo"
req:
/todos/{{ todoId }}:
put:
body:
application/json:
title: "{{ vars.title }}"
description: "{{ vars.description }}"
statusCode: "working"
test: |
// Status code must be 200.
current.res.status == 200
&& current.res.body.status.code == "working"
patchTodo:
desc: "Change Todo Stats"
req:
/todos/{{ todoId }}:
patch:
body:
application/json:
statusCode: "done"
test: |
// Status code must be 200.
current.res.status == 200
&& current.res.body.status.code == "done"
deleteTodo:
desc: "Delete Todo"
req:
/todos/{{ todoId }}:
delete:
body:
application/json: null
test: |
// Status code must be 200.
current.res.status == 200
&& current.res.body.id == todoId
上から細かく見ていきます。
説明とエンドポイントの定義
desc: "Todo API test"
runners:
req:
endpoint: http://127.0.0.1:8080/v1
desc
シナリオについての説明を書くことができます。
また、endpoint
で共通となる API のエンドポイントを定義できます。
変数を定義する
vars
で変数を定義することができます。
vars:
title: "My first todo!!!"
description: "This is a todo for test."
map でテストを書く
list 形式で steps
を書くこともできますが、
保守性を考えて map 形式で書き、各ステップに名前を付けていきます。
以下では、hc
がステップ名です。
steps:
hc:
desc: "Health Check"
req:
/hc:
get:
body:
application/json: null
test: |
// Status code must be 204.
current.res.status == 204
endpoint
を定義しているため、/hc
と書くだけで http://127.0.0.1:8080/v1
にリクエストを飛ばすことができます。
test
では、レスポンスの HTTP ステータスコードが 204 であるかをチェックしています。
変数の使用
vars
で定義した変数は title: "{{ vars.title }}"
のように使用します。
レスポンスの作成された TODO の ID を bind
で todoId
に格納しています。
そうすることで、/todos/{{ todoId }}
で GET のエンドポイントを生成することができます。
また、レスポンスの current.res.body.id
と ID が一致するかも検証しています。
postTodo:
desc: "Create Todo"
req:
/todos:
post:
body:
application/json:
title: "{{ vars.title }}"
description: "{{ vars.description }}"
test: |
// Status code must be 201.
current.res.status == 201
bind:
todoId: current.res.body.id
getTodo:
desc: "Get Todo"
req:
/todos/{{ todoId }}:
get:
body:
application/json: null
test: |
// Status code must be 200.
current.res.status == 200
&& current.res.body.id == todoId
シナリオテストを実行する
run
コマンドで、シナリオテストを実行できます。
なお、詳細なログを出力するために --verbose
オプションをつけています。
$ runn run runbooks/test.yml --verbose
=== Todo API test (runbooks/test.yml)
--- Health Check (hc) ... ok
--- Health Check Postgres (hcPostgres) ... ok
--- Create Todo (postTodo) ... ok
--- Get Todo (getTodo) ... ok
--- Find Todo (findTodo) ... ok
--- Find New Todo (findNewTodo) ... ok
--- Update Todo (putTodo) ... ok
--- Change Todo Stats (patchTodo) ... ok
--- Delete Todo (deleteTodo) ... ok
1 scenario, 0 skipped, 0 failures
出力
なお、dump
を使えば、結果を出力して確認することもできます。
YAML ファイルを作成中は適宜出力すると便利です!
dump: current.res.body
まとめ
チュートリアルも充実していて、サクッと E2E テストを実装することができました。
YAML ファイルを分割して、より分かりやすくすることもできそうです。
可読性も非常に高く、素晴らしいツールだと思います🥳🎉
Discussion