PostmanのTestsでリグレッションテストをつくってみた

## はじめに
ドコモでRAFTELという社内向けの共通API基盤の開発を担当している中島です。
本記事ではRAFTELチームで取り組んでいる、API開発でPostmanを利用した取り組みについて紹介します。

## RAFTEL（サービス共通API基盤） とは
NTTドコモではLeminoやdマガジンなどの大規模サービスを多数提供しています。RAFTELはこのようなサービスを高速に低コストで実装・開発するためのAPI基盤です。
私たちはドコモのサービス開発を「はやく」「やすく」するために以下の取り組みを行ってます。
- 複数の社内基盤をRAFTELに一本化し各部署への調整。申請の負担軽減！
- 仕様書フォーマットを統一し学習コストを軽減！
- ドコモのサービスが共通的に使う機能をマッシュアップAPIでまるっと提供！
- 社内基盤のAPI更新はサービス共通API基盤が吸収

サービスの接続先が1つになったことで、社内基盤を効率よく活用できるようになります。

![RAFTEL（サービス共通API基盤とは）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634735/b5b280db-e78a-d100-15cf-506ffe0aad81.png)



## RAFTEL（サービス共通API基盤）開発での課題

サービス共通API基盤の開発過程で、Postmanを利用していました。
- 他システムへのAPIリクエスト
- 開発中のAPIの動作確認
- デグレが無いか確認

リクエスト電文や結果など、試験した人だけではなくチーム内で共有できるところがいいなと思っています。
その中で大変だと感じたところは、APIのテストでレスポンス内容の確認を目視で行っていたため、確認項目が多く、テスト実施に時間がかかってしまうところです。
そこを解消するべく、PostmanのTestsでリグレッションテストを自動化してみました。


## Postman Testsとは？

以下のような、レスポンスの妥当性を検証するテストをJavascriptで作成できます。
- APIが期待通りに動作していること
- 変更によって既存の機能が損なわれていないこと（デグレ確認）

テストコードを記述する工数がかかりますが、テスト実施の時間が短縮できるメリットの方が大きいと感じたため、リグレッションテストを作成しました。

作成の際には、以下のサイトを参考にしました。

