こんにちは、アイリッジ プロダクト開発グループの神原です。主に自社サービスであるFANSHIPの機能強化を担当しています。
FANSHIPではプッシュ通知の配信に関わる様々な機能をAPIとして提供しています。 以前、PostmanというGUIのツールを用いて、FANSHIPのAPIの網羅的なテストを作成してCI/CDへ組み込み自動化する取り組みを行いました。この記事では、作成したテストの例も交えながらPostmanの機能や使用法をご紹介いたします。
導入方法
公式のダウンロードページからダウンロードして使用できます。Mac、Windows、Linuxの各OSで使用可能です。また、MacであればHomebrew-cask
での導入も可能です。
使い方
リクエストの作成
リクエストを作成するには、画面左上のNew
をクリックして表示されるダイアログからRequest
を選択します。リクエスト名と保存先(Postmanではコレクションという単位で管理されます)を指定して一旦保存します。
これで以下のようにリクエストを作成する雛形ができました。
とりあえず、URLに適当なものを入力してSend
を押下すると、これだけでリクエストを送信できていることがわかります。レスポンスボディ、ヘッダなどは画面下側で参照できます。
実際にAPIをテストする場合には、リクエストヘッダ、ボディ、認証情報などが必要なケースが当然あります。その場合には、Params
、Authorization
、Header
、Body
の各タブに値を設定すればOKです。
FANSHIPの認証APIを叩くために作成したリクエストは以下のようになっています。Header
タブにはKeyとValueの組を入力し、Body
タブにはjson形式でリクエストボディーを記述しています。Body
タブについては、入力形式をラジオボタンで選択できます。
なお、上に示したキャプチャでは右上にintegration
と表示されていますが、これはENVIRONMENTS
(この記事では変数グループと呼びます)といい、リクエスト時に使用する変数をまとめて定義したものです。これについては後述します。
テストの作成
Tests
タブにJavaScriptでテストコードを記述して、リクエストの結果を検証できます。
以下がテストのサンプルになります。
pm.test("Status code is 200", function () { pm.response.to.have.status(200); }); pm.test("Body matches string", function () { pm.expect(pm.response.text()).to.include('"status": "OK"'); });
このテストコードでは、ステータスコード200が返却されているかと、レスポンスボディに"status": "OK"
が含まれているかをテストしています。Send
を押下してリクエストを送信し、レスポンスが返ってくるとTests
に記述したスクリプトが実行され、以下のようにテスト結果が表示されます。
なお、Tests
タブ右側のSNIPPETS
には、何パターンか用意されているテストコードを活用できます。まずはここを見て、実施したいテストがあるか確認するのがよいでしょう。
変数の管理
このようにして作成したテストですが、変数グループを作成して複数の環境で使い回せます。画面右上の歯車マークをクリックするとMANAGE ENVIRONMENTS
のダイアログが開きます。ダイアログ右下のAdd
を押下し、変数のグループを作成します。
例としてapi_iridge_intg
という名前の変数グループを作成し、host
、token
という環境変数とその値を定義しました。{{host}}
, {{token}}
のように、波括弧2つで囲むとこれらの変数の参照が可能です。
この変数グループをコピーして、api_iridge_stg
という名前の変数グループを作成してみます。
api_iridge_intg
と同様に、host
、token
という変数を定義していますが、値を変えています。
このように変数グループを作成しておけば、テストケースの使い回しが可能になります。以下のように、リクエストURLに{{host}}
と記述しておくと、変数グループの切り替えに応じたURLへリクエストを投げられます。
画面右上のプルダウンから選択するだけで変数グループを切り替えられるので簡単です。
テスト作成の事例とTips
リクエストを送信するたびにリクエストボディを変えたい
FANSHIPのAPIにはプッシュ通知の配信を予約する機能があります。このAPIを任意のタイミングでテストしたいのですが、リクエストボディに含まれる配信予約時刻
はリクエスト送信時より未来の日時でなければならない制約があります。テストを自動化したいと考えた場合、リクエストボディを毎回手作業で修正するわけにはいきません。
ここでPre-request Script
を活用します。これはリクエストを送信する前に行う何らかの処理を定義する機能で、Tests
と同様にJavaScriptで記述できます。
上記のケースに対しては、未来の日時(一日後)を取得して変数に格納する処理をPre-request Script
に記述しました。この変数を使用して、実行タイミングに応じて未来の日時に対する配信の予約を行えるようになります。以下がそのサンプルです。
var addDate = function (date, num) { date.setDate(date.getDate() + num); return date; }; var formatDate = function (date, format) { format = 'YYYY-MM-DD hh:mm:ss'; format = format.replace(/YYYY/g, date.getFullYear()); format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2)); format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2)); format = format.replace(/hh/g, ('0' + date.getHours()).slice(-2)); format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2)); format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2)); return format; } var t = formatDate(addDate(new Date(), 1)); pm.environment.set("send_time", t );
レスポンスの内容を別のテストで使いまわしたい
FANSHIPの認証APIは以下の形式のレスポンスを返却します。
{ "status": "OK", "result": { "auth_token": "xxxxxxxxxx" } }
auth_token
は認証トークンで、他のAPIではこの認証トークンをリクエストヘッダに含めることが要求されます。トークンは認証APIを叩くごとに変わる可能性があるため、それを織り込んだテストを検討する必要があります。
この場合、以下のコードをTests
タブ内に記述して、認証トークンを変数fanship_auth
に格納できます。
var jsonData = JSON.parse(responseBody); postman.setEnvironmentVariable("fanship_auth", jsonData.result.auth_token);
上で述べたとおり、Tests
に記述した処理はレスポンスが返ってきた後に実行されるので、レスポンスを解析して変数に格納して別のリクエスト時に使い回しが可能です。
認証APIのTests
内に上記のコードを追加し、実行とトークン取得を一連のテストの先頭で行って、認証トークンが変わる可能性を織り込めます。
CLIでの実行
PostmanのGUIで作成したテストをCIに組み込み、自動でテストを実行できるようにします。テストケースは作成できているので容易に実現できます。
newmanの導入
newmanはPostmanで作成した処理をCLIから実行するためのツールです。(参考) npmでインストールできます。
npm install -g newman
作成したテストと変数グループのエクスポート
CLIから実行するためにはコレクションと変数グループのjsonが必要になります。Postmanにはこれらをエクスポートする機能があります。
画面左側のコレクションのメニューから、Export
を選択します。
すると、エクスポートの形式を選択するダイアログが表示されます。recommendedの表示に基づいてCollectionv2.1でエクスポートします。
変数グループは右上の歯車のマークを押下し、MANAGE ENVIRONMENTS
のダイアログから取得します。
どちらもjsonファイルが得られるので、適当なディレクトリに格納します。
newmanの実行
上の手順で取得したコレクションと変数グループのjsonが、以下の通り格納されているとします。
$ ls
Fanship.postman_collection.json integration.postman_environment.json
newman run
コマンドを実行します。以下のようにコレクションと変数グループのjsonをコマンドに渡します。
newman run Fanship.postman_collection.json -e integration.postman_environment.json
すると、コレクションに規定した処理が順次実行されていきます。
(一部省略) ❏ イベント情報連携 ↳ Androidイベント連携 POST ///省略/// [200 OK, 250B, 35ms] ✓ Status code is 200 ✓ Body matches string ↳ iPhoneイベント連携 POST ///省略/// [200 OK, 250B, 31ms] ✓ Status code is 200 ✓ Body matches string ┌─────────────────────────┬──────────┬──────────┐ │ │ executed │ failed │ ├─────────────────────────┼──────────┼──────────┤ │ iterations │ 1 │ 0 │ ├─────────────────────────┼──────────┼──────────┤ │ requests │ 61 │ 0 │ ├─────────────────────────┼──────────┼──────────┤ │ test-scripts │ 143 │ 0 │ ├─────────────────────────┼──────────┼──────────┤ │ prerequest-scripts │ 134 │ 0 │ ├─────────────────────────┼──────────┼──────────┤ │ assertions │ 122 │ 3 │ ├─────────────────────────┴──────────┴──────────┤ │ total run duration: 12.4s │ ├───────────────────────────────────────────────┤ │ total data received: 48.01KB (approx) │ ├───────────────────────────────────────────────┤ │ average response time: 159ms │ └───────────────────────────────────────────────┘ # failure detail 1. AssertionError Body matches string expected '{"status": "NG", "timestamp": "2019/01/31 16:29:17", "result": {"ecode": "E20005", "error": {"en": "Invalid request parameter.", "ja": "\\u4e0d\\u6b63\\u306a\\u30ea\\u30af\\u30a8\\u30b9\\u30c8\\u30d1\\u30e9\\u30e1\\u30fc\\u30bf\\u3067\\u3059"}}, "api_version": "3.0"}' to include '"status": "OK"' at assertion:1 in test-script inside "アプリインストール / android / お知らせ一覧取得" 2. AssertionError Body matches string expected '{"status": "NG", "timestamp": "2019/01/31 16:29:18", "result": {"ecode": "E20005", "error": {"en": "Invalid request parameter.", "ja": "\\u4e0d\\u6b63\\u306a\\u30ea\\u30af\\u30a8\\u30b9\\u30c8\\u30d1\\u30e9\\u30e1\\u30fc\\u30bf\\u3067\\u3059"}}, "api_version": "3.0"}' to include '"status": "OK"' at assertion:1 in test-script inside "アプリインストール / iphone / お知らせ一覧取得" 3. AssertionError Body matches string expected '{"status": "NG", "error": {"message": "UnDocumented Server Error.", "code": "E99999"}}' to include '"status": "OK"' at assertion:1 in test-script inside "配信 / 即時配信参照"
全ての処理が完了すると、テスト結果のサマリに加えエラーがあった場合は詳細が出力されます。
このようにしてPostmanで作成したテストをCLIから実行できます。
例えば弊社で使用しているGitlabCIの場合、.gitlab-ci.yml
にnewman run
の記述を追加しエクスポートしたjsonファイル群を合わせて用意するだけで、CIへのAPIテスト組み込みが可能になります。
まとめ
API開発と検証の生産性向上のためにはとても有用なツールという印象です。Postmanには他にも機能があるので、ぜひ試してみていただければと思います。