概要
JUnit4の便利な機能が
JUnit5でどのように実装されているか、確かめてみました。
古いテストケースをJUnit5に移すときの自分用備忘録。
諸々の説明はJUnit5公式ドキュメントを参照してください。
検証環境
検証環境は次の通りです。
OS : Windows 7 Home Edition 64bit
Java : JavaSE 15
IDE : STS 4.10.0
その他 : Spring Boot 2.5.5
JUnit4, 5用に別々にプロジェクトを作成
注意事項
Spring Bootをウィザードで作った場合、
そのままだとJUnit4が使えません。
対策としてプロジェクトを作ってから、
pom.xmlからJUnit4を追加、
spring-boot-starter-testへの依存関係を
コメントアウトしました。
新旧比較する機能
- 一時フォルダ作成
- テスト中メソッド名取得
- エラーが出ても全ケースを実施
- 同じテストケースを様々なパターンで繰り返し実施
一時フォルダ作成
JUnit4(抜粋)
@Rule
public TestName testName = new TestName();
@Test
public void testAboutTemporaryFile() throws Exception {
final String testString = "This is a test.";
File file = tempFolder.newFile("sample.txt");
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(file)));
writer.write(testString);
writer.close();
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(file)));
String line = "";
String tmp;
while ((tmp = reader.readLine()) != null) {
line += tmp;
}
reader.close();
assertEquals(testString, is(line));
}
JUnit5(抜粋)
@TempDir
File tempFolder;
@Test
public void testAboutTemporaryFile() throws Exception {
final String testString = "This is a test.";
File file = new File(tempFolder, "sample.txt");
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(file)));
writer.write(testString);
writer.close();
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(file)));
String line = "";
String tmp;
while ((tmp = reader.readLine()) != null) {
line += tmp;
}
reader.close();
assertEquals(testString, line);
}
テスト中メソッド名取得
JUnit4(抜粋)
@Rule
public TestName testName = new TestName();
@Test
public void testAboutMethodName() throws Exception {
System.out.println(
testName.getMethodName() +
" is started.");
}
JUnit5(抜粋)
@Test
public void testAboutMethodName(TestInfo testInfo)
throws Exception {
System.out.println(testInfo + " is started.");
}
JUnit4標準出力
testAboutMethodName is started.
JUnit5標準出力
DefaultTestInfo [
displayName = 'testAboutMethodName(TestInfo)',
tags = [],
testClass = class com.example.demo.JUnit5Tests,
testMethod = public void com.example.demo.JUnit5Tests.
MethodNameTest(org.junit.jupiter.api.TestInfo)
throws java.lang.Exception] is started.
コードの量から引き出せる情報量の差が圧倒的。
エラーが出ても全ケースを実施、同じテストケースを様々なパターンで繰り返し実施
※ケースをまとめて実施することに関連した機能のため、
両方をまとめて比較します。
JUnit4(抜粋)
@RunWith(Parameterized.class)
public class JUnit4ParameterizedTests {
@Rule
public ErrorCollector errors = new ErrorCollector();
@Parameters
public static List data() {
return Arrays.asList(
// 4の階乗は24、5の階乗は120、
// 期待値が異なることでテストはエラーとなる
new Object[][] {
{ 0, 1 },
{ 1, 1 },
{ 2, 2 },
{ 3, 6 },
{ 4, 23 },
{ 5, 121 },
{ 6, 720 }
}
);
}
private int input;
private int expected;
public JUnit4ParameterizedTests(int input, int expected) {
this.input = input;
this.expected = expected;
}
@Test
public void testParameterizedFactorial() {
errors.checkThat("Factorial of " + this.input, , calcurateFactorial(this.input), is(this.expected));
}
public static int calcurateFactorial(int n) {
if (n >= 2) {
return calcurateFactorial(n - 1) * n;
} else {
return 1;
}
}
}
JUnit5(抜粋)
public class JUnit5ParameterizedTests {
// 4の階乗は24、5の階乗は120、
// 期待値が異なることでテストはエラーとなる
@ParameterizedTest
@CsvSource({
"0, 1",
"1, 1",
"2, 2",
"3, 6",
"4, 23",
"5, 121",
"6, 720"
})
public void testParameterizedFactorial(int input, int expected) {
int actual = input;
assertEquals(calcurateFactorial(actual), expected);
}
public static int calcurateFactorial(int n) {
if (n >= 2) {
return calcurateFactorial(n - 1) * n;
} else {
return 1;
}
}
}
注意事項として、JUnit5ではテストメソッドに@Testをつけないこと。
つけてしまうと、次の警告メッセージが表示されます。
ただ、テストは実行できます。
This is typically the result of annotating a method
with multiple competing annotations
such as @Test, @RepeatedTest,
@ParameterizedTest, @TestFactory, etc.
最後に
最後までお読みいただき、ありがとうございました。