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
をオーバーライドすればそれで仕事は終わりなのに、なぜか?
createRunnersForChildren
がprivate
だからだ。ふざけんな。
じゃ、どうするか?ずいぶん前にぐちゃぐちゃ工夫したのだが、実行したいテストメソッド名がtestMethod
だとしたらIntelliJの実行ダイアログでメソッド名の欄をtestMethod[10]
とかに変更してみてほしい。10番目のテストが実行されるはずだ。
しかし、ブログは書いてみるもので、アタマが整理されてうまいインチキを思いついた。 試してみてうまく行ったら、後日報告することにしたい。