0
0

More than 1 year has passed since last update.

Junit4 を自作してみた

Last updated at Posted at 2022-11-11

JUnit4 を作ってみた

Qiita に Junit を作る記事 はあったが、アノテーションを使っていなかったので、今回はアノテーションを使った JUnit を自作してみた。

参考にしたコードは、junit4/src/main/java/org/ 以下です。成果物は、

にあります。

簡単に使い方を説明すると、以下のようなファイルを作り、実行すると、

SampleTest1.java
import myjunit4.JUnitCore;
import myjunit4.Test;
import myjunit4.Before;
import myjunit4.After;
import myjunit4.Assertion;

public class SampleTest1 {
	private int hoge;
	public static void main (String[] args) {
		JUnitCore.main(SampleTest1.class.getName());
	}
	@Before
	public void beforeTest() {
		System.out.println("Test Start...");
		hoge = 0;
	}
	@After
	public void afterTest() {
		System.out.println("Test Finished...\n");
	}
	@Test
	public void test1() {
		Assertion.assertEquals("Should be equal.", 0, hoge);
	}
	@Test
	public void test2() {
		Assertion.assertEquals("Should not be equal.", 1, hoge);
	}
}

Before -> Test -> After の順番で、メソッドが実行される流れになっている。

それでは中身を見てみましょう。

自作 JUnit の中身

Before, Test, After の実体はアノテーションを普通に定義しているだけのものになっています。

Test.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Test {}

ここはそこまで難しくはありませんね。Before と After も同じ感じです。
問題は、JUnitCore.main(クラス名) の部分ですね。
ここでは最初に、クラスのオブジェクトを forName で取得(ここらへん)して、それに定義されているメソッドに対して Testアノテーション・Beforeアノテーション・Afterアノテーション が定義されているメソッドを配列に登録します。

JUnitCore.java
			Test testAnnotation = method.getAnnotation(Test.class);
			Before beforeAnnotation = method.getAnnotation(Before.class);
			After afterAnnotation = method.getAnnotation(After.class);
			if ( testAnnotation == null && beforeAnnotation == null && afterAnnotation == null ) continue;
+			if ( testAnnotation != null ) testMethods.add(method);
+			if ( beforeAnnotation != null ) beforeMethods.add(method);
+			if ( afterAnnotation != null ) afterMethods.add(method);

そして、それを使って、Statement という抽象クラスを継承した TestStatement, BeforeStatement, AfterStatement クラスを作り、それぞれで定義された evaluate() を実行していきます。
以下が、TestStatement の例です。

TestStatement.java
package myjunit4;

import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;

import myjunit4.Statement;
import myjunit4.Counter;

public class TestStatement extends Statement {
	private List<Method> testMethods = new ArrayList<Method>();
	private Object target;
	private Counter counter;

	public TestStatement(List<Method> testMethods, Object target, Counter counter) {
		this.testMethods = testMethods;
		this.target = target;
		this.counter = counter;
	}

+	@Override
+	public void evaluate() throws Throwable {
+		for ( Method method : testMethods ) {
+			counter.addCount();
+			try {
+				method.invoke(target);
+			} catch (Throwable e) {
+				counter.addFailure();
+			}
+		}
+	}
}

これに、Counter クラスで、実行したテストの総数やエラーの数を数えています。

ここまでで実装を見てみて如何だったでしょうか?意外と簡単だったのではないでしょうか?
本家のコードを参考にした時は、意外と簡単に出来ていて自分も驚きました。
今後、JUnit を使う時は、JUnit の気持ちにより近づいて実装ができるようになれれば嬉しいです。
暇があったら、JUnit4 の本家のコードの解説もしたいと思います。

0
0
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
0
0