LoginSignup
3
0

CircleCIの「失敗したテストのみ再実行する」機能とテストの並列実行

Last updated at Posted at 2023-08-02

こんにちは。CircleCI カスタマーサクセスチームのChisatoです。

最近個人的に幸せを感じた出来事は、近所でかわいい子犬(ボーダーコリー)に鬼絡みされたことです。
久しぶりに「ずっとこの瞬間が続けばいいのにな」という気持ちになりました。

逆に、「とっとと終わってほしいな」と思うのが長いテストの実行時間です。
今回は、そんな悩みを解決するのに役立つ下記の機能についてご紹介します。

  • 人気の新機能「失敗したテストのみを再実行する」(Rerun failed tests)
  • テストの分割と並列実行(Test splitting and Parallelism)
  • Test Insights(テストインサイツ)

「失敗したテストのみを再実行する」とは

これまで、テストを再実行するときの選択肢は、次の3種類でした。

  • Rerun from Start (最初からすべて再実行)
  • Rerun from Failed(失敗した箇所以降のジョブをすべて再実行)
  • Rerun with SSH

失敗した箇所以降のジョブをすべて再実行すると、「再実行しなくても良い部分」まで実行されるため、結果を得るまで時間がかかったり、無駄にクレジットを消費してしまったりします。

「失敗したテストのみを再実行する」機能を使うと、迅速に結果が得られ、無駄なクレジットの消費も防ぐことができます。

おかげさまで、多くのお客様から「この機能はぜひ活用したい!」と良いフィードバックをいただいております。

それではテストの並列実行から、実際の設定を見ていきましょう。

テストの分割と並列実行の設定

今回はドキュメンテーションページのサンプルプロジェクトを参考にしました。
このプロジェクトには既にテスト分割と並列実行が設定されていますが、設定方法を説明します。

Config.yml file
version: 2.1

orbs:
    node: circleci/node@3.0.1

jobs:
    build-and-test:
        docker:
            - image: cimg/node:12.16
        parallelism: 5  #1
        steps:
            - checkout
            - node/install-packages:
                pkg-manager: yarn      
            - run: mkdir ~/junit #2
            - run:
                name: Test application
                command: | #3
                    TEST=$(circleci tests glob "src/__tests__/*.js" | circleci tests split --split-by=timings)
                    yarn test $TEST 
            - run:
                command: cp junit.xml ~/junit/  #4
                when: always
            - store_test_results:   #5
                path: ~/junit
            - store_artifacts:
                path: ~/junit
workflows:
    build-and-test:
      jobs:
        - build-and-test

次の手順の番号は、コードスパン中のコメント番号と対応しています。

1. テストを分割し、並列実行するため、build-and-test ジョブで docker キーの後に parallelism キーと 値 を指定します。例えば、値を 5 と設定すると、5 つの別々の Docker コンテナがスピンアップされます。
2. テストの分割方法には3種類ありますが、最も効率的なのが実行時間を元にした分割です。これを有効にするには、テストデータをアップロードする必要があります。テスト結果は junit.xml に保存されるため、 - run: mkdir ~/junit を記述します。
3. テストファイルと分割方法を設定します。環境変数 $TEST の中で、circleci tests glob コマンドで、対象のテストファイルを指定します。それらのファイルを circleci tests split に渡します。タイミングで分割したいので、 --split-by=timings フラグを用います。次に、yarn test $TEST で、環境変数$TESTを参照してテストを実行するよう設定します。
4. command: cp junit.xml ~/junit/ の記述は、テスト結果を ~/junit に保存するためのものです。毎回このステップが実行されるように always とします。
5. 最後にstore_test_results のステップを追記することで、テストデータが CircleCI にアップロードされます。このテストデータにアクセスするには、ダッシュボードでジョブを表示し、 Tests タブをクリックします。

これで、タイミングによってテスト分割できるようになりました。

テスト分割の例

テスト分割されると、ダッシュボードには下記のように複数のコンテナが表示されます。
Screenshot 2023-07-29 at 13.24.21.png

TIMING タブでは、タイミングによって分割されたジョブの各コンテナの情報が確認できます。
Screenshot 2023-07-29 at 13.33.35.png

