JUnit4.12がでました!……2014/12/4に。なんと6ヶ月経ってる。まぁいいや。
- JUnit 4.12の新機能紹介まとめ / うさぎ組(2014/8/5)
- JUnit 4.12から入ったTestRuleを軽く見てみる / 裏紙(2015/2/28)
- JUnit4.12時代のParameterized Test / mike-neckのブログ(2015/5/6)
ググっても4.12の情報があまり引っかからなかったので書いてみますね。
リリースノート斜め読み
とりま、Summary of changes in version 4.12 を斜め読み致して、気になるところ(★)は後でもう少し詳しく書く事にします。なお、バグフィックス、メッセージ変更、挙動の統合などの特にテストコーディングに影響を与えないものはスルー。
- Assersions
- floatのassertNotEquals → float 使わない
- booleanのassertArrayEquals → boolean あまり使わない
- Command-line options
--filter
オプション追加 → コマンドライン使わない
- Test Runners
- ParentRunnerの拡張ポイント追加 → 少し楽になったのかも
- AnnotationBuilderのインナークラス対応 → Runner作るなら
- AnnotationValidator → 新機能ー ★
- Exception Testing
- ExpectedExceptionのメッセージが変えられる → ちょっと嬉しいかも
- ErrorCollector#checkSucceedsのジェネリック化 → checkSucceeds使ったことない
- Timeout for Tests ★
- TestFailedOnTimeoutException追加 → 具体的な型になるのはいいこと
- Timeoutのスタックトレースが出せる → よさげ
- Timeoutの指定方法が増えた → よさげ
- Parameterized Tests ★
- Iterable<Object[]>じゃなくてよくなった → よさげ
- UseParametersRunnerFactory → 新機能ー
- Rules
- Stopwatch追加 → よく書く ★
@Rule
がstaticにも書ける → へ? ★- DisableOnDebug追加 → 使えなくはないんだろうけども
- Theories
- 失敗時のメッセージ改善 → よく使ってる人は影響ある?
- DataPointsからとるのに名前指定ができるように → よさげ ★
- enumやbooleanのDataPointを自動生成 → 使えそう
- DataPointsにIterableが使えるように → よさげ ★
- Categories
@Category
が@Inherited
に → 継承しないけどする時は嬉しいかも@Categories.IncludeCategory
とかにanyMatchが指定できるように → Categoriesランナー使わない
- Maven → スルー
結構なボリュームありますね。
気になるところを個別確認
リリースノート読んだり、プルリク読んだり、コード読んだり書いてみたりしつつ、思ったことを適当に書いていきます。書いてみたのはこの辺に置いてますけど、特に参考にはならなさそうです。
AnnotationValidator
一応新機能なのでとりあげ。 アノテーションにつけるバリデーターフレームワークです。アノテーションを作らないなら関係ありません。アノテーションを作るということは、それを対象にしたRunnerやRuleを作るということなので、この機能の恩恵を受ける人は限定的でしょうか。
JUnit内では「@Category
は@Before
とかが付与されているメソッドにつけてはならない」などの制約をつけるために使用されています。あと、別経路のPublicClassValidator
と言うのが作られていて、テストクラスがpublicであることをこいつで検証するようになってます。AnnotationValidatorの拡張ではなく、ちょっと強引な作りになっていますが、今後はJUnit内部もこの系統のバリデーションに変更されていくのでしょう。internalでもexperimentalでもなく、JUnit的にはトップレベルのorg.junit.validator
パッケージにいきなり来ているあたりからも意気込みを感じますね(適当)。
JUnitが提供するアノテーションに片っ端からこの手のバリデーションが入るようになると、JUnitを拡張した系統のテスティングフレームワークで困ったことがでてくるかもしれないなーとぼんやり思いました。
関連で、JUnit4.11で非publicクラスを実行した場合に落ちるタイミングはインスタンス化しようとした際の「publicコンストラクタがねーよ」だったんですけど、その前に「publicクラスじゃねーよ」と言って落ちるようになってます。条件/タイミングが変わっているのでちょっと注意かも。
AnnotationValidatorのインスタンスは複数のRunnerで共有されるので、イミュータブルかつスレッドセーフにせよとのこと。 また、インスタンスはAnnotationValidatorFactoryがnewInstanceで作るのでpublicのデフォルトコンストラクタが必要です。 これらのことから、AnnotationValidatorはオーバーライドできる3メソッド(validateAnnotatedClass, validateAnnotatedMethod, validateAnnotatedField)の引数に対してしか操作できません。で、どのアノテーションのバリデーターにするかで呼ばれるメソッドがかわります……なんかダサ……いやなんでもない。
Parameterized
- パラメータ定義が少し楽になった
- Runnerが拡張しやすくなった
一つ目が地味ながら嬉しそうな、@Parameters
でIterable<Object[]>
を作らずによくなったこと。Iterable<? extends Object>
になったので、適当にイテレートできる物体を押し付ければパラメタライズドに使えます。今までIterable<Object[]>
だったのはリフレクションで実行する時の引数がObject[]
だからと言う実装都合の話なので、この辺を吸収する程度ではありますがいい変更だと思います。その分JUnit内部がごちゃっとしてるのは……まぁ仕方ないことなのかなと。
もう一つは@UseParametersRunnerFactory
の追加で、これはParameterizedランナーの中の個々で実行されるテストのRunnerを変更するための拡張点です。JUnit4.11まではParameterizedクラスの中にTestClassRunnerForParameters
と言うインナークラスがあり、これがテストを実行するランナー本体でした。これがBlockJUnit4ClassRunnerWithParameters
に切り出されて公開クラスとなったので、Runnerの拡張が可能になったわけです。
しかし、従来の拡張したRunnerがそのまま使用できるわけではありません。アノテーションのパラメータ型名はParametersRunnerFactory
であり、Parameterを想定したRunnerが必要なことを主張しています。RunnerFactory
ではないのです。うまく繋ぎこむラッパーを書けないことはないとは思うのですが、変更点を切り離しきったらRuleになる気もしてしまうのが微妙な感じ。
Theories
こちらもパラメータ定義まわりの微修正ですね。
@DataPoints
が配列だけだったのが、Iterableも良くなりました。これで無駄にListを作ってtoArrayしていた過去とおさらばできます。
@FromDataPoints
は大きな改善に思えます。JUnit4.11まではテストメソッドに同じ型の引数が複数あった場合、型の一致するすべての@DataPoints
から取得されたものがねじ込まれてしまうため、テスト用の別の型を定義して回避するなど涙ぐましい努力が必要でしたが、@FromDataPoints
を引数に付与すれば名前で紐付けられます。何年か前にこれが欲しかった……。
Stopwatch
時間を計るためのルール。よく作るのが標準で用意されるので少し手軽になった。おそらくfinished
メソッドだけをオーバーライドする実装ばかりするんだろうなーと。1クラスでやるならLambdaで書きたいところだけど、継承した1クラスを作って全体で使ったりするとかになるだろうから、いいか。
しかしJUnitは「protectedメソッドいっぱい用意してるから、必要なやつオーバーライドしてね!」というノリだなーと今更ながら思いました。
staticな @Rule
変な書き方ができるようになった。
@Rule @ClassRule public static TestRule rule = ...;
パッと見た感じ、テストクラスと各テストメソッドに対して同じルールがかかるのが期待できて、その通り動く。気にしなくてはいけないのは、通常のRuleはテストメソッドごとにインスタンス化されるのでステートを持っていても問題ないけれど、ご覧の通りstaticフィールドなので同じインスタンスを共有することになるのは注意が必要。つまりStopwatchとかは(今の実装だと)使えません。
しかしこれできて何が嬉しいんだろう……。@ClassRule
に絡む時点でExternalResource
系の重めのRuleなんだろうけど、正直ユースケースがわからないです。
Timeout周りの強化
コンストラクタやファクトリメソッドが充実して、スタックトレースとかその辺も強化された。ドキュメントを読めばわかる感じなので特に触ってません。予測できるAPIというのは良いですね。
タイムアウトの指定はシンプルにいくなら@Test(timeout = 99)
みたく書けるんだけれど、全テストメソッドに指定するのも面倒なのでTimeout
ルールを使うわけです。で、ミリ秒だけだったんだけどTimeUnit
を使える今風(と言うほど新しくもないけど)なコンストラクタと、何かできそうな感じのTimeout#builder()
が増えました。でもTimeout.Builder
のできる事は少ないので、なんだろこれという気分にはなりました。まぁbooleanを受け取らせるファクトリメソッドをオーバーロードするよりはマシ……かな。
あとRuleに追加されたDisableOnDebug
はTimeout
での使用がメインぽい。DisableOnDebugがジェネリック化されてないのはなぜだろうとは思ったけど、用途を考えると要らない気もするので気にしない事にします。
どうでもいいけど、なんかTimeout.java
がすごく大きくなっててちょっとびっくりした。
まとめ
常用するのにインパクトのある変更なかったー!! Parameterized/Theory使いは影響あるけど、「ちょっと楽になるけど知らなくても問題ない」程度。魔改造クラスタに足突っ込んでないのであれば、JUnit実践入門の内容でまだまだ第一線余裕でしょう。
JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)
- 作者: 渡辺修司
- 出版社/メーカー: 技術評論社
- 発売日: 2012/11/21
- メディア: 単行本(ソフトカバー)
- 購入: 14人 クリック: 273回
- この商品を含むブログ (68件) を見る
もう発売されてから2年以上経ってるんだなぁ。