JUnit4.4 - その4

JUnit4.4のソースを見てて思ったこと @BeforeClassに関して

@BeforeClassはテストクラス内の各テスト実行前に1度だけ呼びたいメソッドに定義します。(メソッドはpublicかつstaticでなければいけません)

こんな感じ

public class FooTest{

    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClassが呼ばれました");
    }
    
    @Test
    public void testA(){
        System.out.println("testAが呼ばれました");
    }
    
    @Test
    public void testB() {
        System.out.println("testBが呼ばれました");
    }
}

これを実行するとコマンドプロンプトには下記のように表示されます。

beforeClassが呼ばれました
.testAが呼ばれました
.testBが呼ばれました

んで、ソースを見てて気付いたのですが、この@BeforeClassって複数定義可能な使用になってるんです。
今まで複数定義しようなどと思ったことがないし、今後もそんなことしないですけどねw
(1つのクラス複数定義は推奨されていないとか公式ドキュメントに書いてあったりしないのかな??)

ただ、疑問に思ったことが。
下記のようにテストケースを定義した場合

public class FooTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClassが呼ばれました");
    }
    
    @BeforeClass
    public static void beforeClass2() {
        System.out.println("beforeClass2が呼ばれました");
    }
    
    @Test
    public void testA(){
        System.out.println("testAが呼ばれました");
    }
    
    @Test
    public void testB() {
        System.out.println("testBが呼ばれました");
    }
}

コマンドプロンプトでは

beforeClassが呼ばれました
beforeClass2が呼ばれました
.testAが呼ばれました
.testBが呼ばれました

と表示されると思いきや、実は下記のように表示されます。

beforeClass2が呼ばれました
beforeClassが呼ばれました
.testAが呼ばれました
.testBが呼ばれました

そう、beforeClass2が先に呼ばれちゃうのです。
理由はJUnit内部にて@BeforeClassのメソッドを取得した後にjava.util.Collectionsのreverseメソッドで要素の順序を逆にしてるからなのです。
「なんでなんだ???」と疑問に思ってたんですが、reverseする理由としてはテスト対象クラスの親クラスで定義されている@BeforeClassメソッドを先に実行させたいからだと勝手に解釈しました。
この@BeforeClassはテスト対象クラスの親クラスで定義されていても問題なく動作します。そしてreverseされる前の段階ではテスト対象クラスの@BeforeClassメソッドが一番最初にaddされた状態のListになっているので、親クラスの@BeforeClassのメソッドを先に実行したいためreverseしてるんじゃないかなと。もっと別の深い理由があるのかな???
あと、メソッドの取得に関してはClass#getDeclaredMethodsを使用しているのですが、このメソッドってメソッドの取得順序に関して保障されていないと聞いたことがあるんですが、そのあたりは考慮されていないって事ですかね??

結論としては同一テストクラス内にて@BeforeClassは複数定義すんな(゚Д゚)ゴルァって事でしょうねぇ。まぁ、しないけどww