- [Write API test scripts in Postman](https://learning.postman.com/docs/writing-scripts/test-scripts/)


## リグレッションテストの確認観点

### テスト観点

リグレッションテストを実施するにあたり、以下のようなテスト観点が挙がりました。
- 過去（改修前）のレスポンスと一致しているか
- レスポンスで返却される項目に不足がないか
- レスポンス毎にユニークな値が返ってくる項目については、正規表現などで型・桁・フォーマットチェックを行い、確認する


### テストケース

テスト観点に沿ったテストケースは以下になります。
- 正常系
- 準正常系（対向システムからのエラー返却）
    - RAFTEL（サービス共通API基盤）の仕様によるもの
- 4XXエラー系（バリデーションエラーなど）


## 作成したリグレッションテストのサンプル

正常系のリグレッションテストのサンプルです。
※準正常系（対向システムからのエラー返却）、4XXエラー系（バリデーションエラーなど）のテストは、こちらのサンプルを参考に作成しているので割愛します。

テストするAPIのレスポンスが、以下の内容だったとします。

```javascript
{
    "id": "0123456789abcdefghij"
}
```

リグレッションテストでは、以下の項目についてデグレ確認を行います。
- 共通仕様の項目
    - HTTP ステータスコード：`200`であること
    - レスポンスヘッダーの`Content-type`：`application/json;charset=UTF-8`であること
    - レスポンスヘッダーの`X-Transactionid`：フォーマットが正しいこと

- 各API毎の項目
    - 仕様書通りのレスポンスになっていること
        - レスポンスボディの内容が想定した値と同等であること

PostmanのTestsに、テストケースを記述していきます。

```javascript
// HTTPステータスコード
const success = 200;

// レスポンスヘッダーのContent-Type
const successContentType = "application/json;charset=UTF-8";

// レスポンスボディの想定した値
const successResponseBody = {
    "id": "0123456789abcdefghij"
};


// 共通仕様
// 正常系の場合
pm.test("共通仕様のテスト（正常系）", () => {
  pm.test("ステータスコードが 200 で成功", function () {
    pm.response.to.have.status(success);
  });
  pm.test("レスポンスヘッダー：Content-Typeの値が application/json;charset=UTF-8 であること", () => {
    pm.expect(pm.response.headers.get('Content-Type')).to.eql(successContentType);
  });
  pm.test("レスポンスヘッダーのトランザクションIDフォーマットチェック", () => {
    pm.expect(pm.response.headers.get("X-Transactionid")).to.match(/^[0-9a-zA-Z]{32}$/);    
  });
});

// 各APIの仕様：仕様書通りのレスポンスになっているか
// 正常系の場合
pm.test("仕様書通りのレスポンスになっているか", () => {
    const responseJson = pm.response.json();
    pm.test("レスポンスボディの内容が想定した値と同等であること", () => {
        pm.expect(responseJson).to.eql(successResponseBody);
    });
});
```

### レスポンスの内容が一致するかをテストする
レスポンスの内容が一致するかをテストする一例です。
レスポンスボディの値が想定した値と同等であるかを、`to.eql()`を使用して確認します。
```javascript
const successResponseBody = {
    "id" : "0123456789abcdefghij"
}

pm.test("レスポンスが一致しているかテスト", () => {
    const responseJson = pm.response.json();
    pm.test("レスポンスボディの内容が想定した値と同等であること", () => {
        pm.expect(responseJson).to.eql(successResponseBody);
    });
});
```

### 正規表現になっているかをテストする
正規表現になっているかをテストする一例です。
レスポンスの項目：`id`のフォーマットが半角英数字20桁であるかを比較するため、`to.match()`を使用して確認します。
「デグレ確認」でフォーマットチェックは必要だと思うので、レスポンスの項目ごとに記述すると良いかと思います。


```javascript
const responseJson = pm.response.json();
pm.test("idのフォーマットチェック", () => {
    pm.expect(responseJson.orders[0].id).to.match(/^[0-9a-zA-Z]{20}$/);
});
```

テストケースの作成には、以下のサイトを参考にしています。
- [Use predefined variables to return values](https://learning.postman.com/docs/writing-scripts/script-references/variables-list/)
- [Test script examples](https://learning.postman.com/docs/writing-scripts/script-references/test-examples/)

これらを組み合わせると無限に書けそうです。


## リグレッションテストの実施方法
リクエストをSendすると同時にリグレッションテスト（Tests）が実行されます。
また、リグレッションテストだけを一括して実行したい場合は、「Runner」を使用すると「Collection」や「Folder」単位でテストが可能です。

「Collection」を選択した後、右上の「Run」ボタンをクリックします。

![202312_Postman_test_image01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634735/c893ac64-a122-0876-3884-ea5cd1e10a41.png)


「Collection」に格納されているAPIが一覧表示されます。
テストをしたいAPIのみ選択することも可能です。
チェックを入れた後、右下の「Run」ボタンをクリックするとテストが実行されます。

![202312_Postman_test_image02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634735/95eb6324-f3b6-2954-05ef-5701b9d45d41.png)

テスト結果がそれぞれ出力されました。
テストが失敗した場合には、「PASS」が「FAIL」で出力されるので、どのテストケースがうまくいかなかったのかがひと目でわかります。

![202312_Postman_test_image03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634735/918e86ee-5a17-57c2-9d5d-7dad7686a3da.png)



テストの実施方法は、以下のサイトを参考にしています。
- [Test your API using the Collection Runner](https://learning.postman.com/docs/collections/running-collections/intro-to-collection-runs/)

API毎に正常系・準正常系のテストをまとめて実施できるので、APIのテスト時間の短縮につながります。


## まとめ ＆ 今後やりたいこと
Postman Testsを利用した結果、テスト実施に数日かかっていたのが、「Collection」でボタンをクリックするだけでテストが出来るようになったので、実施コストが減り、チームでの生産性が上がりました。テストが楽になったと実感しています。
担当者だけではなく、誰でもテストを実施したり、テストケースを追加したり出来るようになったことがよかったです。

今後は、今まで開発したAPIの一部では、テスト実施前に手作業が入るため完全自動化を目指したいです。
※APIを叩く際に順序性があるようなものや、他のAPIの結果をリクエスト項目に使用するものなど

チーム内でメンテナンスするルールもできたので、これからもPostmanのTestsを活用していきたいと思います！