テストデータの表示例

テスト結果が正しくアップロードできていると、ダッシュボードの TESTS タブを開いたときに下記のような画面になります。
Screenshot 2023-07-29 at 13.26.06.png

テスト分割の方法について

テスト分割の方法は大きく分けて3種類あります。詳しくはドキュメンテーションページをご参照ください。


失敗したテストのみを再実行する(Rerun failes tests)機能の設定

下記は、この機能を有効にするために、先ほどのコードを書き換えたものです。

先ほどの Config.yml file の状態だと、ダッシュボードから再実行しようとするとき、Rerun failed tests が選択できません。
Screenshot 2023-07-29 at 13.38.38.png

Config.yml file
version: 2.1

orbs:
    node: circleci/node@3.0.1

jobs:
    build-and-test:
        docker:
            - image: cimg/node:12.16
        parallelism: 5
        steps:
            - checkout
            - node/install-packages:
                pkg-manager: yarn      
            - run: mkdir ~/junit
            - run:
                name: Test application
                command: |  #1
                    TEST=$(circleci tests glob "src/__tests__/*.js") #2
                    echo "$TEST" | circleci tests run --command="xargs yarn test -o junit_family=legacy --junitxml=junit.xml" --verbose --split-by=timings 
                    
                         
            - run:
                command: cp junit.xml ~/junit/
                when: always
            - store_test_results:
                path: ~/junit
            - store_artifacts:
                path: ~/junit
workflows:
    build-and-test:
      jobs:
        - build-and-test

1. 機能を有効にするには、この部分を変更する必要があります。テストの実行には、circleci tests split の代わりに、circleci tests run を使います。

2. パラメータの説明は、ドキュメンテーションを下記引用します。

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 も必須です。
--verbose は circleci tests run 用のオプションパラメーターであり、詳細なデバッグメッセージを出力します。
--split-by-timings は、circleci tests run でタイミングに基づくインテリジェントテスト分割を利用するためのパラメーターです。 circleci tests run を使う場合、このパラメーターは必須ではありません。 テストジョブで CircleCI のテスト分割機能を使わないのであれば、省略してください。

ドキュメンテーションでは、各テストタイプに応じた例を確認できます。

設定変更のおかげで、失敗したテストのみを再実行する機能が選択可能になりました。
Screenshot 2023-07-29 at 13.48.19.png

実際に機能を使ってみると、失敗した部分だけが再実行されていることがわかります。
Screenshot 2023-07-29 at 13.48.46.png

最後は気持ちよくグリーンビルドで締めます🥝
Screenshot 2023-07-29 at 13.54.51.png

Test Insights の活用

テストデータをアップロードする設定が有効な場合、テストインサイツ(Test Insights)を利用することができます。
Test Insights では、実行時間の遅い順、失敗の多い順、さらに不安定なテストの自動検知結果を確認できます。

ダッシュボードの TESTS タブをクリックすると、直接 Test Insights のページに遷移してテストの分析ができます。
Screenshot 2023-07-29 at 13.28.08.png

下記は「不安定なテストの自動検知機能」の表示例です。
この機能は、多くのお客様にテスト最適化のため活用いただいています。
Screenshot 2023-07-28 at 16.18.52.png

不安定なテストの自動検知はテスト最適化を進めているお客様にたいへん人気の機能です。
下記のOrbを組み合わせると、自分の指定したSlackのチャネルで通知を受け取ることができます(このOrbはソリューション・エンジニアのTadashiさんが作成したもの)。

また、下記のプロジェクトを活用すると、Insights API を使って(こちらはサポートエンジニアの Aaronさんが作成したもの)指定したSlackチャネルに定期的にデータを飛ばすことができます。

まとめ

今回のプロジェクトの設定では Jasur さんに「失敗したテストのみを再実行する」機能の設定で助けていただきました。ありがとうございました。

暑い日が続きますが、ご自愛ください。爽やかなグリーンビルドで素敵な夏を過ごしましょう。

技術的なご質問は、お気軽に サポートセンター までお問い合わせください。

参考文献

テスト分割によるパイプラインの高速化
失敗したテストのみを再実行する
テストデータの収集

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0