JUnit5.7, 5.8の新機能紹介
Java言語でつくられるソフトウェアを自動テストするときのツールであるJUnitの最新機能を紹介します。 メインは2021年にリリースされた5.8を対象にしますが、一部5.7の機能も深掘ります。
JJUG CCC 2022 Springでのプレゼンになります。
プレゼンアブスト : https://fortee.jp/jjug-ccc-2022-spring/proposal/4152bc33-c3f3-4041-9c3e-3056d82dd51c
リポジトリ : https://github.com/kyonmm/junit-5-8-examples
JUnit5.7, 5.8の新機能紹介kyon_mm
View Slide
JUnitはJava言語で自動テストをするためのフレームワークとしてデファクトスタンダードの位置にある• JUnit5のリリース以降は継続的にリリースされている• 2022/05 最新版は5.8.2• 5.8と5.7の新機能を一部紹介• JUnitのスポンサーはこちらから• https://steadyhq.com/en/junit/about
Jupiterを中⼼に紹介引⽤ : https://junit.org/junit5/docs/current/user-guide
引⽤ : https://junit.org/junit5/docs/current/user-guide
JUnit 5.7の新機能1. DisplayName という MethodOrderer で、表示名に基づいてテストメソッドを英数字でソートする2. MethodOrderer.MethodName が MethodOrderer.Alphanumeric の代わりになった。3. @TestMethodOrder が存在しない場合のデフォルトの MethodOrderer をjunit.jupiter.testmethod.order.default で設定する4. @CsvFileSource は、リソースパスの代わりにファイルパスを指定できる5. 他は https://junit.org/junit5/docs/5.7.0/release-notes/index.html#new-features-and-improvements-2 を参照
DisplayName という MethodOrderer で、表示名に基づいてテストメソッドを英数字でソートする@TestMethodOrder(MethodOrderer.DisplayName.class)public class DisplayNameTestA {@Test@DisplayName("test03")void testX1(){}@Test@DisplayName("test01")void testX2(){}@Test@DisplayName("test02")void testX3(){}}
MethodOrderer.MethodName がMethodOrderer.Alphanumeric の代わりになった。@TestMethodOrder(MethodOrderer.MethodName.class)public class MethodNameTestA {@Testvoid testB(){}@Testvoid testA(){}@Testvoid test0(){}@Nested@TestMethodOrder(MethodOrderer.Alphanumeric.class)public class AlphanumericTestA {@Testvoid testB(){}@Testvoid testA(){}@Testvoid test0(){}}}
@TestMethodOrder が存在しない場合のデフォルトのMethodOrderer をjunit.jupiter.testmethod.order.default で設定するtest {useJUnitPlatform()systemProperty("junit.jupiter.testmethod.order.default", 'org.junit.jupiter.api.MethodOrderer$Random’)}
@CsvFileSource は、リソースパスの代わりにファイルパスを指定できる@ParameterizedTest@CsvFileSource(files = "src/test/java/org/example/csv/test-data.csv")void test(String name, String number, boolean isJVM){System.out.println("%s : version %s, is JVMLang : %s".formatted(name, number, isJVM));}
JUnit 5.8の新機能 1/21. テストクラスの実行順序をグローバルで指定する2. ネストしたテストクラスの実行順序をローカルで指定する3. assertThrowsExactly() メソッドが追加されました。これは assertThrows() をより厳密にしたもの。4. assertInstanceOf() メソッドは、assertTrue(obj instanceof X)の代わりとして機能します。5. 実際のオブジェクトに対する toString() が null または "null" を返した場合、assertNull() の失敗メッセージに実際のオブジェクトの型が含まれるようになりました。
テストクラスの実行順序をグローバルで指定するtest {useJUnitPlatform()systemProperty("junit.jupiter.testclass.order.default", 'org.junit.jupiter.api.ClassOrderer$ClassName')// systemProperty("junit.jupiter.testclass.order.default", 'org.junit.jupiter.api.ClassOrderer$DisplayName')// systemProperty("junit.jupiter.testclass.order.default", 'org.junit.jupiter.api.ClassOrderer$OrderAnnotation')// systemProperty("junit.jupiter.testclass.order.default", 'org.junit.jupiter.api.ClassOrderer$Random')testLogging {events "passed", "skipped", "failed"}}
ネストしたテストクラスの実行順序をローカルで指定する@TestClassOrder(ClassOrderer.OrderAnnotation.class)public class NestedTestA {@Nested@Order(3)class WhenLoginAOrder3 {@Testpublic void test(){Assertions.assertEquals("NestedTestA-WhenLoginA", "NestedTestA-WhenLoginA");}}@Nested@Order(1)class WhenLoginBOrder1 {@Testpublic void test(){Assertions.assertEquals("NestedTestA-WhenLoginB", "NestedTestA-WhenLoginB");}}@Nested@Order(2)class WhenLoginCOrder2 {@Testpublic void test(){Assertions.assertEquals("NestedTestA-WhenLoginC", "NestedTestA-WhenLoginC");}}}
assertThrowsExactly() メソッドが追加されました。これは assertThrows() をより厳密にしたもの。@Testpublic void test(){Assertions.assertThrows(RuntimeException.class, () -> {throw new SomeException();});Assertions.assertThrowsExactly(SomeException.class, () -> {throw new SomeException();});}public class SomeException extends RuntimeException { }
assertInstanceOf() メソッドは、assertTrue(obj instanceof X)の代わりとして機能します。@Testpublic void test(){Assertions.assertTrue(BigDecimal.valueOf(10.5) instanceof Object);Assertions.assertInstanceOf(Object.class, BigDecimal.valueOf(10.5));}
実際のオブジェクトに対する toString() の実装が null または "null"を返した場合、assertNull() の失敗メッセージに実際のオブジェクトの型が含まれるようになりました。@Testpublic void test(){Assertions.assertEquals("some", "null");Assertions.assertNull("null");}
JUnit 5.8の新機能 2/26. @TempDir を使って複数のテンポラリ・ディレクトリを作成できるようになりました。フィールドやメソッドのパラメータで @TempDir アノテーションを宣言するたびに、個別のテンポラリ・ディレクトリを作成するようになりました7. @TempDir フィールドをプライベートにすることができるようになりました。8. @CsvSource または @CsvFileSource で使用される数値リテラルは、700_000_000 のようなアンダースコアを使用して表現することができるようになりました。9. @CsvSource と @CsvFileSource に ignoreLeadingAndTrailingWhitespace 属性 (デフォルトではtrue に設定) が追加され、ホワイトスペースをトリミングするかどうかが制御できるようになりました。10. 他は https://junit.org/junit5/docs/5.8.0/release-notes/index.html#new-features-and-improvements-3 を参照
@TempDir を使って複数のテンポラリ・ディレクトリを作成できるようになりました。フィールドやメソッドのパラメータで @TempDir アノテーションを宣言するたびに、個別のテンポラリ・ディレクトリを作成するようになりました@Testpublic void test1(@TempDir Path dir1, @TempDir Path dir2) {Assertions.assertNotEquals(dir1.toAbsolutePath(), dir2.toAbsolutePath());}
@TempDir フィールドをプライベートにすることができるようになりました。@TempDirprivate static Path dir3;@Testpublic void test2(@TempDir Path dir4){Assertions.assertNotEquals(dir3.toAbsolutePath(), dir4.toAbsolutePath());}
@CsvSource または @CsvFileSource で使用される数値リテラルは、700_000_000 のようなアンダースコアを使用して表現することができるようになりました。@ParameterizedTest@CsvSource(value = {"apple,150000","orange,200000","'beef, chicken',0xF2F3F","sushi,1_500_000"})void underscore(String food, int rank) {Assertions.assertTrue(100000 < rank , "%s is lower than 100000".formatted(food));}
@CsvSource と @CsvFileSource に ignoreLeadingAndTrailingWhitespace属性 (デフォルトでは true に設定) が追加され、ホワイトスペースをトリミングするかどうかが制御できるようになりました。@ParameterizedTest@CsvSource(value = {"apple, 150000","orange, 200000","'beef, chicken', 0xF2F3F","sushi, 1_500_000"}, ignoreLeadingAndTrailingWhitespace = true)void ignoreWhiteSpace(String food, int rank) {Assertions.assertTrue(100000 < rank , "%s is lower than 100000".formatted(food));}