node.js + GitHub + Travis CI + Code ClimateでCI入門

## はじめに

この記事は、JavaScript開発でCI環境を導入するためのガイドです。
もしCI環境の導入に興味を持ったら、この記事を土台にみなさまの環境にあったCI/CDへ発展させてください。

### 対象となる読者

- JavaScriptで開発をしている
- CIという言葉を聞いたことがある
- テスティングフレームワークを使ったことがない
- バグ修正をしたら別の箇所でバグが出た
- 依存パッケージの更新作業に負担を感じる

この記事は、テスト自動化やCIに興味はあるが、まだ導入したことがない開発者を対象としています。

### 対象とする環境

- node.js 12.18.3
- jest 26.0

## CIとは / テスト自動化とは

[CI (Continuous Integration / 継続的インテグレーション)](https://www.redhat.com/ja/topics/devops/what-is-ci-cd)とは、短期間で開発ブランチを統合し続ける開発手法です。グループ開発では、開発者がそれぞれ作業ブランチを抱えます。その作業ブランチは、定期的に統合しないと細分化し続けます。細分化しすぎたブランチは統合に膨大な作業が必要になる[インテグレーション地獄](https://www.solutionsiq.com/agile-glossary/integration-hell/)を引き起こします。このインテグレーション地獄を回避するために発案された手法がCIです。

テスト自動化とは、ソフトウェアによってテストの設計、実行、報告を支援する取り組みです。テスト自動化に必要なソフトウェアをセットにしたものがテスティングフレームワークです。CIにおけるテストは、作業ブランチが正常に統合できているかを判定します。

テスト自動化はCIを実現するために必須の要素です。CIにおけるテストツールは、開発ブランチが統合されるたびにテストを自動実行し結果を報告し続けます。CIに必要な回数のテストを手動で実行するのは、現実的ではありません。

テスト自動化はCIの実施に必須の要素です。そのためCI環境には必ずテストツールが含まれます。

### テスト自動化の利点

テスト自動化には、以下のような利点があります。

- リグレッションの防止
- 複数環境での動作確認
- CD（継続的デリバリー / 継続的デプロイメント）への発展

#### リグレッションの防止

プログラムを修正すると、思わぬ箇所に影響しバグを発生させてしまう危険性があります。修正により取り去ったはずのバグが再発したり、他の機能が正常に働かなくなることを[リグレッション](http://e-words.jp/w/%E3%83%AA%E3%82%B0%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88.html)や[デグレード](http://e-words.jp/w/%E3%83%87%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89.html)といいます。

テスト自動化はリグレッションの発生を早期に発見し、問題箇所を特定するのに役立ちます。その結果、新機能開発や機能修正の負担を減らします。

プログラムが依存しているnpmモジュールの更新も、リグレッションやデグレードを引き起こします。依存関係が複雑なほどモジュール更新によるリグレッションの発見は難しくなります。テスト自動化はこうした問題の発見と修正作業の負担を減らします。

#### 複数環境での動作確認

複数のプラットフォームをサポートするプログラムの品質を維持するのは大変な作業です。さらにnode.jsの複数のバージョンをサポートすると、テストの工数は掛け合わせで増えていきます。

テストツールは、動作環境の構築を自動化します。そのためテスト工数を圧縮できます。

#### CD（継続的デリバリー / 継続的デプロイ）への発展

CI環境は、CD（継続的デリバリー / 継続的デプロイメント）へ発展できます。

継続的デリバリーは、テストを通じでソフトウェアを本番環境へ展開可能か判定する開発手法です。継続的デプロイメントは、テストに合格したコードを自動的に本番環境へ展開する開発手法です。CDはソフトウェア開発と運用を一体化し、ソフトウェアの更新頻度を向上させます。

## CI環境の構成

本記事では、以下のサービスを組み合わせてCI環境を構築します。

+ リモートリポジトリ : GitHub
+ テスティングフレームワーク : jest
+ CIサービス : Travis CI
+ コードカバレッジ収集 : Quality By Code Climate

### jest

[jest](https://jestjs.io/ja/)はJavaScriptテスティングフレームワークです。テストファイルの作成、実行、テスト網羅率のレポートまでを1つのフレームワークでカバーします。今回はjestを最小限の構成で導入する方法をご紹介します。

#### インストール

[Getting Started](https://jestjs.io/docs/ja/getting-started)

最初に、jestをインストールします。

```bash
npm install --save-dev jest
```

#### テストファイルを書く

つぎにテストファイルを作成します。

プロジェクトルートに`sum.js`というJavaScriptファイルがあり、その中に`sum`という関数があるとします。同じディレクトリに`test.spec.js`を作成し、sum関数をテストします。

*▼sum.js*

```js
function sum(a, b) {
  return a + b;
}
module.exports = sum;
```

*▼test.spec.js*

```test.spec.js
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
```

sum関数に引数`1,2`を与え、戻り値が`3`であればテスト成功、それ以外ならテスト失敗となります。

#### テストの実行

最後に、package.jsonにテスト実行コマンドを追加します。

*▼package.json*

```json
{
  "scripts": {
    "test": "jest"
  }
}
```

`npm run test`でコマンドを実行すれば、テストが実行されて結果が報告されます。

より詳しい導入方法は、こちらの記事を参照してください。

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

### Travis CI

[Travis CI](https://travis-ci.org/)とは、リポジトリの監視、テストの実行、結果の報告を行うCIサービスです。さまざまな言語 / OS / テスティングフレームワークに対応しており、今回はnode.jsとjestの組み合わせでテストを行います。

Travis CIはバプリックリポジトリでは無料で利用できます。プライベートリポジトリのテストは有料サービスとなります。

#### サインイン

まずは[サインインページ](https://travis-ci.org/signin)からGitHubアカウントでサインインします。

![](https://www.evernote.com/l/AAk2T9VFXsRGIKvL48JTRgzRYENr0ZrwJV0B/image.png)

#### リポジトリの追加

つぎにトップページのプラスボタンを押して、テスト対象リポジトリを追加します。

![](https://www.evernote.com/l/AAlALS4PSN1A8befF8t5_UJ7n56S4GbwwBgB/image.png)

パブリックリポジトリの一覧が表示されるので、チェックボックスをONにします。

![](https://www.evernote.com/l/AAktMSxcAbZCbYa-u3SJBSDlaGagNlTM308B/image.png)

これでTravis CIがリポジトリの監視を開始します。Travis CIはmasterブランチにコードがpushされると動き出します。その都度テストが実行され、結果がGitHubアカウントのメールアドレスに報告されます。

#### 設定ファイル

Travis CIはリポジトリのルートディレクトリに配置された`.travis.yml`という名前の設定ファイルにしたがって動作します。node.jsでテストを実行するには、以下の設定ファイルを追加します。

*▼.travis.yml*

```yml
language: node_js
node_js:
  - "10"
  - "12"
  - "14"
```

`language: node_js`を設定すれば、Travis CIが`package.json`を探して`test`コマンドを実行します。`node_js`の中にバージョン番号を追加すれば、Travis CIはそれぞれのnode.jsでテストを並列実行します。

.travis.ymlのより詳しい記述方法は、[公式ドキュメント](https://docs.travis-ci.com/user/customizing-the-build)を参照してください。

ymlファイルに関する詳しい解説は、こちらの記事をご参照ください。

- [YAMLとは何か？ - いつもRailsの設定ファイルで出てくるやつの正体](https://qiita.com/Yama-to/items/587544993fb62610528a)

#### テストの実行

`.travis.yml`をリモートリポジトリのmasterブランチにpushすれば、Travis CIがテストを開始します。

Travis CIは

- 仮想マシンの起動
- 言語環境のインストール
- `package-lock.json`や`yarn.lock`などにしたがって依存モジュールをインストール
- package.jsonの`test`スクリプトを実行
- テスト結果を報告

という手順でテストを実行します。

CIサービスは、テストの実行のたびに初期状態の仮想マシンを起動し、モジュールをインストールします。そのためローカルのテストでは発見しにくい、動作環境に依存するバグも発見できます。

すべてのテストをパスすれば、ビルドの状態を表すバッジの色が緑になります。

![](https://www.evernote.com/l/AAkkU_luQ7RA_JGY-9-p5AUoO7LuCvOj81sB/image.png)

### Quality By Code Climate

Travis CIには、テストがどれだけのコードを網羅しているかを表す[コードカバレッジ](https://www.itmedia.co.jp/im/articles/1111/07/news144.html)を表示する機能がありません。コードカバレッジが低すぎると、リグレッションの発生を見逃す可能性が高くなります。

[Quality By Code Climate](https://codeclimate.com/quality/)は、コード品質を監視、維持するためのオンラインサービスです。今回はこのサービスをTravis CIと連携させ、コードカバレッジを監視します。

Quality By Code Climateも、パブリックリポジトリでは無料で利用できます。

#### サインイン

[Code Climate](https://codeclimate.com/quality/)の「LOGIN」メニューからQUALITYサービスにログインします。

![](https://www.evernote.com/l/AAnPEs5G9mZAOrysFiLHomzXhMU3Hchd-FwB/image.png)

「Open Source」を選択し、サービスを開始します。

![](https://www.evernote.com/l/AAmk77dwXUVFt5oP_t9ls4J-Q_zh1BcE09sB/image.png)

#### リポジトリの追加

つぎに、監視するリポジトリを追加します。「Add a repository」ボタンを押して、リストからパブリックリポジトリを選びます。

![](https://www.evernote.com/l/AAlA2DaoI9ZOnJWQ6d4it-hJ6buUS9Xn3TQB/image.png)

リポジトリの初回スキャンが始まり、しばらくするとコードの監視が始まります。

#### Test Report IDの取得

初期状態では、Test Coverageの欄が雨傘アイコンになっています。これはコードカバレッジの情報がないことを表します。

![](https://www.evernote.com/l/AAkrWNhfXjRBeqIylQyPvr7n3Ue35VVQwFoB/image.png)

Travis CIとの連携には、Test Report IDが必要になります。下のスクリーンショットを参考に、IDを取得してください。

![](https://www.evernote.com/l/AAmHHxHJiMJA_qVYzaHGVKVEv4UNK4uCu-0B/image.png)

このIDはCode Climateにコードカバレッジ情報を送信する書き込み専用キーです。パブリックリポジトリに公開しても問題ありません。（[公式ドキュメント](https://docs.codeclimate.com/docs/finding-your-test-coverage-token#should-i-keep-my-test-reporter-id-secret)）

#### Travis CIとの連携

testコマンドに、カバレッジ出力オプションを追加します。

*▼package.json*

```json
{
  "scripts": {
    "test": "jest --coverage"
                  ^^^^^^^^^^
  }
}
```

Test Report IDをTravis CIに渡すため、`.travis.yml`を書き換えます。

*▼.travis.yml*

```yml
env:
  global:
    - CC_TEST_REPORTER_ID=【ここにTest Report ID】
language: node_js
node_js:
  - "10"
  - "12"
  - "14"
before_script:
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
  - chmod +x ./cc-test-reporter
  - ./cc-test-reporter before-build
after_script:
  - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
```

参考 [CodeClimate : Travis CI Test Coverage](https://docs.codeclimate.com/docs/travis-ci-test-coverage)

Test Report IDを環境変数にセットします。テスト前に報告用アプリケーションをダウンロード、テスト後にCode Climateへ結果を送信します。

この`package.json`と`.travis.yml`をmasterブランチにプッシュします。

#### 確認

Quality By Code Climateのページへ戻り、雨傘アイコンを確認します。
雨傘アイコンがパーセンテージに変更されていれば、無事に設定完了です。

![](https://www.evernote.com/l/AAmGxeZXgL1GBqJ4vLViy0bbI5B7MrUz8-cB/image.png)

## 個人的な感想

[GitHub Actions](https://github.co.jp/features/actions)の登場によりCI/CD環境の選択肢が大きく広がりました。CI環境を小さく導入することで、こうした動きをより理解しやすくなります。

以上、ありがとうございました。