#navi_header|技術| JUnit実践入門(初版)での JUnit 4.10 をベースに、書籍で紹介されている主要なJUnitの機能が TestNG 6.x で提供されているか比較してみました。 #amazon||> ||< - JUnit -- http://junit.sourceforge.net/ - TestNG -- http://testng.org/doc/index.html ※全JUnit4.x系と全TestNGの6.x系のすべてのchangelogやコード、JavaDocを精読して調査した '''わけではありません。''' Googleでざっくりと検索した結果のまとめ記事になります。JUnit4.x系も、TestNG6.x系もそれぞれ活発に開発が続けられてますので、本記事で紹介している参考URLの内容や本記事の内容自体も近い将来、内容が古くなる可能性があります。随時気づいたら更新して行きたいとは思いますが、あくまでも 2013-01-14 時点でざっくり調べた範囲でのスナップショットとしてご了承ください。個人的にはTestNGラバーのため、JUnit4.xの最新状況を調べきれてない所も多々あると思います、ご容赦願います。 #more|| * 書籍で紹介されている各種JUnitの機能について、TestNGで使えるか? フレームワークとしてのコンセプトから異なりますのでJUnitと全く同じ意味と機能が提供されているわけではありませんが、目指すところはほぼ同じ機能がTestNGでも各種提供されています。 | JUnit(4.10) | TestNG |h | "@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に無いものは・・・ - AssumeXXYY - "@Rule" アーキテクチャ - Android開発での連携 - Cucumberとの連携 でしょうか。あくまでもざっくりベースですので、各「同等有り。」とした機能について詳細まで踏み込めば、当然ながらJunit/TestNGとで差異が出てきます。 以下、私見に基づく注記。 - JUnitの"Enclosed"テストランナーを使った、InnerClassを使ってテストコードを整理する技法ですが、2011-06-30リリースの6.1からはネストクラス中のアノテーションも自動で拾ってくれるようになっているようです。 -- CHANGES.txt: --- https://github.com/cbeust/testng/blob/master/CHANGES.txt --- "6.1"のところに "Added: Nested classes are now automatically added for consideration for inclusion" とありました。 -- 実験コード with TestNG 6.8 --- https://gist.github.com/4528710 - "Enclosed"機能そのもののサポート云々というよりは、InnerClassを用いてsetup/teardownを含めたテスト単位の構造化をサポートしているか否かが重要ポイントに思います。その点で、TestNG 6.1 以降であれば問題なくサポートされ、構造化も可能に思われます。(テストクラスのインスタンスメンバをInnerClassからアクセス云々までは未検証。単体テストのポリシーからそこまで状態を共有させるのは避けたほうが良いかと。) - Hamcrestとの連携ですが、MatcherAPIのカスタマイズなど高度な話題までは踏み込んで調べていません。もしかしたらTestNGと連携したり、Matcherなどディープな領域をTestNGと連携させようとすると、色々とトラブルが出てくるかもしれません。というかTestNGで実験中、よくわからない嵌まり方して地雷踏んだかも・・・。 - "@Rule" アーキテクチャ:2013年1月時点では、TestNG側では正式対応には至ってないようです。 -- 2011年の6月頃に、TestNG側でも"@Rule"相当の機能を使えるようにしよう、という話題があったようです。2013年1月時点では、その後どうなったのか不明です。StackOverflowではTestNGの開発者自身が「基底クラスから派生とか上手く使えばRule相当できるよ!」と書いてたりします。(質問者からは、「でもそれって結局TestNGがRule相当の機能持ってないってことだよね?」とか突っ込まれてます。) -- Does TestNG support something like JUnit4's @Rule? - Stack Overflow --- http://stackoverflow.com/questions/6099633/does-testng-support-something-like-junit4s-rule -- wolfs/testng-rules - GitHub --- https://github.com/wolfs/testng-rules -- Rules for TestNG - Google グループ --- https://groups.google.com/forum/#!topic/testng-dev/RounLOTz_UU - Cucumberとの連携:2012年の5-8月にGitHub上でCucumber連携のプロジェクトが始まったようです。現在の安定性や今後のサポートは不明。 -- Re: [Cucumber] [JVM] - Google グループ --- https://groups.google.com/forum/?fromgroups=#!msg/cukes/ih1xOvLBIao/gjMrmHRTaTwJ -- [testng-users] TestNG Integration with Cucumber - Google グループ --- https://groups.google.com/forum/?fromgroups=#!topic/testng-users/pn9iL70pqYY -- talios/cucumber-testng-factory · GitHub --- https://github.com/talios/cucumber-testng-factory * その他で比較してみたポイント その他、JUnitとTestNGで個人的に気になったポイントについて比べてみました。 ** テストクラスのインスタンス生成の比較 JUnitはテストメソッドごとにインスタンスを生成します。 一方、TestNGはテストクラスごとにインスタンスを生成します。 この点は、テストメソッド間でDBコネクションなど生成にコストがかかるリソースを共有しようとする際にポイントとなってきます。 参考: - TestNG Basic Concepts and Annotations -- http://www.asjava.com/testng/testng-basic-concepts-and-annotations/ - JunitNewInstance -- http://martinfowler.com/bliki/JunitNewInstance.html --- Martin Fowler氏によるJUnitにおけるインスタンス生成がなぜ今の設計になったのかの説明。 - Why variables in NUnit [TestFixture] classes should be static? - James Newkirk's Blog - Site Home - MSDN Blogs -- http://blogs.msdn.com/b/jamesnewkirk/archive/2004/12/04/275172.aspx --- NUnitは最初はTestNGと同じく1テストクラス=1インスタンスだったが、後にJUnit方式で1テストメソッド=1インスタンスになったらしい。その変更による、状態を共有するにはstaticを使う必要がある点についての弁解記事。 ** 複数のテストケースをマルチスレッドで実施 JUnitでは・・・すみません、JUnit 4.10の段階で、ライブラリとしてサポートしているかどうか断定できるほど調べきれませんでした。 利用者側で工夫する必要あり?参考: - Junit multiple threads - Stack Overflow -- http://stackoverflow.com/questions/7809268/junit-multiple-threads - JUnit のテストメソッドを複数スレッドで実行する - 日々常々 -- http://d.hatena.ne.jp/irof/20110126/p1 - java - Concurrent JUnit testing - Stack Overflow -- http://stackoverflow.com/questions/4970907/concurrent-junit-testing TestNGではXMLによるテストスイートや"@Test"アノテーションでマルチスレッド実行をサポートしています。 - 5.10 - Parallelism and time-outs -- http://testng.org/doc/documentation-main.html#parallel-running - WeBlowg Side:TestNGでマルチスレッドテストを試してみた -- http://www.gside.org/blowg/e/entry/200810292217 ** テストメソッドの実行順序制御 まず大前提として、 '''単体テストの段階で実行順序に依存するようなテストコードは避けたほうが良い''' という共通認識があると考えています。これはJUnit/TestNGにかぎらず、どの言語のどのテストフレームワークを使う場合でも同じだと考えています。 どうしても実行順序を制御したいとなりますと、それは単体ではなく、単体レベルの機能を連携させた結果をテストすることになるので、単体ではなく結合テスト以上のレベルだと思います。そうなりますと、単体テストフレームワークでどうにかするよりは振る舞いをテストするRSpecやCucumber、FITなどより上位のテストを実行するためのフレームワークを使ったほうが適切かもしれません。 TestNGの場合はテストケース間で依存性を持たせたり優先順位を設定することは可能ですが、あくまでもライブラリとしてそうした機能が提供されているだけであり、単体テストのレベルでそれに依存するのは避けたほうが良いと思います。(逆に結合テスト的なレベルのテストコードをTestNGで実装するのであれば、便利に活用できると思います) 一応ざっとGoogke先生に聞いてみて, JUnit/TestNGそれぞれでの実行順序の制御手法を見つけたのでメモしておきます。 JUnit向け: - java - How to run test methods in spec order in JUnit4? - Stack Overflow -- http://stackoverflow.com/questions/3693626/how-to-run-test-methods-in-spec-order-in-junit4 - java - Specifying an order to junit 4 tests at the Method level (not class level) - Stack Overflow -- http://stackoverflow.com/questions/3089151/specifying-an-order-to-junit-4-tests-at-the-method-level-not-class-level - Understanding JUnit method order execution « Gary Gregory -- http://garygregory.wordpress.com/2011/09/25/understaning-junit-method-order-execution/ TestNG向け: - testing - order of execution of tests in testng - Stack Overflow -- http://stackoverflow.com/questions/2669576/order-of-execution-of-tests-in-testng - How to execute testng test methods in order we specified using Priority IMethodInterceptor -- http://automation-webdriver-testng.blogspot.jp/2012/07/how-to-execute-testng-test-methods-in.html ** その他、Web上での JUnit4 と TestNG の機能比較記事 注意: - あくまでも個人的な感想ですが、Web上のJUnit4とTestNGの機能比較表のほとんどが「TestNG側の機能を軸に」JUnit4がそれに対応しているか、という形でまとめられているような印象を受けました。 - JUnit4になってマイナーバージョンアップのレベルでも機能拡張が多くなってきたため、これらの比較記事が参照する「JUnit4」のバージョンと、最新のバージョンが異なる可能性が非常に高いと思われます。そのため、これらの比較記事も最新のJUnit4の機能を正確に捉えていないように思われます。 - ですので、以下の参考リンクの比較記事は、それらが書かれた当時のJUnit4をベースにしていて、すでに古くなっている点を念頭に参照してください。 割りと中立な書き方: - Migration to JUnit4 or TestNG - XPlanner - Codehaus -- http://docs.codehaus.org/display/XPR/Migration+to+JUnit4+or+TestNG - コード品質を追求する: JUnit 4 対 TestNG -- http://www.ibm.com/developerworks/jp/java/library/j-cq08296/index.html - JUnit 4 & TestNG -- http://www.oki-osk.jp/esc/testing/JUnit4-TestNG.html TestNGよりな書き方: - JUnit 4 Vs TestNG – Comparison -- http://www.mkyong.com/unittest/junit-4-vs-testng-comparison/ --- 比較に使ってるJUnit4が古いきがする・・・。最新のJUni 4.10なら少なくともGroup Testには対応できるし、Enclosed使えばTestNGと同等のParameterized Testも対応出来る。 その他: - TestNG or JUnit | Javalobby -- http://java.dzone.com/articles/testng-or-junit - Yuri Zelikov - Google+ - TestNG vs. JUnit4 I am currently evaluating test… -- https://plus.google.com/101365568654452259113/posts/VR6t2jJRm9x * 2013-01-14時点でのまとめ 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!! #navi_footer|技術|