jcunit's blog

JCUnitの開発日誌(ログ)です。"その時点での"JCUnit作者の理解や考え、開発状況を日本語で書きます。

IntelliJはParameterizedテストランナーを特別扱いする

@Suiteのついたテストクラスはまとめていろんなクラスにあるテストを実行する。このいろんなクラスというのはSuiteの「子」としてJUnitに扱われる。 @Suiteアノテーションがつけられたクラスの中のあるメソッドIntelliJのテスト結果画面から選択すると、選ばれたメソッドが属するクラスの選ばれたメソッドを実行する。このとき、@Suiteがついたクラス(親側のクラス)はもう関係ない。 このアプローチがうまく行くのは「子」が静的なクラスだからだ。

    @RunWith(Suite.class)
    @Suite.SuiteClasses({ExampleSuite.Test1.class, ExampleSuite.Test2.class})
    public class ExampleSuite {
      public static class Test1 {

ためしに、こういのを作ってみるといい。static修飾子をTest1から取り去るとテストが動かなくなってしまうのがわかる。

ところでParameterizedもSuiteの一種なのだ。 だが、通常のSuiteと異なり、

    
    // Parameterized.Parameters
    new Object[]{
       {"test1", "hello", "world"}, // 0
       {"test2", "scott", "tiger"}  // 1
    }

のような二重配列の中の一個一個の配列(=テストケース)例えば{"test1", "hello", "world"}が「子」に対応するだ。これらからParameterized#createRunnersForChildrenによってテストランナーが生成され、Parameterizedオブジェクトに登録される。 そして、これを一個一個別の静的クラスにすることはできない。動的に静的なクラスを作ることはできませんよね?

IntelliJ@Parameterizedテストのメソッドを個別に実行するように要求されると、実行クラスはSuiteとなる親のクラス(つまり@Parameterizedがついたクラス)、メソッドは指定されたものを実行する。 これだけでは一体、何番目のテストケースを実行するのかわからない。

ではどうするか?プログラム引数として[0]とか[1]とかを渡すのだ。 これがJUnitの側で解釈されて何番目のテストケースが実行されるかが決まる。

なるほど。

で、JCUnit。JCUnitのランナーはこのParameterizedランナーの仕組みに"則って"作られている。"則って"というのは真似して、という意味だ。Parameterizedを継承していないのだ

だから、JCUnitのテスト結果画面から、テストメソッドを一個だけ選んで実行しようとしても動かない。IntelliJがParameterizedだと認識してくれないから、プログラム引数に[1]とか[10]とかをくれないのだ。 Parameterized#createRunnersForChildrenをオーバーライドすればそれで仕事は終わりなのに、なぜか?

createRunnersForChildrenprivateだからだ。ふざけんな。

じゃ、どうするか?ずいぶん前にぐちゃぐちゃ工夫したのだが、実行したいテストメソッド名がtestMethodだとしたらIntelliJの実行ダイアログでメソッド名の欄をtestMethod[10]とかに変更してみてほしい。10番目のテストが実行されるはずだ。

しかし、ブログは書いてみるもので、アタマが整理されてうまいインチキを思いついた。 試してみてうまく行ったら、後日報告することにしたい。