JUnit実践入門(初版)での JUnit 4.10 をベースに、書籍で紹介されている主要なJUnitの機能が TestNG 6.x で提供されているか比較してみました。
※全JUnit4.x系と全TestNGの6.x系のすべてのchangelogやコード、JavaDocを精読して調査したわけではありません。Googleでざっくりと検索した結果のまとめ記事になります。JUnit4.x系も、TestNG6.x系もそれぞれ活発に開発が続けられてますので、本記事で紹介している参考URLの内容や本記事の内容自体も近い将来、内容が古くなる可能性があります。随時気づいたら更新して行きたいとは思いますが、あくまでも 2013-01-14 時点でざっくり調べた範囲でのスナップショットとしてご了承ください。個人的にはTestNGラバーのため、JUnit4.xの最新状況を調べきれてない所も多々あると思います、ご容赦願います。
フレームワークとしてのコンセプトから異なりますのでJUnitと全く同じ意味と機能が提供されているわけではありませんが、目指すところはほぼ同じ機能がTestNGでも各種提供されています。
JUnit(4.10) | TestNG |
---|---|
"@Test", "@Ignore", "@After", "@Before", ... | 同等のアノテーションが利用可能。 |
例外発生の expect | "@Test(expectedExceptions)" |
タイムアウトの検出 | "@Test(timeOut)" |
JUnit組み込みのMatcher | TestNGでもいろいろデフォルトのassertionが提供されてます。 |
Hamcrestとの連携 | TestNGでもHamcrest利用できます。 |
"Enclosed" テストランナー | ネストクラスによる構成に対応。(注記参照) |
"Theories"によるParameterized Test | "@DataProvider"で柔軟に利用できます。 |
"Categories"によるカテゴリ化 | "Group"という概念でXMLでグルーピングを設定出来ます。 |
Assume | 無いかも・・・ |
"@Rule" | 無い。 |
Mockitoとの連携 | TestNGでもMockito使えます。 |
DbUnitとの連携 | TestNGでも使えたはず。 |
Androidのテスト | わざわざTestNGに切り替える必要あるか? |
コードカバレッジ | SonarとTestNGを連携させたことあります。他のカバレッジツールとの連携は不明。 |
Maven, Ant, Jenkinsとの連携 | Antはわかりませんが、Maven/Jenkinsとの連携は可能です。 |
Cucumberとの連携 | 無いかも・・・ |
まとめるとJUnit4.10にあってTestNGに無いものは・・・
でしょうか。あくまでもざっくりベースですので、各「同等有り。」とした機能について詳細まで踏み込めば、当然ながらJunit/TestNGとで差異が出てきます。
以下、私見に基づく注記。
その他、JUnitとTestNGで個人的に気になったポイントについて比べてみました。
JUnitはテストメソッドごとにインスタンスを生成します。
一方、TestNGはテストクラスごとにインスタンスを生成します。
この点は、テストメソッド間でDBコネクションなど生成にコストがかかるリソースを共有しようとする際にポイントとなってきます。
参考:
JUnitでは・・・すみません、JUnit 4.10の段階で、ライブラリとしてサポートしているかどうか断定できるほど調べきれませんでした。
利用者側で工夫する必要あり?参考:
TestNGではXMLによるテストスイートや"@Test"アノテーションでマルチスレッド実行をサポートしています。
まず大前提として、単体テストの段階で実行順序に依存するようなテストコードは避けたほうが良いという共通認識があると考えています。これはJUnit/TestNGにかぎらず、どの言語のどのテストフレームワークを使う場合でも同じだと考えています。
どうしても実行順序を制御したいとなりますと、それは単体ではなく、単体レベルの機能を連携させた結果をテストすることになるので、単体ではなく結合テスト以上のレベルだと思います。そうなりますと、単体テストフレームワークでどうにかするよりは振る舞いをテストするRSpecやCucumber、FITなどより上位のテストを実行するためのフレームワークを使ったほうが適切かもしれません。
TestNGの場合はテストケース間で依存性を持たせたり優先順位を設定することは可能ですが、あくまでもライブラリとしてそうした機能が提供されているだけであり、単体テストのレベルでそれに依存するのは避けたほうが良いと思います。(逆に結合テスト的なレベルのテストコードをTestNGで実装するのであれば、便利に活用できると思います)
一応ざっとGoogke先生に聞いてみて, JUnit/TestNGそれぞれでの実行順序の制御手法を見つけたのでメモしておきます。
JUnit向け:
TestNG向け:
注意:
割りと中立な書き方:
TestNGよりな書き方:
その他:
2013-01-14時点では、JUnit4.xの方がやや多機能になりつつあるようです。
ただし、テストフレームワーク単体としてではなく、それを補助する外部ライブラリやビルドシステムの連携など、フレームワークを取り巻く「エコシステム」のレベルで見てみると、やはりJUnitと連携する各種ライブラリやシステムの豊富さには圧倒されます。
TestNGはWebサイトにもあるように単体テストだけでなく、結合テストなどより大きなレベルのテストまで対応できるようなコンセプトで作られています。そのため、単体テストとしてのあるべき姿に厳密に従う(=JUnitのインスタンス生成ポリシー?)のではなく、多少単体テストとしての厳密性を放棄しても、より現実的な妥協点を探りやすい作りになっているように感じました。
個人的にはTestNGの方が、単体テストとしてのアーキテクチャに拘っていない分融通が効く感じがしてそこが好みではあります。
しかしながらWeb上のリソースではやはりJUnitに関する記事のほうが圧倒的多数を占めますし、Javaでのテスト自動化はJUnitを中心にエコシステムが形成されているため、TestNGをそれらと組み合わせようとすると一々、TestNGとの連携機能の有無やノウハウを調べないといけないため、その分のコストが発生します。
またテストケース間の依存性や状態の共有については、JUnitの方はアーキテクチャレベルで徹底して排除しようとしているように見えます。一方でTestNGは特にポリシーは押し付けず、プログラマに一任しているように思います。この点について、テストコード作成のスキルがばらばらなメンバーを想定するのであれば、TestNGの場合適切でない依存関係や状態共有が混入する危険があります。JUnitを使ったほうが、アーキテクチャレベルでそうした作りこみを難しくしているので、クリーンなテストコードを維持しやすそうです。
繰り返しますが個人的にはTestNGラバーですので、もしTestNGに目を向けてくれて、JUnitにしようかTestNGにしようか迷いましたら、そうした良し悪しで上手くバランスを取った上で決めていただければと思います。
Happy Test Coding!!