不安定なテストを自動で再実行するGradleプラグインを試してみた

失敗したテストを自動で再実行してくれるGradleプラグイン test-retry-gradle-plugin を試しました
2020.09.16

はじめに

テスト結果が安定しない時は多々あると思います。 外部サービスの機嫌が悪くレスポンスが遅くて失敗、一時的にテスト環境に負荷が掛かって失敗、seleniumでリダイレクトに時間が掛かって失敗 etc...

この様にテスト結果が安定しないテストを不安定なテスト(Flaky tests)と呼ぶらしいです。

このようなテストは再実行すれば大体成功するので、ローカルなら手動で再実行すればいいのですが、CIで実行しているテストが不安定だと以降のパイプラインがストップし調査や再実行にコストが掛かります。

そのような時に最適な、失敗したテストを自動で再実行してくれるGradleプラグイン test-retry-gradle-plugin を今回は試しました。

導入方法

Gradleのブログを参考に、 build.gradle に以下を追記します。

plugins {
    id 'org.gradle.test-retry' version '1.1.6'
}

test {
    retry {
        failOnPassedAfterRetry = false 
        maxFailures = 40
        maxRetries = 3
    }
}

これだけで導入が出来ます。テストコードの修正は必要ありません

各項目について説明

  • failOnPassedAfterRetry: ビルドを失敗させるか成功させるかを制御
  • maxFailures: 許容する最大テスト失敗数。この値を超えた場合は、再実行しません
  • maxRetries: 再実行する回数

このようになっています。

maxFailures は、この値を超える場合は原因は別にあるので再実行はしない、という意味合いで使うようです。なので不安定なテスト以上の数は設定しないよう気をつけましょう。

確認

新しいプロジェクトを作成し、JUnit5で試してみました。

ちなみに test-retry-gradle-plugin はJUnit4と5に対応してます。

public class RetryTest {

	@Test
	void test() {
		Random random = new Random();
		assertThat(random.nextBoolean()).isTrue();
	}
}

実行する毎に結果が変わるテストを作成して、テストを実行。

$ ./gradlew test --tests retry.RetryTest

> Task :test

RetryTest > test() FAILED
    java.lang.AssertionError at RetryTest.java:14

RetryTest > test() FAILED
    java.lang.AssertionError at RetryTest.java:14

3 tests completed, 2 failed

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 2s

初回テストが失敗した為再実行し、3回目のテストが成功したのでビルドも成功しました。

IntelliJでテストを実行すると下記のように結果が表示されます。

出力

上記のテスト結果を見るとわかるのですが、再実行回数分テスト結果が出力されます。

CIでテストを実行した際には、同じテストのテスト結果が複数出力されるので、実際のテスト数以上のエラーが出力される場合があります。少し見難いです。

まとめ

テストコードを修正せずに組み込めるのはとても便利です。 不安定なテストを無くしたくても難しい、CIでテストが頻繁に失敗して都度手動で再実行している等の場合には一考の価値がありそうです。

参考