Start Building for Free
CircleCI.comアカデミーブログコミュニティサポート

失敗したテストのみを再実行する (プレビュー)

1 week ago2 min read
クラウド
このページの内容

背景および概要

CircleCI では、この度、失敗したテストのみを再実行できる機能をプレビュー公開しました。 このオプションを選択すると (下図参照)、テストが一時的に失敗した際に、テストスイート全体ではなく一部のテストのみを再実行できます。

これまで、ワークフロー内のテストジョブのテスト結果が不安定である場合にワークフローの実行を完了するには、 失敗状態からワークフローを再実行するしかありませんでした。 この方法では、成功したものも含めてテストジョブの*すべてのテスト*を再実行するため、フィードバックの獲得が遅れ、不要なクレジットを使うことにもなります。

"Re-run failed tests only (失敗したテストのみの再実行)" オプションでは、新しいコミットではなく同じコミットで失敗したテストを再実行できます。

Option to rerun failed tests from Rerun menu

前提条件

  • ワークフローのテストジョブについて、CircleCI に テスト結果をアップロードするよう設定する。 JUnit XML 出力file 属性または classname 属性を含める必要があります

  • テストジョブで、テストの実行に circleci tests run を使用する (下記参照)。

クイックスタート

実装前: サンプルの .circleci/config.yml ファイル

 - run:
    name: Run tests
    command: |
      mkdir test-results
      TEST_FILES=$(circleci tests glob "**/test_*.py" | circleci tests split --split-by=timings)
      pytest -o junit_family=legacy --junitxml=test-results/junit.xml $TEST_FILES

- store_test_results:
    path: test-results

上記のサンプル CircleCI コンフィグファイルの中身は以下のとおりです。

  1. 名前の末尾が .py の Python テストファイルを実行する

  2. 過去のタイミング結果に基づいてテストを分割する (インテリジェントテスト分割に関する こちらのチュートリアルを参照)

  3. テスト結果を新規ディレクトリ test-results に保存する

  4. テスト結果を CircleCI にアップロードする

注: -o junit_family=legacy は、生成するテスト結果に file 属性を含めるために使用しています。 このサンプルで使用していないものは、並列実行を設定するキーだけです (詳細については「 テスト分割と並列実行」を参照)。

実装後: サンプルの .circleci/config.yml ファイル

以下では、前述のサンプルを編集し、失敗したテストのみを再実行できるように circleci tests run コマンドを使用するように更新しました。

 - run:
    name: Run tests
    command: |
      mkdir test-results
      TEST_FILES=$(circleci tests glob "**/test_*.py")
      echo $TEST_FILES | circleci tests run --command="xargs pytest -o junit_family=legacy --junitxml=test-results/junit.xml" --verbose --split-by=timings #--split-by=timings is optional, only use if you are using CircleCI's test splitting

 - store_test_results:
    path: test-results
  • TEST_FILES=$(circleci tests glob "/test.py")

    CircleCI の glob コマンドを使用して、テストファイルのリストを作成しています。 今回は、名前の先頭が test_ で末尾が .py のテストファイルを探しました。 Ensure that the glob string is enclosed in quotes.

  • echo $TEST_FILES |

    circleci tests run コマンドにテストのリストを標準入力 ( stdin) として渡します。

  • circleci tests run --command="xargs pytest -o junit_family=legacy --junitxml=test-results/junit.xml" --verbose --split-by=timings

    • circleci tests run を呼び出し、--command= パラメーターに元のテスト実行コマンド (pytest) を指定しています。 このパラメーターは必須です。 同じく、xargs も必須です。

    • --verbosecircleci tests run 用のオプションパラメーターであり、詳細なデバッグメッセージを出力します。

    • --split-by-timings は、circleci tests run でタイミングに基づくインテリジェントテスト分割を利用するためのパラメーターです。 circleci tests run を使う場合、このパラメーターは必須ではありません。 テストジョブで CircleCI のテスト分割機能を使わないのであれば、省略してください。

設定の検証

コンフィグファイルの更新が完了したら、次回にジョブのテストが失敗した場合に [Re-run failed tests only (失敗したテストのみを再実行)] ボタンをクリックしてください。

--verbose 設定を有効にすると、次回の CircleCI でのジョブ実行時に以下のような出力が表示されるようになります。

circleci-tests-plugin-cli plugin Installed. Version: 1.0.5909-ca27755
DEBU[2023-05-14T17:53:44Z] Attempting to read from stdin. This will hang if no input is provided.
DEBU[2023-05-14T17:53:44Z] rerunning failed tests
INFO[2023-05-14T17:53:44Z] starting execution

[Re-run failed tests only (失敗したテストのみを再実行)] ボタンをクリックした場合、テスト失敗が 1 回以上発生した fileclassname に含まれているテストのみが再実行されます。

[Re-run failed tests only (失敗したテストのみを再実行)] ボタンをクリックした場合、テスト失敗が 1 回以上発生した fileclassname に含まれているテストのみが再実行されます。 本記事の説明と異なる挙動が見られた場合には、 こちらの Discuss の投稿 (英語) にてお問い合わせください。

