アイリッジ開発者ブログ

アイリッジに所属するエンジニアが技術情報を発信していきます。

Postmanを利用してAPIテストを自動化する

こんにちは、アイリッジ プロダクト開発グループの神原です。主に自社サービスであるFANSHIPの機能強化を担当しています。

FANSHIPではプッシュ通知の配信に関わる様々な機能をAPIとして提供しています。 以前、PostmanというGUIのツールを用いて、FANSHIPのAPIの網羅的なテストを作成してCI/CDへ組み込み自動化する取り組みを行いました。この記事では、作成したテストの例も交えながらPostmanの機能や使用法をご紹介いたします。

導入方法

公式のダウンロードページからダウンロードして使用できます。Mac、Windows、Linuxの各OSで使用可能です。また、MacであればHomebrew-caskでの導入も可能です。

使い方

リクエストの作成

リクエストを作成するには、画面左上のNewをクリックして表示されるダイアログからRequestを選択します。リクエスト名と保存先(Postmanではコレクションという単位で管理されます)を指定して一旦保存します。

これで以下のようにリクエストを作成する雛形ができました。

f:id:iridge-tech:20190419120039p:plain

とりあえず、URLに適当なものを入力してSendを押下すると、これだけでリクエストを送信できていることがわかります。レスポンスボディ、ヘッダなどは画面下側で参照できます。

f:id:iridge-tech:20190419153859p:plain

実際にAPIをテストする場合には、リクエストヘッダ、ボディ、認証情報などが必要なケースが当然あります。その場合には、ParamsAuthorizationHeaderBodyの各タブに値を設定すればOKです。

FANSHIPの認証APIを叩くために作成したリクエストは以下のようになっています。HeaderタブにはKeyとValueの組を入力し、Bodyタブにはjson形式でリクエストボディーを記述しています。Bodyタブについては、入力形式をラジオボタンで選択できます。

f:id:iridge-tech:20190419154057p:plain f:id:iridge-tech:20190419154127p:plain

なお、上に示したキャプチャでは右上に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に記述したスクリプトが実行され、以下のようにテスト結果が表示されます。

f:id:iridge-tech:20190419154556p:plain

なお、Testsタブ右側のSNIPPETSには、何パターンか用意されているテストコードを活用できます。まずはここを見て、実施したいテストがあるか確認するのがよいでしょう。

変数の管理

このようにして作成したテストですが、変数グループを作成して複数の環境で使い回せます。画面右上の歯車マークをクリックするとMANAGE ENVIRONMENTSのダイアログが開きます。ダイアログ右下のAddを押下し、変数のグループを作成します。

f:id:iridge-tech:20190419154643p:plain

例としてapi_iridge_intgという名前の変数グループを作成し、hosttokenという環境変数とその値を定義しました。{{host}}, {{token}}のように、波括弧2つで囲むとこれらの変数の参照が可能です。

この変数グループをコピーして、api_iridge_stgという名前の変数グループを作成してみます。 api_iridge_intgと同様に、hosttokenという変数を定義していますが、値を変えています。

f:id:iridge-tech:20190419164214p:plain

このように変数グループを作成しておけば、テストケースの使い回しが可能になります。以下のように、リクエストURLに{{host}}と記述しておくと、変数グループの切り替えに応じたURLへリクエストを投げられます。

f:id:iridge-tech:20190419154817p:plain f:id:iridge-tech:20190419154840p:plain

画面右上のプルダウンから選択するだけで変数グループを切り替えられるので簡単です。

テスト作成の事例と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を選択します。

f:id:iridge-tech:20190419154951p:plain

すると、エクスポートの形式を選択するダイアログが表示されます。recommendedの表示に基づいてCollectionv2.1でエクスポートします。

f:id:iridge-tech:20190419155012p:plain

変数グループは右上の歯車のマークを押下し、MANAGE ENVIRONMENTSのダイアログから取得します。

f:id:iridge-tech:20190419155104p:plain

どちらも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.ymlnewman runの記述を追加しエクスポートしたjsonファイル群を合わせて用意するだけで、CIへのAPIテスト組み込みが可能になります。

まとめ

API開発と検証の生産性向上のためにはとても有用なツールという印象です。Postmanには他にも機能があるので、ぜひ試してみていただければと思います。