home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Groovy/Maven/Java + TestNG Example

Groovy/Maven/Java + TestNG Example

Groovy / Maven / Java + TestNG Example
id: 1122 所有者: msakamoto-sf    作成日: 2012-11-11 17:09:40
カテゴリ: Groovy Java Maven TestNG 

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ビルドの例を Groovy/Maven/Examples (includes "Java Joint Compile") にまとめていますので、Maven設定の細かい調整はそちらを参照してください。

※2013-07-15追記:Maven3にて、JUnit(Java, Groovy) + TestNG(Java, Groovy) + Spock(Groovy)の5種類のテストケースを一気に実行するサンプルを用意しましたので、手っ取り早くコピペしたい場合はそちらを参照してみてください: Java/Maven3/JUnit, Spock, TestNGを同時実行する

練習:JavaのコードをGroovyのTestNGでMavenに組み込む

まずは練習として、JavaのコードをGroovyで記述したTestNGのテストケースでテストするごく簡単なサンプルをMavenに組み込んでみます。

サンプルソース(gjt1)ツリー:

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に組み込んでいます:

   <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>1.8.8</version>
    </dependency>

続いて、"*.groovy"をコンパイルするよう、gmavenプラグインを組み込んでいます。providerとして1.8を選択しています。

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.4</version>
        <configuration>
          <providerSelection>1.8</providerSelection>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>generateStubs</goal>
              <goal>compile</goal>
              <goal>generateTestStubs</goal>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

ちなみに、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

自明のことですが、テストはパスします。

$ 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)のディレクトリ構成です:

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フィールドの更新を試みています。

...
    @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);
    }

単体テストを実行してみます。

$ 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を使う資料:

GroovyでTestNGのテストケースを書く資料:



プレーンテキスト形式でダウンロード
現在のバージョン : 3
更新者: msakamoto-sf
更新日: 2013-07-15 11:39:26
md5:387cd214fa29a2d42a0f8f834f9cd782
sha1:a9e0d40ec2ba840bce047a9d15298d4f9287a7ec
コメント
コメントを投稿するにはログインして下さい。