JUnit4 の実行順序

最近 JUnit にハマっています(笑)

アノテーションベースに生まれ変わった JUnit4

JUnit4 系では、アノテーションベースになり、テストがとても書きやすくなった(し、可読性も上がった)と個人的には感じている。
ただ、このアノテーション、結構な種類があり、どのアノテーションで定義されたものが、どのタイミングで実行されるのか、いまいち押さえられていない。ということで、今回はよく使われる @Before とか @After の他に、@RunWith、@Rule で指定できる TestWatcher の実行タイミングについても簡単に調べてみた。

テスト対象のクラス達

Runner
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class DummyJUnit4ClassRunner extends BlockJUnit4ClassRunner {

    public DummyJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
        System.out.println("DummyJUnit4ClassRunner");
    }
}
TestWatcher
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class DummyTestWacher extends TestWatcher {

    public DummyTestWacher() {
        System.out.println("DummyTestWacher");
    }

    @Override
    protected void starting(Description description) {
        System.out.println("DummyTestWacher#starting");
    }

    @Override
    protected void finished(Description description) {
        System.out.println("DummyTestWacher#finished");
    }
}
テストクラス
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(DummyJUnit4ClassRunner.class)
public class JUnitExecutionSequenceLearningTest {

    @Rule
    public DummyTestWacher wacher = new DummyTestWacher();

    public JUnitExecutionSequenceLearningTest() {
        System.out.println("SubTest");

    }

    @BeforeClass
    public static void beforeOnce() {
        System.out.println("@BeforeClass");
    }

    @Before
    public void before() {
        System.out.println("@Before");
    }

    @After
    public void after() {
        System.out.println("@After");
    }

    @AfterClass
    public static void afterOnce() {
        System.out.println("@AfterClass");
    }

    @Test
    public void test1() {
        System.out.println("@Test-1");
    }

    @Test
    public void test2() {
        System.out.println("@Test-2");
    }
}

結果

で、これを実行した結果がコレ。

DummyJUnit4ClassRunner
@BeforeClass
DummyTestWacher
SubTest
DummyTestWacher#starting
@Before
@Test-1
@After
DummyTestWacher#finished
DummyTestWacher
SubTest
DummyTestWacher#starting
@Before
@Test-2
@After
DummyTestWacher#finished
@AfterClass

ランナーは何よりも先に呼び出されるのね。
あと、@BeforeClass はテスト対象のクラスがインスタンス化されるよりも前に呼び出されるんだ〜。
確かに @BeforeClass は、メソッドシグネチャも public static じゃないと怒られるからな。そりゃそうか。
あとは、まぁ何となく予想通りかな。

@Rule の可能性

このルールクラスは何となくやけど、可能性がありそう。この辺りは別途調べて結果を載せるぜよ( *`ω´)