テストを高速化しよう！CircleCI での並列テストのやり方をご紹介！！【CircleCI実践入門】

# はじめに
今回はCircleCIで並列テストを実施する方法について解説します！

実際の使い方は、以下の公式記事を読む方が早いですが、本記事ではRailsのプロジェクトにRSpecを適用する方法について解説します。
https://circleci.com/docs/ja/2.0/parallelism-faster-jobs

# YouTube動画
動画で確認したい方はこちらをどうぞ！
[【YouTube動画】 テストを高速化しよう！CirceCI での並列テストのやり方をご紹介！！【CircleCI入門】](https://youtu.be/AC3QCvE9y3Y)
[![テストを高速化しよう！CirceCI での並列テストのやり方をご紹介！！【CircleCI入門】](https://img.youtube.com/vi/AC3QCvE9y3Y/0.jpg)](https://youtu.be/AC3QCvE9y3Y)

# GitHub
GitHubからコードをダウンロードして試すこともできます。

https://github.com/yassun-youtube/circleci-parallel-test-sample

```bash
$ git clone git@github.com:yassun-youtube/circleci-parallel-test-sample.git
```

# 並列処理をするために
並列処理をするには、有料プランへの切り替えが必要です。
30ドル支払えば、テストが高速化します！

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751408/f8081ec6-6670-2703-dd98-23c375c5b7ae.png' width='600'>


# 実際の設定ファイル
以下が実際のファイルです。

本記事では、並列テストと関連する部分だけを説明します。

それ以外の基本的な書き方については、以下のQiita記事か公式サイトの記事を参考にしてください。
https://qiita.com/yassun-youtube/items/2a09d5b1b56feace8156

```circleci.yml
version: 2.1
jobs:
  test:
    docker:
      - image: circleci/ruby:2.7.2-node
    parallelism: 4
    steps:
      - checkout
      - restore_cache:
          keys:
            - bundle-{{ .Environment.CACHE_VERSION }}-{{ checksum "Gemfile.lock" }}
      - run:
          command: bundle install
      - save_cache:
          key: bundle-{{ .Environment.CACHE_VERSION }}-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - run:
          name: Prepare Test
          command: circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings > /tmp/tests-to-run
      - run:
          name: Run Test
          command: bundle exec rspec --format documentation --format RspecJunitFormatter --out tmp/test-results/rspec.xml $(cat /tmp/tests-to-run)
      - store_test_results:
          path: tmp/test-results
workflows:
  version: 2
  test_workflow:
    jobs:
      - test
```

## 並列処理する数
並列処理する数はparallelismで指定します。
有料プランの場合は最大80まで指定できます。

```yml
parallelism: 4
```

## テストファイルを分割するために
並列テストを実行するために、以下のコマンドを記述します。

``glob "spec/**/*_spec.rb"``で、specディレクトリ以下の_spec.rbファイルを表示し、``split --split-by=timings``でCircleCIで保存されているタイミングデータをもとにテストファイルを分けます。
分けたファイルをtmp以下のtests-to-runsディレクトリに保存して準備は完了です。

*タイミングデータには、ファイル名またはクラス名ごとに各テストが完了するまでにかかった時間が記録されています。

```yml
- run:
    name: Prepare Test
    command: circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings > /tmp/tests-to-run
```

## テストを実行する
あとはテストを実行するだけです。
RSpecの結果をRspecJunitFormatter (JUnit) で保存する場合は、gemの追加も必要です。

```yml
- run:
    name: Run Test
    command: bundle exec rspec --format documentation --format RspecJunitFormatter --out tmp/test-results/rspec.xml $(cat /tmp/tests-to-run)
```

```bash
# Gemfile
gem 'rspec_junit_formatter'
```

## 次回テストを効率的にするために
テストを準備するときに使用したタイミングデータは以下を指定しない場合、記録されません。
タイミングデータを使うと、テストの終了時間が均等になるようにファイルが分配されるので、テストが速くなります。

```yml
- store_test_results:
    path: tmp/test-results
```

　
# 分散と並列 (parallelismとparallel_tests)
CircleCIでparallelismを使うと、複数のマシンでテストを実行できますが、1つのマシン内で複数のテストを実行することもできます。
1つのマシン内で複数のテストを実行するには、Railsの場合、parallel_testsというgemを使います。

このgemを使うと、1つのマシン内でテストを複数動かすことができるので、さらに速度が上がります。


# おわりに
今回はCircleCIでテストを高速化するための手法として、並列処理 (parallelism) について紹介しました。
parallel_testsを使って、さらに分割する方法は別動画・記事で触れたいと思います。

また、CircleCIの使い方については、基本編とJOBの使い方についても動画・記事を書いてます。
不安な方はぜひ、ご確認ください。

## 初心者必見！ CircleCIでHello Worldしてみよう！
YouTube動画
https://youtu.be/6uZltaISUvo

Qiita記事
https://qiita.com/yassun-youtube/items/2a09d5b1b56feace8156

## CircleCI を使いこなす！ JOBの設定方法を徹底解説！！
YouTube動画
https://youtu.be/NWjNn2DLcPM

Qiita記事
https://qiita.com/yassun-youtube/items/38c6d32b50cbda2fcb9e