きり丸の技術日記

技術検証したり、資格等をここに残していきます。

Javaで事前条件を満たしていないテストを安全に終了させる(AssumeTrue)

たとえばDBは本番環境ではOracle、テスト環境ではH2を使っているケースがあるとします。その場合、Oracleでは動くがH2では動かないSQLを作成してしまうことが考えられます。

他にも、本番環境はAmazon RDS for Oracleを使っているが、テスト環境で用意できているOracleのバージョンが合わないパターンもあるでしょう。バージョンによっては動かないSQLを作成してしまうことも考えられます(例:ALTER SEQUENCEはOracle 18cから使えるが、それ以前のバージョンはDROP/CREATEするしかない)。

この記事ではAssumeTrueを使用して、事前条件を満たせないテストがあった時に、テストを安全に終了させます。

ゴール

事前条件を満たしていないテストを終了させる。ただし、テスト終了後はDisabledのように、正常終了とも異常終了とも異なる状態にする。

f:id:nainaistar:20210801220220p:plain

環境

  • Java
    • 15
  • org.springframework.boot
    • 2.5.2
  • JUnit
    • 5.7.1

ユースケース

  • 特定の環境でしか動かないテストを特定の環境だけで動くようにする
    • OS
    • DB
    • 等々

      対応

大きく2つ、AssumeTrueAssumingThatのメソッドがあります。

AssumeTrue

AssumeTrueでは事前条件を満たせていない場合、以後の処理を停止させます。

使い方として、org.junit.jupiter.api.Assumptions#assumeTrueの第1パラメータに事前条件を記載します。第2パラメータに失敗時のメッセージを記載します。

本来であればorg.junit.jupiter.api.Assertions.failで失敗しますが、AssumeTrue以後の処理を停止させているために安全に終了します。

@Test
void test_01() {
    assumeTrue(true);
    fail();

    // 結果メッセージ
    // Assumption failed: assumption is not true
}

@Test
void test_02() {
    assumeTrue(true, "このテストはoracle環境では動きません");
    fail();

    // 結果メッセージ
    // Assumption failed: このテストはoracle環境では動きません。
}

なお、AssumeFalseも存在しますが、出力するメッセージが混乱してしまったので、私は推奨しません。

AssumingThat

AssumingThatでは事前条件を満たせていない場合でも、以後の処理を実行します。特定の環境のみ追加テストを行うイメージでよいでしょう。

使い方として、org.junit.jupiter.api.Assumptions#assumingThatの第1パラメータに事前条件を記載します。第2パラメータに追加テストを記載します。

@Test
void test_01() {
    assumingThat(
        true,
        () -> {
            // ここでエラーになったら処理終了する。
            assertThat(1).isEqualTo(1);
        }
    );

    // assumingThatはここも実行する
    // fail();
}

なお、機能として紹介はしますが個人的にはAssumingThatは推奨しません。理由としては条件分岐が入ったことにより、テストが複雑になるからです。

備考

今回紹介したメソッドで事前条件に一致しない場合、TestAbortedExceptionを発生させます。JUnit 5単体で使用している場合は安全に処理はしてくれますが、メッセージを出力してくれません。

もし、メッセージを確認したい場合は、@SpringJUnitConfig等のフレームワークのテストアノテーションを使いましょう。

# ログ抜粋
21:35:12.828 [Test worker] 
... - After test method: context [DefaultTestContext@799f7b8a testClass = AssumeTests.AssumeTrue, testInstance = kirimaru.biz.domain.AssumeTests$AssumeTrue@1836d0cc, testMethod = test_02@AssumeTests.AssumeTrue, testException = org.opentest4j.TestAbortedException: Assumption failed: このテストはoracle環境では動きません
...

なお、@SpringBootTestだとメッセージを出力してくれなかったので、あんまりメッセージを作りこんでも無意味かもしれません。AssumeTrueで事前条件を満たさなかったときに、標準出力にメッセージを設定する方法がわからなかったので、教えていただけると助かります…。

ちなみに

そもそも、Springの機能にorg.springframework.test.context.junit.jupiter.DisabledIfというもっと簡単に使えそうな機能がありました。

軽い気持ちで「Disabled」に「If」使えたら楽だなーって思っていたのが、そのままありました。

こちらはまったく検証していませんので、DisabledIfも検証して、今後記事にする予定です。

終わりに

ピュアな機能として学ぶことも大事ですが、やはりライブラリは便利な機能を提供してますね。ライブラリの機能って本当に知らない機能は知らないから困る…。

ま、まぁ、こういうことができる、ということがわかっていれば他の言語でも同様の機能がありそうだ、というアタリをつけられるので、1つ成長したと思うことにします。


この記事お役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考

f:id:nainaistar:20210801220345p:plain