🚀

テスト終わるまで何時間?Claude Codeでparallel_rspecを使いこなす方法

に公開

昼食を食べにいって戻ってきてもまだテストが終わってない K@zuki. です。

前回、Claude Codeのタイムアウトを延長する方法を紹介しました。

https://zenn.dev/khasegawa/articles/75b49e2cbb14c8

でも、そもそも2時間もかかるテストって、タイムアウト以前の問題ですよね。
今回は、Claude Codeのカスタムコマンド機能を使って、テストを並列実行で爆速化する方法を紹介します。

要約

  • ローカルで直列実行すると2〜3時間(1時間ぐらいしたらさすがに切るので実態は不明)
  • 並列実行にすると約10分で完走 🎉
  • Claude Codeのカスタムコマンドで自動化可能
  • /parallel_rspecと打つだけ
  • タイムアウト設定と組み合わせることで、さらに快適に実行可能

そもそもどれくらい遅いのか

正直に言えば、ローカルで直列で全てのテストを最後まで実行したことがありません。
CIで実行すればparallel_rspecを使っているので10分強程度で終わりますが、ローカルではそうも言ってられません。

ローカルでの実行結果を元にいくつかのテスト結果のメトリクスを雑に集計すると、2〜3時間らしいですが、早くても1時間半ではないでしょうか。
待ってられないので、いつも途中で止めてしまいます。

でも、そこそこのPCでparallel_rspecを使えば10分強で終わるはずですよね。
そのため、大規模なリファクタリングやCIにテストしてもらう前にもある程度はローカルでテストを回しておきたいところです。

Claude CodeのCustom slash commands機能

実は、Claude Codeにはスラッシュコマンドという便利な機能があります。
そして、任意のコマンドを定義することも可能になっています。

https://docs.anthropic.com/en/docs/claude-code/slash-commands#custom-slash-commands

.claude/commands/ディレクトリにMarkdownファイルを置くと、/コマンド名で実行できるようになります。
今回は、このディレクトリにparallel_rspec.mdを作成しておくことで、面倒くさいテストの実行から、テスト結果の分析までインタラクティブにできるようにしています。

parallel_rspec.mdの中身

実際のファイルを見てみましょう。

.claude/commands/parallel_rspec.md
# Execute RSpec Tests in Parallel

How to run RSpec tests in parallel using the `parallel_rspec` gem.

**Note:** System tests (spec/system) are excluded from parallel execution due to their long execution time. Run them separately if needed.

**Redis DB Isolation:** Each parallel process automatically uses a separate Redis database based on TEST_ENV_NUMBER, preventing cache conflicts during parallel execution.

## Setup Steps (Always Required)

1. Get number of CPU cores.

    ```bash
    docker compose run --rm backend nproc
    ```

2. Set up the database for parallel testing. Replace {cores} with the number from step 1.

    ```bash
    docker compose run --rm backend bin/rails "parallel:drop[{cores}]"
    docker compose run --rm backend bin/rails "parallel:setup[{cores}]"
    ```

## Execution Mode

### When user specifies paths after the command (e.g., "/parallel_rspec spec/models spec/requests/api/v1")

Run only the specified paths (use 10 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} $ARGUMENTS
    ```

Note: `$ARGUMENTS` represents the paths specified by the user after the command.

### When user does NOT specify any paths (just "/parallel_rspec")

Run ALL tests in this exact order:

1. Run model tests (~2-3 minutes, use 5 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} spec/models
    ```

2. Run controller tests (~5-10 minutes, use 10 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} spec/controllers
    ```

3. Run request tests (~10-15 minutes, use 10 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} spec/requests
    ```

4. Run service tests (~5-10 minutes, use 10 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} spec/services
    ```

5. Run job tests (~3-5 minutes, use 10 minutes timeout):

    ```bash
    docker compose run --rm backend bundle exec parallel_rspec -n {cores} spec/jobs
    ```

ポイントは以下の通りです。

  • CPU数を自動取得 - 環境に応じて最適な並列数を設定
  • データベースの準備 - 並列実行用のDBを自動セットアップ
  • 任意のテストファイルの実行 - 引数が指定されていればそのファイルのみ並列実行
  • ディレクトリごとに実行 - 各ディレクトリに適切なタイムアウトを設定
  • 引数対応 - 特定のファイルだけテストすることも可能

これぐらいならスクリプトを事前に定義しておいた方が便利ではありますが、実験感覚で作成しています。
タイムアウトの話に関しては、前回話した以下の記事で紹介した通り、タイムアウトを指定しないと2分がデフォルトになるのが困るためです。

https://zenn.dev/khasegawa/articles/75b49e2cbb14c8

これを使って全件をローカルで実行すると、なんと10分強で全てのテストが完走します 🎉

実際の使い方

Claude Codeで以下のように入力するだけです。

/parallel_rspec

すると、Claude Codeが自動的に

  1. CPU数を確認
  2. 並列実行用のデータベースをセットアップ
  3. 各ディレクトリのテストを順番に実行

を行います。
また、特定のファイルだけテストしたい場合には、

/parallel_rspec spec/requests/api/v1

と引数を指定してあげるだけでOKです。

タイムアウトとの組み合わせ

タイムアウト設定と組み合わせることで、さらに快適にテストを実行できます。
parallel_rspec.mdでは、各ステップに適切なタイムアウトが設定されています。

  • modelテスト ... 5分
  • controllerテスト ... 10分
  • requestテスト ... 10分

これにより、問題があっても無駄に待たされることがありません。

これらの基準に関してですが、テストを並列実行して実測値を元に超えない範囲で設定しています。

実行結果の例

実際の実行結果の一例です。

 Test Results Summary

  All parallel RSpec tests have been completed successfully using 12 CPU cores:

  1. Model tests: 2401 examples, 0 failures, 35 pendings (2:42)
  2. Controller tests: 138 examples, 0 failures (28 seconds)
  3. Request tests: ⚠️ 5688 examples, 60 failures, 100 pendings (6:58)
  4. Service tests: 1052 examples, 0 failures (1:17)
  5. Job tests: 239 examples, 0 failures (44 seconds)

  Total: 9518 examples, 60 failures (all in request specs), 135 pendings

  The main issues are in the request specs, particularly:
  - API v1 links create specs (10 failures)
  - API v2 custom field templates create specs (2 failures)

このようにそれぞれの結果について確認でき、トータルで10分強で全テストが完走できます。
具体的に「どのテストが落ちているのか」について確認すれば、それについてもその場で確認することができます。

まとめ

Claude Codeのカスタムコマンド機能を使えば、複雑な並列テストも/parallel_rspecの一言で実行できます。
ローカルでの実行時間が、n時間が10分になれば、テストを回す心理的ハードルが劇的に下がります。

みなさんも.claude/commands/にカスタムコマンドを作って、開発を効率化してみてください!

Discussion