#navi_header|Groovy|
Groovyの面白いところは、Javaのprivateフィールドに何も特別な操作なしで参照したり更新することが出来る点です。
これは、特にレガシーコードをJUnitやTestNGなどの単体テストフレームワークに組み込むときに大変便利な特性になります。
本記事ではJavaのコードをGroovyで記述したTestNGのテストケースを使ってテストしてみて、privateを操作するテストコードのごく簡単なサンプルをMavenで組んでみます。
※2013-04-27追記:本記事ではGMavenを使っています。MavenでのGroovy/Javaのビルド("Joint Compile")で、もう少し実践的な構成にしたり、GMavenでなくmaven-antrun-plugin + GroovyのAntTaskを使ったMavenビルドの例を [[1188]] にまとめていますので、Maven設定の細かい調整はそちらを参照してください。
※2013-07-15追記:Maven3にて、JUnit(Java, Groovy) + TestNG(Java, Groovy) + Spock(Groovy)の5種類のテストケースを一気に実行するサンプルを用意しましたので、手っ取り早くコピペしたい場合はそちらを参照してみてください: [[1203]]
#more||
* 練習:JavaのコードをGroovyのTestNGでMavenに組み込む
まずは練習として、JavaのコードをGroovyで記述したTestNGのテストケースでテストするごく簡単なサンプルをMavenに組み込んでみます。
サンプルソース(gjt1)ツリー:
#pre||>
gjt1/
pom.xml
src/
main/
groovy/gjt1/Calc1.groovy
java/gjt1/Calc2.java
test/
groovy/gjt1/Calc1Test.groovy
java/gjt1/Calc2Test.java
||<
ソースは短いので、GistにUPしてます。DLしたら↑のソースツリーに整えてビルドしてみて下さい。
https://gist.github.com/4054109
ポイントとなる箇所だけ簡単に解説していきます。
** pom.xmlでgroovyソースのコンパイルとgroovyライブラリの依存性を組み込む
まずgroovyライブラリの依存性を組み込みます。今回はgroovy-1.8.8のjarをdependencyに組み込んでいます:
#pre||>
org.codehaus.groovy
groovy-all
1.8.8
||<
続いて、"*.groovy"をコンパイルするよう、gmavenプラグインを組み込んでいます。providerとして1.8を選択しています。
#pre||>
org.codehaus.gmaven
gmaven-plugin
1.4
1.8
generateStubs
compile
generateTestStubs
testCompile
||<
ちなみに、codehausのgmavenのドキュメントでは"gmaven-runtime-(version)"をdependencyに組み込んでますが、試した所 "An API incompatibility was encountered ..." という例外が発生してしまいました。外してみたところ正常に動作したのでそのままにしてます。(同じく codehaus のドキュメントで紹介されている gmaven-archetype-basic の archetype のpom.xmlではgmaven-runtimeなんて影も形も無いので、よくわかりません・・・。)
groovyソースは、デフォルトでは以下のディレクトリに配置します。(もちろん設定で変更可能です)
src/main/groovy/**/*.groovy
src/test/groovy/**/*.groovy
** JavaからGroovyを、GroovyからJavaのクラスをテストさせてみる
テスト対象自体は、コンストラクタでintを2つとりインスタンスメンバにセット、calc()で加算したのを返すだけのものです。
| Groovyで実装 | src/main/groovy/gjt1/Calc1.groovy |
| Javaで実装 | src/main/java/gjt1/Calc2.java |
テストコードでは、Javaからも、Groovyからも、両方から Calc1/Calc2 それぞれテストさせてます。
| GroovyのTestNGテストケース | src/test/groovy/gjt1/Calc1Test.groovy |
| JavaのTestNGテストケース | src/test/java/gjt1/Calc2Test.java |
自明のことですが、テストはパスします。
#pre||>
$ mvn clean test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running TestSuite
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.699 sec
Results :
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
||<
* 本番:GroovyのテストコードからJavaのprivateフィールドを更新してみる。
先ほどの練習でGroovyとJavaのテストコードの連携を確認できましたので、いよいよ、GroovyのテストコードからJavaのprivateフィールドを更新してみます。
サンプルコード(gjt2)は以下のgistにUPしています。
https://gist.github.com/4054100
サンプルコード(gjt2)のディレクトリ構成です:
#pre||>
gjt2/
pom.xml
src/main/java/gjt2/Calc.java
src/test/groovy/gjt2/CalcTest.groovy
||<
pom.xmlは練習のgjt1のものと同じです。
テスト対象となるJavaのCalcクラスも、練習の時のものと一緒でパッケージ名とクラス名を変えただけです。
Groovyで書いたTestNGのテストコードを見てみます。calc()の中で、2つめのassertのところでJavaのCalcクラスのprivateフィールドの更新を試みています。
#pre||>
...
@Test
public void calc() {
Calc c = new Calc(10, 20);
Assert.assertEquals(c.calc(), 30);
// ここでJavaのCalcクラスのprivateフィールドを更新している。
c.v1 = 1;
c.v2 = 2;
// privateフィールドへの更新が反映されていることを確認
Assert.assertEquals(c.calc(), 3);
}
||<
単体テストを実行してみます。
#pre||>
$ mvn test
...
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running TestSuite
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.828 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
||<
正常にテストが成功しました。
* まとめと参考資料
今回はごく簡単なテストケースを通じてprivateフィールドをGroovyからの更新を紹介しましたが、応用すれば、従来では不可能か非常に難易度が高いと考えられていた、Singletonが関連するような箇所のtestコードも柔軟かつ容易に構築できそうです。Groovyではこの他にもメタプログラミングを容易にしてくれる機能が揃っていますので、JavaのレガシーコードをGroovyでテストする道筋が見えてきます。
以下、参考資料です。
MavenでGroovyを使う資料:
- MavenプロジェクトでGroovyを使う - 壷ラボ
-- http://d.hatena.ne.jp/hakurai+java/20110605/1307288851
- Home - GMaven - Codehaus
--- http://docs.codehaus.org/display/GMAVEN/Home
- Practically Groovy: Unit test your Java code faster with Groovy
-- http://www.ibm.com/developerworks/java/library/j-pg11094/
--- このDeveloperWorkの記事は、Groovy 1.0だったりあまりにもバージョンが古いため、ちょっと参考にならないかも。
GroovyでTestNGのテストケースを書く資料:
- Groovy - Using TestNG with Groovy
-- http://groovy.codehaus.org/Using+TestNG+with+Groovy
- groovyでTestNGのテストコードを書いてみよう - exception think
-- http://d.hatena.ne.jp/kimukou_26/20111225/1324749744
- groovy - user - Groovy and TestNG
-- http://groovy.329449.n5.nabble.com/Groovy-and-TestNG-td3329270.html
- Using the TestNG DataProvider with Groovy | The Kaptain on ... stuff
-- http://www.kellyrob99.com/blog/2009/08/09/using-the-testng-dataprovider-with-groovy/
#navi_footer|Groovy|