日々常々

ふつうのプログラマがあたりまえにしたいこと。

JUnitの各要素の実行順

仕組みとか説明するのも面倒だし、ソースを出すのも手間だし、論より証拠って便利な言葉に乗っかって。

こんなテストがあったとする。ありえないけど。ないけど、まぁあったとする。

@Grab('junit:junit:4.11')
import org.junit.*
import org.junit.rules.*
import org.junit.runner.*
import org.junit.runners.model.*

class Tests {

    static { println 'static-initializer' }
    @ClassRule public static TestRule classRule = {s,d ->{->
        println 'ClassRule-before'; s.evaluate(); println 'ClassRule-after'
    } as Statement}
    @BeforeClass static void setUpClass() { println 'BeforeClass' }

    { println 'initializer' }
    Tests() { println '<init>' }
    @Rule public TestRule rule = {s,d ->{->
        println 'Rule-before'; s.evaluate(); println 'Rule-after'
    } as Statement}
    @Before void setUp() { println 'Before' }

    @Test void testMethod1() { println 'test1' }
    @Test void testMethod2() { println 'test2' }

    @After void tearDown() { println 'After' }

    @AfterClass static void tearDownClass() { println 'AfterClass' }
}

で実行する。と、こう出る。

static-initializer
ClassRule-before
BeforeClass
initializer
<init>
Rule-before
Before
test1
After
Rule-after
initializer
<init>
Rule-before
Before
test2
After
Rule-after
AfterClass
ClassRule-after
JUnit 4 Runner, Tests: 2, Failures: 0, Time: 31

おーけー?

  1. staticイニシャライザ
  2. @ClassRule の前処理
  3. @BeforeClass
  4. (テストメソッド数繰り返し)
    1. インスタンスイニシャライザ
    2. コンストラクタ
    3. @Rule の前処理
    4. @Before
    5. *テストメソッド本体*
    6. @After
    7. @Rule の後処理
  5. @AfterClass
  6. @ClassRule の後処理

JUnitのコードを読んでたり、予想出来る人にはあたりまえの話かな。別段JUnitだからとか関係ない話も混ざってるけど。
テストメソッドでイニシャライザとかコンストラクタとか使うことは(Parameterizedランナーを使用する場合などを除いて)無いとは思いますが、とりあえずこんな感じだ、と。
RuleとBefore/Afterとの順番は悩むことも有るのかなーと思わなくも無いのですが、そんな悩みを抱えて調べたりするくらいなら、素直にRuleChainさんとかを使うこと。今はこうなってるってだけで、今後のバージョンでRuleとBefore/Afterの順番が変わっても文句はいえません。特にドキュメント化もされてなかったはずだし。