Postmanを使ったAPIリグレッションテスト

この記事は[品川Advent Calendar 2019](https://qiita.com/advent-calendar/2019/shinagawa)の２日目です。

# 導入
最近、開発の大部分がAPI開発になってきました。そしてアジャイル開発なんてものをかじっているとどうしてもリグレッションテストの自動化が必要になってくるのですが、色々調べたらPostmanが便利そうなんでご紹介します。


## 長い３行で
[APIのテストやるならPostmanが便利だよ](#apiのテストやるならpostmanが便利だよ)
[シナリオテストもできるよ](#シナリオテストもできるよ)
[CIに組み込みたいならNewmanっての使うとできるよ](#ciに組み込みたいならnewmanっての使うとできるよ)

## APIのテストやるならPostmanが便利だよ
ダウンロードとかインストールは省略。起動できたところから解説。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/607ac3c2-07a4-6856-2d39-69d9a2358306.png)

####とりあえずCollectionを作る
CollectionはAPIの固まりです。簡単に他人にシェアしたり、後述するシナリオテスト時にまとめて実行することができます。Collectionの中にCollectionを作ることはできませんが、より分類したいあなたはCollectionの下にフォルダを作ることができます。フォルダの下にフォルダを作ることもできます。

<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/b552d928-b69e-a9f9-6515-8c3a033861d5.png">


####リクエストを作る
Collectionが作れたらリクエストが作れます。
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/e9fbb691-7d99-13e0-354d-9fd7fbd20ecc.png">


送り先のurlやリクエストのメソッド、Bodyなどを指定して送ると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/2a4f14fa-85d4-759f-9de9-75ce24b4f654.png)

ちゃんと値が帰ってきました。もうこれでPostmanマスターですね。

####テストを作る
ここまでは下準備です。ここから本当にやりたかった、APIのテストを作っていきます。
テストタブをクリックすると真っ白なテキストボックスが出てきます。ここにテストを書いていくのですが、多分初見だと書き方がさっぱりわからないので、右側にあるスニペットを使いましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/35ecbde7-e399-b8e6-5eb9-c795a99fc1d4.png)

今回はスニペットの中にある`Response Body: JSON value check`を参考に作ってみます。

```js
pm.test("createUser Test", function () {
    var jsonData = pm.response.json();
    //レスポンスのnameの値がばやしだったら成功
    pm.expect(jsonData.name).to.eql("ばやし");
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/4bc2b7f7-db95-e0e0-d05b-77b973b6a214.png)

成功しました。今回はbodyの中身しか試験していませんがステータスコードなど他にも様々な試験ができます。他にもスニペットありますし、[公式サイト](https://learning.getpostman.com/docs/postman/scripts/test-scripts/)に書き方も乗っているので色々と見てみると良いと思われます。これで一応テストは出来た！

####環境変数を使う
開発やっていると同じシステムでも複数の環境に存在することってありますよね。あるある。urlとかログイン用のユーザ名とか手で書き直すのはやりたくないわけで、そんな人のためにEnvironmentsという機能があります。

右上の設定ボタンを押して

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/02d00184-a8b4-95a5-5021-70f0b24fc150.png)

環境名と値を設定すればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/fbba89da-d13b-d649-86e7-caa9d0b72b7d.png)

今回はurlを環境変数として定義します。initial valueはその名の通り初期値、current valueは現在その変数に入っている値です。そう、つまり環境変数は途中で書き換えることが出来ます。

定義した環境変数は```{{}}```で囲むことで使えます。あと、現在どの環境を使っているかの切り替えをお忘れなく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/04cc4139-8cf2-29f7-8d96-d9095efc94bc.png)

## シナリオテストもできるよ
単体のAPIテストは出来るようになりました。でもリグレッションテストやる場合は、シナリオテストがやりたいですよね。もっと言うと先に送ったAPIのレスポンスを次のAPIのリクエストに使いたいですよね？それも環境変数を使うことでなんとかなります。

#####今回のシナリオ
ユーザを作る(createUser)
↓
自動付与されるユーザIDを使って新しく作られたユーザが商品を買う(createOrder)

####環境変数を使ってリクエスト間を跨ぐ値のやり取り
とりあえず空の環境変数を用意します。今回はユーザ作成時に自動付与されるユーザIDを使いたいので、```user_id```を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/a1c5e396-e016-eba0-f562-4d5b54815ef8.png)

空の環境変数が用意できたら、値の引き継ぎ元(createUser)のリクエストのテストタブに行き、こんな感じで書いてください。

```js
//他でも使うから外出し
var jsonData = pm.response.json();
pm.test("createUser Test", function () {
    pm.expect(jsonData.name).to.eql("ばやし");
});
//環境変数にレスポンスのidを代入
pm.environment.set("user_id",jsonData.id);
```

実行してみた後に、環境変数を確認すると設定した際には空だったcurrent valueに値が入ってますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/4414383d-0d6c-1889-aed2-8ee8135b017b.png)

いちいちcurrent value確認するのが面倒だと言う方はconsole機能もあるためそっちで確認するのもまた良いと思われます。


```js
console.log(pm.environment.get("user_id"));
```

Postmanのコンソールの出し方はメニューバーの```view```から```Show Postman Console```でいけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/f6c71ccf-dcf6-3547-06bf-b82620aa6a3c.png)

console画面を開くのが面倒だという方は、試験に表示させたい値を混ぜ込むこと同一画面上で確認もできます。

```js
tests["env user id = "+ pm.environment.get("user_id")] = true;
```

余談が過ぎました。
受け取り側(createOrder)は上で記述した環境変数にアクセスできます。

```js:requestのbody
{
  "item": 1,
  "user": {{user_id}},
  "number": 3
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/7f84cdf0-bba6-9835-fe1f-c5ea7a4d2309.png)

####Collectionsの中のテストを一度に実行する
はい、値の引き継ぎも出来るようになりました。さて、今回は２つのAPIしかテストしていないので、手でポチポチ入力してもいいですけど、何十何百ってAPIをテストするのは手ではちょっとやってられませんね。もし宜しければテストの固まりを一度に実行してくれると楽ですね。と言うことでCollection Runner機能を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/85be1c1d-f580-5123-3682-bd2d5da1437c.png)

