LoginSignup
2
1

More than 1 year has passed since last update.

JUnit4とJUnit5の比較(便利な機能編)

Last updated at Posted at 2021-09-26

概要

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.

最後に

最後までお読みいただき、ありがとうございました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1