Node.jsとjestを使ってGithub Actionsで自動テストを実行する

システムの品質を保つためには、プログラムを作成したら期待通りに動くか動作確認が必要です。
そして品質を保ち続けるには、プログラムに変更を加えるたびに期待通りに動くか動作確認をする必要があります。
今回は以下の条件で自動テストが動いて品質を担保し続ける仕組みを作りたいと思います。

# 前提条件
- GithubActionsでテストを動かす
- Node.jsのバージョンは14系とする
- テストフレームワークはjestを使用する
- 自動テスト実行のタイミングは、mainブランチへプルリクエストを出したタイミングとする
  - こうすることで、開発者がプルリクエストを出したときに毎回自動テストが動いて品質を保ちやすくなる
  - そして自分のコードでテストが落ちたことが明白になる
  - レビューアはテストが通ったことを確認してからmainブランチにマージできる

# ファイル構成
```
nodejs-test-example
│  .gitignore
│  package-lock.json
│  package.json
│
├─.github
│  └─workflows
│          unittest.yml
│
├─src
│      fizzbuzz.js
│      index.js
│
└─__tests__
        fizzbuzz.test.js
```

# 作業ディレクトリの作成
```bash
$ mkdir nodejs-test-example
```

# jestインストール
```bash
$ cd nodejs-test-example
$ npm install --save-dev jest
```

# テスト対象の作成
テスト対象は何でもいいんですが、今回はfizzbuzz関数を作成して、それをテスト対象とします。
``` src/fizzbuzz.js
"use strict";

const fizzbuzz = (value) => {
  let result = value;
  if (value % 3 == 0 && value % 5 == 0) {
    result = "FizzBuzz";
  } else if (value % 3 == 0) {
    result = "Fizz";
  } else if (value % 5 == 0) {
    result = "Buzz";
  }
  return result;
}

module.exports = fizzbuzz;
```

``` src/index.js
"use strict";

const fizzbuzz = require("./fizzbuzz")

console.log(fizzbuzz(1));
console.log(fizzbuzz(3));
console.log(fizzbuzz(5));
console.log(fizzbuzz(15));
```

## 実行結果
```bash
$ node src/index.js 
1
Fizz
Buzz
FizzBuzz
```

とりあえずちゃんと動いてそうです。

また、こちらを参考に.gitignoreを作成しておきます。
https://github.com/github/gitignore/blob/main/Node.gitignore

# テストの作成
fizzbuzz関数をテストするテストコードを作成していきます。
``` __tests__/fizzbuzz.test.js
const fizzbuzz = require("../src/fizzbuzz");

const testData = [
  { testCase: "1の場合は1が返ること", value: 1, expected: 1 },
  { testCase: "3の場合はFizzが返ること", value: 3, expected: "Fizz" },
  { testCase: "5の場合はBuzzが返ること", value: 5, expected: "Buzz" },
  { testCase: "15の場合はFizzBuzzが返ること", value: 15, expected: "FizzBuzz" },
];

testData.forEach((v) => {
  test(`fizzbuzz_${v.testCase}`, () => {
    // 実行
    const actual = fizzbuzz(v.value);

    // 検証
    expect(actual).toBe(v.expected);
  });
});
```

package.jsonを修正しテストを実行できるようにします。
``` package.json
{
  "scripts": {
    "test": "jest"
  },
  "devDependencies": {
    "jest": "^28.1.3"
  }
}

```

テストを実行してみます。
```bash
$ npm test

> test
> jest

 PASS  __tests__/fizzbuzz.test.js
  √ fizzbuzz_1の場合は1が返ること (3 ms)
  √ fizzbuzz_3の場合はFizzが返ること
  √ fizzbuzz_5の場合はBuzzが返ること (1 ms)
  √ fizzbuzz_15の場合はFizzBuzzが返ること (1 ms)

Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        1.392 s
Ran all test suites.
```
無事、テストが通りました。

# workflow作成
GithubActionのworkflowを作成します。
```.github/workflows/unittest.yml
name: ci

on:
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Setup Nodejs
        uses: actions/setup-node@v1
        with:
          node-version: 14

      - name: Unit test
        run: |
          npm install
          npm test

```

# githubにコミット

```bash
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin git@github.com:xxxxx/xxxxxxx.git
$ git push origin main
```
まだこの段階では自動テストは動きません。

# プルリクエストを出してテストを起動してみる
別ブランチをを作成し、適当な修正を加えてプルリクエストを出してみます。

```bash
$ git checkout -b exe_unittest
$ # 何か修正する
$ git add .
$ git commit -m "hoge"
$ git push origin exe_unittest
```

ここまで終わったらmainブランチへのプルリクエストを出してみます。

# 動作確認
どうやら期待通りにテストが起動し、テスト結果は全てOKのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273110/2e247d7c-22bf-37ee-e17a-11f3d3311965.png)

これで安心してmainブランチにマージで出来ます。

現場からは以上です。

# repository
https://github.com/y-dobashi/nodejs-test-example