前回 の続き
今回は値の比較、アサーションについて。
JUnit5が提供するアサーション
JUnit5はJUnit4とほぼ同等のAssertion機能を提供している。また、より高度なAssertionを求める場合は、サードパーティライブラリーの利用を勧めている。
JUnit5のAssertionの基本的なもの
以下の通り。なお、assertThat
はなくなった。また、メッセージはこれまでは引数の最初に渡していたが、引数の最後に渡すようになった。
メソッド | 比較内容 |
---|---|
Assertions#assertEquals |
左(期待値)と右(実際の値)が等しいことを確認する |
Assertions#assertNotEquals |
左(期待値)と右(実際の値)が等しくないことを確認する |
Assertions#assertTrue |
値が true であることを確認する |
Assertions#assertFalse |
値が false であることを確認する |
Assertions#assertSame |
左(期待するオブジェクト)と右(実際のオブジェクト)が同じインスタンスであることを確認する |
Assertions#assertNotSame |
左(期待しないオブジェクト)と右(実際のオブジェクト)が同じインスタンスでないことを確認する |
Assertions#assertNull |
値が null であることを確認する |
Assertions#assertNotNull |
値が null でないことを確認する |
Assertions#assertArrayEquals |
左の配列(期待値)と右の配列(実際の値)が順番、値ともに等しい配列であることを確認する |
サンプルコード
@Test void assertVariation() { assertEquals("2nd test", getText(), "メッセージは3つめの引数"); assertEquals("2nd test", getText(), () -> "メッセージは Supplier でも渡せる"); assertTrue(true, "これは [true]"); assertFalse(false); // メッセージなし assertNotEquals("いろいろなassertion", getText()); assertNotSame(new Something(), new Something(), () -> "notSame は reference の比較"); assertSame(something, something); assertNotSame(something, new Something(), () -> "型が違うけど比較できる..."); assertNull(returnsNull()); assertNotNull(getText()); assertArrayEquals(new int[]{1,2,3,4,5,6,7,8}, intArray(), () -> "配列のテスト"); } private static final Object something = new Object(); private static class Something {} @NotNull private String getText() { return "2nd test"; } @Nullable private String returnsNull() { return null; } @NotNull private static int[] intArray() { return new int[]{1, 2, 3, 4, 5, 6, 7, 8}; }
追加になったAssertion
Iterable
の比較をおこなうassertionメソッド(Assertions#assertIterableEquals
)が追加された。
サンプルコード
@Test void assertionForCollections() { assertIterableEquals(Arrays.asList( new Identity<>(0) , new Identity<>(1) , new Identity<>(2) , new Identity<>(3) ), identityList()); } @Data @RequiredArgsConstructor static class Identity<T> { private final T id; } @NotNull private List<Identity> identityList() { return IntStream.range(0, 4) .mapToObj(Identity::new) .collect(toList()); }
便利なAssertion
Assertions#assertAll
という複数のAssertをサポートするメソッドが追加された。
可変長引数で渡された Executable
(Assertionの式)または Stream<Executable>
を受取りすべてのAssertionをすべて実行し、どれがfailしたかエラー表示する。
サンプルコード
@Test void assertAllThatFails() { Stream<Executable> tests = IntStream.rangeClosed(1, 7) .mapToObj(i -> () -> { log.info("This is assertion[{}]", i); assertEquals(i, i + (i % 3 == 0? 1 : 0), () -> "assertion" + i); }); assertAll(tests); }
実行結果
19:06:46.940 [INFO com.example.ex2.FourthTest] - This is assertion[1] 19:06:46.945 [INFO com.example.ex2.FourthTest] - This is assertion[2] 19:06:46.946 [INFO com.example.ex2.FourthTest] - This is assertion[3] 19:06:46.947 [INFO com.example.ex2.FourthTest] - This is assertion[4] 19:06:46.947 [INFO com.example.ex2.FourthTest] - This is assertion[5] 19:06:46.948 [INFO com.example.ex2.FourthTest] - This is assertion[6] 19:06:46.948 [INFO com.example.ex2.FourthTest] - This is assertion[7] Failures (1): JUnit Jupiter:FourthTest:assertAllThatFails() MethodSource [className = 'com.example.ex2.FourthTest', methodName = 'assertAllThatFails', methodParameterTypes = ''] => org.opentest4j.MultipleFailuresError: Multiple Failures (2 failures) assertion3 ==> expected: <3> but was: <4> assertion6 ==> expected: <6> but was: <7>
なお、複数のAssertionを実行してもテストは1としてしかカウントされない。
JUnit5のAssumption
Assumptionは条件に合致した場合のみテストを実行し、条件に合致しない場合にはテストをスキップするヘルパーメソッド。JUnit4にあった assumeThat
や assumeNotNull
、 assumeNoException
がなくなり、 assumeTrue
が残った。また、 assumeFalse
、 assumingThat
が追加された。
サンプルコード
@Test void thisTestDoNotRunOnSunday() { final DayOfWeek dayOfWeek = today().getDayOfWeek(); assumeFalse(SUNDAY.equals(dayOfWeek)); log.info("日曜以外"); assertFalse("日".equals(dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPAN))); } @Test void thisTestRunOnSunday() { final DayOfWeek dayOfWeek = today().getDayOfWeek(); assumeTrue(SUNDAY.equals(dayOfWeek)); log.info("日曜"); assertEquals("日", dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPAN)); } private static final ZoneId ZONE_ID = ZoneId.of("Asia/Tokyo"); @NotNull @Contract(pure = true) private static LocalDate today() { return LocalDate.now(ZONE_ID); }
実行結果
Test run finished after 10468 ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 1 tests found ] [ 0 tests skipped ] [ 1 tests started ] [ 1 tests aborted ] [ 0 tests successful ] [ 0 tests failed ]
assumingThat
は最初の引数の BooleanSupplier
が true
を返した場合のみ後続の Executable
(Assertion)が実行される。
assumingThat
のサンプルコード
@Test void thisTestDoNotRunOnSunday() { final DayOfWeek dayOfWeek = today().getDayOfWeek(); assumingThat( () -> !SUNDAY.equals(dayOfWeek) , () -> assertFalse("日".equals(dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPAN))) ); } @Test void thisTestRunOnSunday() { final DayOfWeek dayOfWeek = today().getDayOfWeek(); assumingThat( () -> SUNDAY.equals(dayOfWeek) , () -> assertEquals("日", dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.JAPAN)) ); }
実行結果
Test run finished after 10261 ms [ 2 containers found ] [ 0 containers skipped ] [ 2 containers started ] [ 0 containers aborted ] [ 2 containers successful ] [ 0 containers failed ] [ 2 tests found ] [ 0 tests skipped ] [ 2 tests started ] [ 0 tests aborted ] [ 2 tests successful ] [ 0 tests failed ]
コードはこちらから