Runボタンを押すと違う画面が開きますね。これがCollection Runnerです。デフォルトではCollectionの中のリクエストが全て選択されていると思うので、そのままRun [Collection名]ボタンを押してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/29be59ed-05bf-f286-22ed-0bad6584d74d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/c9b7f38a-185b-f5fb-ba51-f5b85c6cb0ca.png)

これで複数テストを一度で実行できるようになりました。
ここまで来るとリグレッションテストも大分楽にできそうですね。ただ人間の欲とは恐ろしいもので、ここまで来ると事前にテストデータを用意してバリエーション試験やりたくなりませんか？動的にパラメータを変えながら試験したくなりますよね。csvファイルやjsonファイルで試験データを定義できるやり方もあるんでご紹介します。

####csvで試験データを定義する
Collection Runnerでテストを実行する際に、試験データをインポートすることでそのデータを用いて試験を実行することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/58ae7d28-d9be-32bf-8677-e26d844e0edb.png)


こちらがcsvです。

```csv:testdata.csv
name,postcode
ばやし1,0000001
ばやし2,0000002
```

csvで定義したデータへのアクセスは環境変数と同じように```{{name}}```みたいな感じで指定することができます。csvで定義した列数分だけ実行され、1度目のnameの中には「ばやし１」2度目のnameの中には「ばやし２」が入ります。当然毎回レスポンスが変わってしまうため、そこもテストデータの中に含めるかテストスクリプトの中で工夫をする必要があります。

```js
//他でも使うから外出し
var jsonData = pm.response.json();
pm.test("createUser Test", function () {
    //イテレーション数を固定値の後に結合
    pm.expect(jsonData.name).to.eql("ばやし"+pm.info.iteration);
});
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/af44bc2c-e6e1-2fc4-fc9e-13bc5ac6eefd.png)

これでテストデータを外部に定義して、バリエーション試験ができるようになりました。もう怖いものなしですね。
ただこれまでの内容は全てGUIベースなので、CIに組み込んでコミットの度に自動実行とか、デプロイの度に自動実行とかが出来ませんね。

## CIに組み込みたいならNewmanっての使うとできるよ

さすがPostman、CUI版も用意してあります。その名もNewman。
Postmanで作成したテストをJSONで吐き出し、Newmanで実行するだけです。

Collectionをエクスポート。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/e4d58430-fe46-33be-e8bf-e25986282447.png)

環境変数を使っている場合は、Environmentsもエクスポートしておくのをお忘れなく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102837/b43f25df-fad9-8351-d48a-78c28b71ba82.png)

実行環境でnewmanを```npm install```

```sh
$ npm install newman
```

```node_modelues/.bin/newman run```で実行ができます。
私はローカルにしか```npm install```していませんが```-g```オプションをつければそのまま```newman run``でもいけます。

```-e {environment.json}```と```-d {data.json}```をつけることをお忘れなく。


```sh

$ node_modules/.bin/newman run Sample.postman_collection.json -e Sample.postman_environment.json -d testdata.json
newman

Sample

→ createUser
  POST localhost:3000/users [200 OK, 306B, 79ms]
  ✓  createUser Test

→ createOrder
  POST localhost:3000/orders [200 OK, 300B, 10ms]
  ✓  createOder Test

┌─────────────────────────┬───────────────────┬──────────────────┐
│                         │          executed │           failed │
├─────────────────────────┼───────────────────┼──────────────────┤
│              iterations │                 1 │                0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│                requests │                 2 │                0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│            test-scripts │                 2 │                0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│      prerequest-scripts │                 0 │                0 │
├─────────────────────────┼───────────────────┼──────────────────┤
│              assertions │                 2 │                0 │
├─────────────────────────┴───────────────────┴──────────────────┤
│ total run duration: 167ms                                      │
├────────────────────────────────────────────────────────────────┤
│ total data received: 116B (approx)                             │
├────────────────────────────────────────────────────────────────┤
│ average response time: 44ms [min: 10ms, max: 79ms, s.d.: 34ms] │
└────────────────────────────────────────────────────────────────┘

```

成功しました。あとはお好みのCI環境に組み込んで、使ってみてください。
それではみなさん、良いリグレッションテストライフを。


### 余談のテストスクリプトの中で使える値TIPS
```{{$guid}}```: ランダムでguidの形式のデータが入っています
```{{$timestamp}}```: 今の時間のデータが中に入っています
```{{$randomInt}}```: 0から1000の間の数字がランダムで入ってます