他のサンプル

Ruby (RSpec) テストを実行するジョブの設定

  1. Gemfile に以下の gem を追加します。

    gem 'rspec_junit_formatter'
  2. circleci tests run を使うようにテストコマンドを更新します。

     - run: mkdir ~/rspec
     - run:
        command: |
          circleci tests glob "spec/**/*_spec.rb" | circleci tests run --command="xargs bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml" --verbose --split-by=timings
  3. glob コマンドは、必要に応じて調整してください。 テスト結果を rspec に対応した形式で出力する方法については、「 テストデータの収集」の RSpec に関するセクションを参照してください。 現在のジョブで インテリジェントテスト分割機能を使用している場合は、circleci tests split コマンドを circleci tests run コマンドに変更し、--split-by=timings パラメーターを付けてください。

Ruby (Cucumber) テストを実行するジョブの設定

  1. 以下のようにテストコマンドを更新します。

    - run: mkdir -p ~/cucumber
    - run:
        command: |
        circleci tests glob "features/**/*.feature" | circleci tests run --command="xargs bundle exec cucumber --format junit --out ~/cucumber/junit.xml" --verbose --split-by=timings
  2. glob コマンドは、必要に応じて調整してください。 テスト結果を Cucumber に対応した形式で出力する方法については、「 テストデータの収集」の Cucumber に関するセクションを参照してください。 現在のジョブで インテリジェントテスト分割機能を使用している場合は、circleci tests split コマンドを circleci tests run コマンドに変更し、--split-by=timings パラメーターを付けてください。

Cypress テストを実行するジョブの設定

  1. cypress-circleci-reporter を使用します。 これを .circleci/config.yml でインストールするか、package.json に追加してください。 .circleci/config.yml でインストールする場合は次のように指定します。

      #add required reporters (or add to package.json)
      -run:
        name: Install coverage reporter
        command: |
          npm install --save-dev cypress-circleci-reporter
  2. cypress-circleci-reportercircleci tests run を組み合わせて実行し、CircleCI にテスト結果をアップロードします。

         -run:
            name: run tests
            command: |
              mkdir test_results
              cd ./cypress
              npm ci
              npm run start &
              circleci tests glob "cypress/**/*.cy.js" | circleci tests run --command="xargs npx cypress run --reporter cypress-circleci-reporter --spec" --verbose --split-by=timings" #--split-by=timings is optional, only use if you are using CircleCI's test splitting
    
         - store_test_results
            path: test_results

    glob コマンドの部分は、ニーズにあわせて調整してください。 現在のジョブで インテリジェントテスト分割機能を使用している場合は、circleci tests split コマンドを circleci tests run コマンドに変更し、--split-by=timings パラメーターを付けてください。

Javascript/Typescript (Jest) テストを実行するジョブの設定

  1. jest-junit 依存関係をインストールします。 この処理は .circleci/config.yml に以下のように追加します。

      - run:
          name: Install JUnit coverage reporter
          command: yarn add --dev jest-junit

    または、 こちらの使用手順 (英語) に従い、jest.config.js ファイルに依存関係を追加します。

  2. 以下のようにテストコマンドを更新します。

    - run:
        command: |
          npx jest --listTests | circleci tests run --command=“xargs npx jest --config jest.config.js --runInBand --” --verbose --split-by=timings
        environment:
          JEST_JUNIT_OUTPUT_DIR: ./reports/
          JEST_JUNIT_ADD_FILE_ATTRIBUTE: true
    
      - store_test_results:
          path: ./reports/
  3. npx jest --listTests コマンドは、必要に応じて調整してください。 テスト結果を jest に対応した形式で出力する方法については、「 テストデータの収集」の Jest に関するセクションを参照してください。 現在のジョブで インテリジェントテスト分割機能を使用している場合は、circleci tests split コマンドを circleci tests run コマンドに変更し、--split-by=timings パラメーターを付けてください。

    JEST_JUNIT_ADD_FILE_ATTRIBUTE=true は、file 属性の存在を確認するために設定しています。 .circleci/config.yml で設定する代わりに、addFileAttribute= "true" 属性を利用して jest.config.js ファイルに JEST_JUNIT_ADD_FILE_ATTRIBUTE=true を追加することもできます。

Playwright のテストを実行するジョブの設定

  1. circleci tests run を使うようにテストコマンドを更新します。

     - run:
        command: |
          mkdir test-results #can also be switched out for passing PLAYWRIGHT_JUNIT_OUTPUT_NAME directly to Playwright
          pnpm run serve &
          TESTFILES = $(circleci tests glob "specs/e2e/**/*.spec.ts")
          echo $TESTFILES | circleci tests run --command="xargs pnpm playwright test --config=playwright.config.ci.ts --reporter=junit" --verbose --split-by=timings
  2. glob コマンドは、必要に応じて調整してください。 現在のジョブで インテリジェントテスト分割機能を使用している場合は、circleci tests split コマンドを circleci tests run コマンドに変更し、--split-by=timings パラメーターを付けてください。 テスト分割を使用しない場合は、--split-by=timings を省略できます。 注: Playwrightの既にビルドインされている flagPLAYWRIGHT_JUNIT_OUTPUT_NAME)を使用して、JUnit XML 出力ディレクトリを指定することも可能です。

