Insomniaの3つのモードを触ってみる

[Insomnia](https://github.com/Kong/insomnia)(直訳：不眠症)はOSSのAPIクライアントで、元々は[Greg Schier](https://github.com/gschier)という人が立ち上げたOSSであり、[2019年にKongが買収](https://konghq.com/blog/news/kong-acquires-insomnia)した後はKongが主体で開発している。
このAPIクライアントは以下のような特徴を持っている。

- 対応プロトコルが豊富（GraphQL, REST, WebSockets, Server-sent events (SSE), gRPC, HTTP互換）
- APIのデバッグ、設計、テストに利用できる
- CLIを使うことでリンティング（コードの静的解析）やテストをCI/CDパイプライン内で実施できる
- プロジェクトの共有
- クラウドやGitとの自動同期

ここではそれぞれの特徴は掘り下げず、Insomniaが持つSpec、Collection、Testという3つのモードをそれぞれ触って、どういう特徴を持つものかを確認する。
なお、触る際の教材として[Kong Academy](https://education.konghq.com/dashboard)の"(KDLL-203) Designing & Testing APIs with Kong Insomnia"を使ったため、ここで記載する内容はそれに沿った内容となる。

## 本記事の要約
Insomniaの3つのモードは以下の通り。
- Spec：YAML形式でAPIの仕様を作成、編集でき、Linterや簡単な動作確認も出来る。
- Collection：Specで作成したAPIのリクエストをまとめて管理でき、BodyやHeader、認証方法などを微調整しながら動作確認出来る。様々な言語のコードにも変換出来る。
- Test：Collectionのリクエストを元にテストを実施できる。テストコードを自動生成し、カスタマイズして実行出来る。

APIの仕様を書いてしまえば実装からテストまで自動生成でき、かつその仕様作成についても補助機能を提供している、というのがInsomniaの特徴となりそう。
APIを使った実装をするなら、とりあえず使っておけレベルで便利そうだとは思う。

## 事前準備
### Insomniaのインストール
インストーラはWindows、Mac、Linux版がそれぞれ用意されている。
[Download Insomnia](https://insomnia.rest/download)にアクセスすると自分のアーキテクチャにあったバイナリがダウンロードできる。
自分のアーキテクチャと異なるものをダウンロードしたい場合は[Releases](https://github.com/Kong/insomnia/releases)から取得できる。
また、Macユーザであればbrewでもインストール出来る。
```
brew install --cask insomnia
```
インストール後、アプリケーションを起動すると以下のようなアカウントと紐づける画面が出る。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/b25a12eb-61ab-90a4-7023-31d0db16eb22.png" width="400">

ここではGitHubと連携して進める。
連携するとE2EEのためのパスフレーズを聞かれるので設定する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/259a933d-fc6e-b265-74bb-eee99bd88685.png" width="400">


その後にサブスクリプションのプランを聞かれる。ここではFreeで進める。
![1707807439705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/1526fef7-3b31-a08e-79e2-63403179a34b.png)
なお、有料版だと認証認可、SSO連携、AIによるテスト作成支援などが使える模様。
[ここ](https://insomnia.rest/pricing)に比較表があるので、興味がある人は見てみるとよい。
クライアントアプリを立ち上げ直し、GitHubのSSOでログインする。

### 学習用サンプルの導入
今回は試すことが主目的なので、1から作らずに出来合いのものを使って試していく。
ここではKongの学習教材のリポジトリ[kong-edu-insomnia](https://github.com/kong-education/kong-edu-insomnia)にあるBanKongという仮想の銀行サービスを使う。
これを手元にcloneしておく。
```
git clone https://github.com/imurata/kong-edu-insomnia.git
cd kong-edu-insomnia
```
サンプルの中のBanKongサービスを起動する。Docker daemonが稼働している必要があるので注意。
```
docker compose -f ./bankong/docker/docker-compose-bankong-combined_local_portchange.yaml up -d
```
起動した後に[http://localhost:29080](http://localhost:29080)にアクセスするとフロントエンドのWebサービスが確認できる。
また、[http://localhost:3000](http://localhost:3000)にアクセスするとバックエンドのサービスが確認できる。
 
## 検証
最初に新しくProjectを作成する。
Filterの右横の`+`をクリックする。
![1708519539387.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c6b71daf-2175-4566-c00e-5a23c668e0d3.png)

BanKongというProjectを作成する。ここではCloudを使わない形で進めたいのでProject typeは`Local Vault`で進める。
![1708520384158.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/543252f1-2f51-97b5-fa81-8269f99b0ada.png)


空のProjectが作成された後、先程cloneしたリポジトリ内にあるProjectを取り込む。
Projectの取り込み方法は以下のいずれかから選択する。
![1708521609538.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/88c72616-6325-e66c-6d8d-c1c1e08ed2f1.png)

ここでは`Import`で進める。
`Import`ではInsomnia、Postman、Swagger、[OpenAPI](https://spec.openapis.org/)等様々なフォーマットのAPIを取り込む事が出来る。
cloneしたリポジトリ内にOpenAPIで定義されたYAML(`./bankong/openapi/bankong-v1.0.5.yaml`)があるのでこれを読み込む。

以上で準備はOKなので、InsomniaのSpec、Collection、Testの各モードを検証していく。

## Specモード
SpecモードではAPIの仕様の編集・確認を行う事ができる。
`Import`して表示された項目をクリックし、上の`SPEC`をクリックすると仕様が表示される。
![1708522060845.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/88ba9672-50ae-c438-9826-49074d661668.png)

なお、右側にPreviewが表示されているが、表示させたくない場合は左サイドバーのSPECの横の`👁‍🗨Preview`をクリックすれば非表示に出来る。
また、Preview画面からは実際にAPIを発行することも出来る。
![1708523560326.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c754f423-f8e8-b061-3e1c-79d7ea3c4fdc.png)

エディタ側に戻ると、⚠マークが出ているのが確認できる。
InsomniaにはLinterも備えていて、問題箇所を自動的に指摘してくれる。
![1708523901600.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c40fd3ba-92d9-c9fb-d2e3-9da8fb5a705d.png)

ここでの指摘内容は以下となっている。
- info内にcontactが含まれない
- servers.urlの末尾がスラッシュで終わっているが、スラッシュは不要
- getやpostで使っているタグの定義がGlobalに存在しない

それぞれ修正すると、以下のように`No lint problems`と表示されて警告表示が消える。
![1708524605088.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/7a30f7ef-29ac-c2f2-3e13-86b77d407079.png)

このような感じでSpecモードではAPIの仕様を編集・確認することが出来る。

## Collectionモード
`SPEC`の横のギアマークから`Generate collection`をクリックすると、Specの内容を元にAPIリクエストのセットが`COLLECTION`内に作成される。
![1708589425160.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/d0792b46-73b6-bdd6-1d55-f87a34a000f2.png)

`COLLECTION`に移動しそれぞれのリクエストを見ると、上部に`_.base_url`や`_.id`のような赤くハイライトされた表示が確認できる。
![1708590438896.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/487719df-ba6e-e421-0c15-d876b5c30a72.png)
これは[環境変数](https://docs.insomnia.rest/insomnia/environment-variables)であり、現在は`base_url`と`_.id`いう環境変数がColletion内で利用しているにも関わらず定義されていないため警告表示となっている。
環境変数は左サイドバー内の`Base Environment`の右のギアマークをクリックすると、`Manage Environment`という画面に遷移し、ここで設定することが出来る。
`Manage Environment`で`Base Environment`の右の`+`をクリックすると、`Shared environment`と`Private environment`の選択肢が表示される。
![1708603851211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/9f529841-2aa4-a106-7480-d002ead823d9.png)

これはそれぞれ以下の意味となる。
- `Shared environment`: Export可能な環境変数
- `Private environment`: Export出来ない環境変数

名前の通り、共有するかどうかで使い分けると良さそう。
ここでは`Shared environment`で環境変数を定義する。
OpenAPI envの環境変数をコピーし、`base_url: {{_.host}}`を追加する。
`id`については個別のトランザクションを指定するためのもので、[http://localhost:3000/transactions/](http://localhost:3000/transactions/)にアクセスすると登録済みのトランザクション全件が閲覧でき、個別のトランザクションについては[http://localhost:3000/transactions/\$id](http://localhost:3000/transactions/$id)で閲覧できるようサンプルのサービスが用意されている。
ここでは最初から登録されている`143aadce-f995-4503-ba6e-01ed01c6af88`を設定した。
また、新規作成した環境変数には名前をつけられるので、ここではlocaldevとした。
![1708931792915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/e26c3839-24eb-0da8-df4d-96b911f974ec.png)

Collectionの画面に戻って、GETの`Get Specific transaction`から`Send`を実行すると以下の右側のような感じでレスポンスコードとBodyを取得できる。
![1708931854977.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/7de469ea-a62a-3bf7-5c3a-4eccb841bd42.png)

また、POSTの`Create new transaction`から新しいトランザクションを作ることも出来る。
POSTの際はボディのフォーマットをJSONからYAML等に変更したり、認証方法をAPIキーだけでなくBasic AuthやOauthに変更することも出来る。
またクエリやヘッダーも編集出来るので、確認したい内容によって書き換えると良さそう。
![1708932409039.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/501b78b7-a055-8aa8-ef8c-b413f2577c99.png)


### Patchの実装
上記のPOSTを実行するとID:42のトランザクションが生成されるが、これを以下のようの変更したい。
```json:変更前
	{
		"id": 42,
		"source": "GR872659435350353",
		"senderName": "Max Mustermann",
		"destination": "DE8412325587359375895",
		"amount": 42,
		"currency": "EUR",
		"subject": "Invoice #42-08/15"
	}
```
```json:変更後
	{
		"id": 42,
		"source": "GR872659435350353",
		"senderName": "Max Mustermann",
		"destination": "DE8412325587359375895",
		"amount": 100,
		"currency": "USD",
		"subject": "Invoice #42-08/15"
	}
```
これを行うために、Patchを実装する。
Specモードに切り替えエディタ画面を確認すると、89行目から114行目にpatchの実装がコメントアウトされていることが確認できる。
これをアンコメントする。
VSCodeと同じショートカットが使えるので、Macの人は選択してCommand+スラッシュ、Windowsの人はCtrl＋スラッシュでアンコメント出来る。
なお、`patch:`のインデントの位置が少しずれているため赤い波線が出る。
`patch:`の前のスペースを1つ消せば正常な位置になる。
正常にpatchが追加できれば、PATHSのところに`PTCH`とPatchが表示されるようになる。
![1708934173126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/8281fa46-a3cb-7c19-dfea-b49e0825e204.png)
次にCollectionモードに戻り、Patchのリクエストを追加する。
自動生成機能を使う場合、Specモードで`SPEC`の右のギアマークから`Generate collection`をクリックすると生成できるが、今回は手動で生成する。
![1708934478543.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/1c5bcef2-b99a-3a65-a606-0b2d13b3543e.png)

Collectionモードで左サイドバーの`Transaction`の右の▽をクリックして`HTTP Request`を追加する。
![1708934293593.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c96f5314-0e1e-2c7f-01df-5aabb451d273.png)
名前を`New Request`から`Patch a transaction`に変更する。
次に画面上部の`GET ▽`となっているところをクリックして`PATCH`に変更する。
次にその横のパスを指定する。ここでアンダースコア(_)を入力すると自動で候補が出てくるので、Patchを当てる対象となるトランザクションである`{{ _.base_url }}/transactions/{{ _.id }}`を選択する。
ただ、`id`はlocaldevのものを引っ張ってきているので、`URL PREVIEW`には`http://localhost:3000/transactions/143aadce-f995-4503-ba6e-01ed01c6af88`が表示され、書き換える対象は先程Postしたものと異なってしまう。
そのためここでは一旦ベタ書きでidを上書きし、`42`を指定する。
![1708935292574.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/d5067cf3-da52-9e2b-c88e-168c66a5bfb8.png)
次に`Body`のタブを選択してJSON形式で上書きする内容を記入する。
```json
	{
		"id": 42,
		"source": "GR872659435350353",
		"senderName": "Max Mustermann",
		"destination": "DE8412325587359375895",
		"amount": 100,
		"currency": "USD",
		"subject": "Invoice #42-08/15"
	}
```
以上でPatchの準備が整ったので、`Send`をクリックしてPatchを当ててみる。
適用後、GETの`List all transactions`で変更後の値を確認すると書き換わったことが確認できる。
問題なければ、ここで確認した内容をコードにすることが出来る。
リクエストの横の▽をクリックすると、`Generate Code`というのが選択できる。
![1708936150930.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/d84b0951-9643-2c51-b860-3004de000b25.png)
選択後、 言語やライブラリを選択すると、以下のような感じでコードが出力される。めちゃくちゃ便利。
![1708936409382.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/9e60c125-8c69-d1a9-6d30-b335b53d3e4d.png)


## Testsモード
TestsモードではCollectionにあるリクエストを使ってテストを行うことが出来る。
まず、上部の`TESTS`をクリックしてTestsモードに切り替え、左サイドバーの`New test suite`をクリックし、新規作成されたテストスイートの名前を`Unit Test Suite`に変更する。
次に上部の`New test`をクリックする。すると`Returns 200`と書かれたテストの雛形が作成される。
![1709008772072.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/9a785e7d-b381-3e5c-205f-9c92d9a75a48.png)

ここでは全てのトランザクションを取得するリクエスト（GETの`List all transactions`）のテストを作成する。
まず作成したテストの雛形の名前を`List All Transactions Returns 200`に変更する。
次に、横の`Select a request`をクリックすると、Collection内のリクエストの一覧が表示されるので、GETの`List all transactions`を選択する。
作成後、更に右にある再生ボタン（▷）をクリックすると、テスト結果が表示される。
![1709009139841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/238dfa32-c1f5-55ec-9393-d923488f95fa.png)

クリックするとテストコードが確認できる。

```js
const response1 = await insomnia.send();
expect(response1.status).to.equal(200);
```
なお、テストコードはJavaScriptのテストフレームワークであるMochaとChaiで書かれている。詳細は[こちら](https://docs.insomnia.rest/insomnia/unit-testing)。
同じように`Get Specific Transaction`も追加して確認する。
![1709012053787.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/531ecbf1-fbe3-9c61-6baa-7204481a130d.png)

せっかくなので少しテストをカスタマイズしてみる。
`Get Specific Transaction`のBodyをチェックするように書き換える。
```js
const response1 = await insomnia.send();
expect(response1.status).to.equal(200);
const body = JSON.parse(response1.data);
expect(body).to.have.all.keys('source', 'senderName', 'destination', 'amount', 'currency', 'subject', 'id');
```
これでテストを再度実行すると、やはり`Passed`となる。
テストに失敗するよう、`'id'`を消してみると以下のようにテストに失敗した。
![1709012572721.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/4b8e00e8-d614-f29a-f084-6e3eb2a3e106.png)

このように、TestモードではAPIのテストを作成・管理できることが確認できた。

## 所感
要約のところにも書いたけど、設計からテストまで一通り補助する機能があるのは非常に便利。
特に自動生成周りは初めて開発する人のハードルを下げてくれるので、特に慣れたツールとかなければ使ってみるとよいかと思う。
今回はCLI周りは触れなかったが、機会があれば触ってCI/CDパイプラインに組み込んでみたいと思う。