JestでExpressのAPIテスト環境を構築してみた

## 概要
今回は、Jestを利用してExpressで作成したAPIのテスト環境を構築したので、概要だけご紹介です。詳しい環境構築の方法等は、公式サイトのリンクを適宜記載してますので、御覧ください。

## 環境
* Node.js : `v8.11.3`
* npm : `6.5.0`
* sequelize : `4.37.10`
* sqlite3 : `4.0.6`
* Jest : `23.6.0`
* jest-jenkins-reporter : `1.0.2`
* supertest : `3.4.2`

## 利用しているnpmパッケージのご紹介
### 1. Sequelize
Node.js用のORMです。今回は、Sequelizeを使って、DBのマイグレーションから操作まで行いました。 PostgreSQL、MySQL、SQLiteに対応してます。今回は、本番系でMySQLを利用し、テスト用DBにSQLiteを利用しました。   
[Sequelizeの公式サイト](http://docs.sequelizejs.com/manual/getting-started.html)

### 2 sqlite3
OSSのRDBMSで、サーバではなくファイルベースで動作します。MySQLとの完全互換はありませんが、本システムのテストには十分なため、テスト用DBとして利用しました。  
[SQLiteの公式サイト](https://www.sqlite.org/index.html)

### 3. Jest
Jestは、Facebook社がOSSとして開発を進めている、JavaScriptのユニットテストのためのツールです。今回はこのフレームワークを利用して、テストを作成しました。  
[Jestの公式サイト](https://jestjs.io/ja/)

### 4. jest-jenkins-reporter
Jestのテスト結果をJenkinsで集計するためのプラグインです。
[jest-jenkins-reporterの公式サイト](https://github.com/pilipa-cn/jest-jenkins-reporter)

### 5. Supertest
HTTPリクエストとレスポンスのアサーションを簡単に実装できるパッケージです。Jestと組み合わせて、テストを実装します。  
[Supertestの公式テスト](https://github.com/visionmedia/supertest)

## テスト実行環境の構成
以下、簡単なテスト実行環境の構成になります。

![jestによるテスト構成図.png](https://qiita-image-store.s3.amazonaws.com/0/62976/60f9e029-4662-83e5-665c-cc8647d78f29.png)



### 簡単な説明
#### ①テスト用DBの作成、②テスト用データ挿入
Sequelizeには、ORマッパーとしての機能だけでなく、DBのマイグレーション機能があります。この機能を利用して、SQLiteでテスト用DBを作成します。また、以下のように、`config/config.json`によって、環境別でDBを切り替えることも可能です。  

[マイグレーションについて](http://docs.sequelizejs.com/manual/migrations.html)

```config/config.json
{
  "development": {
    "username": "root",
    "password": null,
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}
```

#### ⑦レスポンスをテスト
JestとSupertestによるテストの書き方ですが、以下の記事が参考になりそうです。

[Facebook製のJavaScriptテストツール「Jest」の逆引き使用例](https://qiita.com/chimame/items/e97883fd46b67529d59f)

私は以下のようなフォルダ構成にしています。

```フォルダ構成
root
│
├─__test__ # テストファイル格納フォルダ
│  ｜─hogehogeApi.spec.js # テストファイル
│  ｜─fugafugaApi.spec.js
│  ｜─...
│
│   

```

テストコードの一部も載せておきます。

```javascript
const request = require('supertest');
const server = require('../bin/www');

// テストが終了したら、サーバをクローズする
afterAll(() => {
	'use strict';

	server.close();
});

describe('hogehoge API のテスト', () => {
	'use strict';

	describe('正常系テスト', () => {

    	test('レスポンスが適切な値を持っていることを確認', async () => { 

    		const response = await request(server).get('/api/hogehoge');

    		expect(response.body[0].hogeName).toBe('hogehoge');
    		expect(response.body[0].seq).toBe(1);

    	});

    	test('ステータスコードが200であることを確認', async () => { 

    		const response = await request(server).get('/api/hogehoge');
    		expect(response.statusCode).toBe(200);

    	});
	});
});
```

テストの実行には、以下のコマンドをnpm scriptsに登録して実行しています。`--coverage`オプションを使うと、カバレッジも一緒に出力してくれます。

```
jest --coverage --verbose

```

結果は以下のように出力されます。

```
PASS __test__/hogehogeApi.spec.js
   hogehoge API のテスト
     正常テスト
         ✓ レスポンスが適切な値を持っていることを確認 (131ms)
         ✓ ステータスコードが200であることを確認 (20ms)

・
・
・
-------------------------------|----------|----------|----------|----------|-------------------|
 File                           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
 -------------------------------|----------|----------|----------|----------|-------------------|
 All files                      |     51.6 |    28.32 |    63.72 |    56.06 |                   |
  hogehog                       |      100 |      100 |      100 |      100 |                   |
   express.js                   |      100 |      100 |      100 |      100 |                   |
  hogehoge/bin                  |    56.67 |    33.33 |    66.67 |    56.67 |                   |
   www                          |    56.67 |    33.33 |    66.67 |    56.67 |... 71,73,74,75,77 |
```

#### ⑧jest-Jenkins-reporterでテスト結果出力
package.jsonに、テストの集計結果の出力フォルダなどを設定してます。この出力ファイルをJenkinsで読み込みます。

```package.json
"jest": {
    "testResultsProcessor": "jest-jenkins-reporter"
  },
"jestSonar": {
    "reportPath": "reports",
    "reportFile": "report.xml",
    "indent": 4
}
```


## Jestを使ってみて
* 今まで、テストをするのに複数のパッケージを組み合わせていたが、Jestだけでテストするための主要な機能が揃うのでとても便利。
* ReactのようなViewのテストも実行できるようなので、今後試してみたい。