既知の制限

  • 失敗したテストのみを再実行する場合、再実行後のジョブの実行時にタイミングに基づくテスト分割の効率が想定より低くなることがあります。これは、テストのうち、失敗して再実行されたものの結果だけが保存されるためです。

  • 現時点では、テストを実行する Orb とこの新機能を組み合わせることはできません。

  • シェルスクリプトを呼び出してテストを実行する場合、circleci tests runcircleci/config.yml ではなくシェルスクリプト内に記載してください。

  • "Re-run failed tests only (失敗したテストのみを再実行)" 機能では、組織のワークスペースの 保持期間を超えたジョブを再実行することはできません。

  • ジョブでコードカバレッジレポートのアップロードを行う場合、 再実行中に問題が発生することがあります

FAQ

質問: 不明点や問題がある場合の問い合わせ先はどこですか?

回答: こちらの Discuss の投稿にコメントとしてお問い合わせください。


質問: この機能では、テストが個別に再実行されますか?

回答: いいえ。本機能では、テスト失敗が 1 回以上発生した classnames または file を再実行します。


質問: .circleci/config.yml ファイルで circleci tests run を設定していない場合、この機能を使うとどうなりますか?

回答: ワークフローの再実行時に、失敗したテストも含むすべてのテストが実行されます。 実質的に、"Rerun workflow from failed (失敗状態からワークフローを再実行)" と同じ効果です。


質問: .circleci/config.yml ファイルで circleci tests run を使用し、CircleCI へのテスト結果のアップロードはジョブに設定していない場合、この機能を使うとどうなりますか?

回答: ジョブが失敗します。


質問: "Re-run failed tests only (失敗したテストのみを再実行)" オプションはいつ使用できますか?

回答: 現時点では、このオプションは "Re-run workflow from failed (失敗したワークフローを再実行)" オプションと同時に表示されます。


質問: このページに示されていないテストフレームワークでも、この機能を使用できますか?

回答: はい。前述の 前提条件を満たしているジョブであれば、本機能は利用可能です。 この "Re-run failed tests only (失敗したテストのみを再実行)" 機能は、テストランナーおよびテストフレームワークに依存しません。 「 テストデータの収集」の手順に従って、ジョブでテスト結果をアップロードしてください。 一部のデフォルト設定では classnamefile が結果に含まれないため、ジョブの調整が必要になります。

クイックスタート」セクションを参考に、テストコマンドで circleci tests run を使うように編集してください。

問題が発生した場合は、 こちらの Discuss の投稿にコメントをお寄せください。


質問: CircleCI Web アプリでは、"Re-run failed tests only (失敗したテストのみを再実行)" でジョブを再実行したかどうかを確認できますか?

回答: 現時点ではできません。


質問: ジョブを再実行するときに、並列実行とテスト分割を使用するとどうなりますか?

回答: ジョブの parallelism キーで指定された数のコンテナまたは仮想マシン (VM) がスピンアップします。 ただし、これらの並列コンテナ/VM 全体でテストが分割されるので、各並列コンテナ/VM のテスト実行ステップではテストの一部のみが実行されるか、テストの実行自体が行われません。 たとえば、parallelism を 8 に設定しても、テスト数によっては、テスト分割で 2 つの並列コンテナ/VM にしかテストが "割り当てられない" 可能性があります。 こうした場合、他 6 つの並列コンテナ/VM も起動されますが、テスト実行ステップでテストを実行することはありません。

Question: この機能を設定しようとすると、maven の surefire テストが失敗することはありますか?

Answer: 依存モジュールでテストがスキップされたのを見たときに失敗を報告する代わりに、テストフレームワークがスキップされたテストを無視するように、-DfailIfNoTests=false フラッグを追加する必要がある場合もあります。

Question: circleci tests run でテスト分割のタイミングタイプを指定することは可能ですか?

Answer: はい、circleci tests split --split-by=timings --timings-type= と同様に、test-selector フラグを使用してタイミングタイプを指定することができます。 ファイル名、クラス名、テスト名のいずれかを渡すことができます。



ドキュメントの改善にご協力ください

このガイドは、CircleCI の他のドキュメントと同様にオープンソースであり、 GitHub でご利用いただけます。 ご協力いただき、ありがとうございます。

サポートが必要ですか

CircleCI のサポートエンジニアによる、サービスに関する問題、請求およびアカウントについての質問への対応、設定の構築に関する問題解決のサポートを行っています。 サポートチケットを送信して、CircleCI のサポートエンジニアにお問い合わせください。日本語でお問い合わせいただけます。

または、 サポートサイト から、サポート記事やコミュニティフォーラム、トレーニングリソースをご覧いただけます。