Create-React-Appで作ったReactアプリのTest結果をCodeBuildでレポート出力する方法

#はじめに
最近インフラ関係をAWSに移し、CodeBuildを使い始めたのですが、[AWSの公式ガイド](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/test-report-jest.html)に書いてある内容通りにやってみてもテストレポートが出力されなかったので、今回自力で設定したことを備忘録もかねて残しておきます。

#想定読者
CodeBuildのプロジェクト設定等はあらかた終わっていて、ビルドができるようになったので、テストレポートを出力したい人

##1.React側の設定
まず公式ガイドにも書いてある通り、xml形式でファイルを出力するため、[jest-junit](https://www.npmjs.com/package/jest-junit)を追加します。

```javascript:console
yarn add jest-junit
```

そして公式ガイド通りにjestのreportersを設定しようとすると**エラーが出ます。**
プロジェクトルート直下のpackage.jsonに以下を記述してみてください。

```javascript:公式ガイド

module.exports = {
  reporters: [
    'default',
    [ 'jest-junit', {
      outputDirectory: <test report directory>,
      outputName: <report filename>,
    } ]
  ]
};
```

```json:package.json
....

 "jest": {
    "reporters": [
      "default",
      [
        "jest-junit",
        {
          "outputDirectory": "reports/results(結果を出力したい任意のディレクトリ)",
          "outputName": "test-results.xml(出力したいファイル名)"
        }
      ]
    ]
  }
```

>####<font color="FireBrick">**These options in your package.json Jest configuration are not currently supported by Create React App:**</font>
>#####<font color="FireBrick">**・reporters<br /> If you wish to override...**</font>

**Create-React-Appではその設定は認めません！**と怒られてしまいました。

そこで、もう一度package.jsonを開き、scriptsの部分を編集し**直接reportersを記述してやります。**

```json:package.json

  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom --verbose",
 ++ "test:ci": "react-scripts test --watchAll=false --ci --reporters=default --reporters=jest-junit",
    "eject": "react-scripts eject"
  },
```

reporters以外の各optionは[公式サイト](https://jestjs.io/docs/ja/cli#--ci)に詳しく書いてあるのでここでは割愛します。
また、CodeBuildにCodePipelineなどを使ってCI/CD環境を導入することも多いと思うのでここでは**test:ci**コマンドを編集しています。自分がわかりやすいscript名で問題ありません。
consoleに戻って、test:ciコマンドを実行します。

```javascript:console
yarn test:ci 

...
yarn run v1.22.5
$ react-scripts test --ci --reporters=default --reporters=jest-junit

PASS  src/tests/Main.test.js (7.653 s)
  Main's debug test
    √ should show all contents (645 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.971 s, estimated 10 s
Ran all test suites related to changed files.

Watch Usage
 › Press a to run all tests.
 › Press f to run only failed tests.
 › Press q to quit watch mode.
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press Enter to trigger a test run.
```
うまくいきました。
これでプロジェクトルートに**junit.xml**というファイルが出力されていると思います。
出力先やファイル名を変更したい場合は、再度package.jsonを開き、以下の記述を追加します。

```json:package.json
   "jest-junit": {
    "outputDirectory": "任意のディレクトリ",
    "outputName": "任意のファイル名"
  }
```
このディレクトリ名とファイル名はbuildspec.ymlでも使うので覚えておきましょう。

#2 CodeBuild側の設定

buildspec.ymlの末尾に以下を追記すれば終わりです。便利！

```yml:buildspec.yml
reports:
  jest_reports:
    files:
      - "package.jsonで指定したファイル名"
    file-format: JUNITXML
    base-directory: "package.jsonで指定したディレクトリ"
```

後はCodeBuildページからレポート履歴を見ていただければレポートがあると思います。



余談ですが2020年12月17日現在、buildspec.ymlの**pre_build phaseでtestを実行**してしまうと、
テストが失敗したときに**レポートがうまく生成されない仕様**となっているようです。

必ずbuildかpost_build phaseでtestは実行しようと思いました。こえー

また、<font color="red">test scriptsの実行に失敗するとその後のcommandsがスキップ</font>されるので
phases/build/commandsの順序には気を付ける、場合によってはtest fail時にも必要な処理はfinallyブロックに分けて記述するべきだなあと感じました。
(そもそもローカル環境でテスト通してからgit pushするからあまり想定しなくても良いことかもですが・・・)

```yml:buildspec.yml
意図的にエラーを出し、その後のdocker build等が行われないことを確認する。
以下は手元にあったtest後にdocker buildするymlファイル

build:
    commands:
      - yarn install
      - yarn test:ci --watchAll=false 
      - docker build -t $ACCOUNT_ID.dkr.ecr.$DEFAULT_REGION.amazonaws.com/failedtest:latest .
      - docker push $ACCOUNT_ID.dkr.ecr.$DEFAULT_REGION.amazonaws.com/failedtest:latest
```

```text:Errorlog
[Container] 2020/12/17 09:26:21 Command did not exit successfully yarn test:ci --watchAll=false exit status 1
[Container] 2020/12/17 09:26:21 Phase complete: BUILD State: FAILED  ##以降のdockerの処理が行われない
[Container] 2020/12/17 09:26:21 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: yarn test:ci --watchAll=false. Reason: exit status 1
[Container] 2020/12/17 09:26:21 Entering phase POST_BUILD
```
#3.最後に
ここまで見てくださってありがとうございました。
初投稿なので緊張しました。何か間違っていたり、もっと良い方法がございましたら教えて頂けると幸いです