うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

JUnit5でテストに時間がかかりすぎたら失敗にする Timeout アノテーション

@Timeout で実行時間がかかりすぎていたらFailにする

自動テストの実行時間がかかりすぎているときには、Failにしたいということがたまにおきます。IOに依存しているテストではよくありますし、複雑なロジックをくんでいて無限ループになってしまったり、組み合わせ爆発がおきてしまったり。そういうのが予見されるときには個別に@Timeoutというアノテーションをテスト対象の範囲に最大実行時間を指定しておくことで実現します。

package junit5.timeout;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;

class TimeoutDemo {

  @BeforeEach
  @Timeout(5)
  void setUp() {
    // この中の処理で5秒以上実行してしまったらここでFailする
  }

  @Test
  @Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
    // unit指定なし => 秒。
    // unit指定 => nano秒から日まで指定できる
  void _100ミリ秒以上かかるとテストが失敗する() {
  }

  @Test
  void 非同期実行におけるタイムアウトはassertTimeoutPreemptivelyを使うと便利() {
    assertTimeoutPreemptively(
        Duration.ofSeconds(1),
        // なにか非同期で実行するもの。Executableをわたす。
        () -> {
        });
  }

}

@Timeoutはクラスにつけたら、@Testや@BeforeEachなどのそれぞれにつけたのと一緒の動きになります。 もちろん、@Nested がついたクラスがインナークラスにいても動作します。

package junit5.timeout;

import org.junit.jupiter.api.*;

import static java.lang.Thread.sleep;

// ClassにもTimeoutをつけられる
@Timeout(2)
public class TimeoutClassDemo {

  @BeforeEach
  void setup() throws InterruptedException {
    sleep(1_000);
  }

  @Test
  void some_spec_1() throws InterruptedException {
    sleep(1_000);
  }

  @Test
  void some_spec_2() throws InterruptedException {
    // Timeoutよりおおきいので失敗する
    sleep(2_100);
  }

  // Nestedの中でもClassにつけたTimeoutは有効
  @Nested
  class SomeContext {
    @BeforeEach
    void setup() throws InterruptedException {
      sleep(500);
    }

    @Test
    void some_spec_3() throws InterruptedException {
      sleep(1_000);
    }

    @Test
    void some_spec_4() throws InterruptedException {
      // Timeoutよりおおきいので失敗する
      sleep(2_100);
    }
  }
}

リポジトリ

GitHub - kyonmm/junit5-timeout

参考書籍

テスト駆動開発

テスト駆動開発

Java本格入門 ?モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで

Java本格入門 ?モダンスタイルによる基礎からオブジェクト指向・実用ライブラリまで

[改訂新版]マインドマップから始めるソフトウェアテスト

[改訂新版]マインドマップから始めるソフトウェアテスト