mike-neckのブログ

Java or Groovy or Swift or Golang

インテグレーションテストを実行するためのbuild.gradleの記述法

こんにちわ、みけです。

某社で一日中ドラクエやってて、

何の成果もあげていません。



あ、いや、そんなことはどうでもいいです。

いや、よくないか。


インテグレーションテストとは…

とりあえず、ここでは、乱暴な言い方ですが、

ソフトウェアの機能に対して期待している動作を

検証するテストということにしておきましょう。

(一つのオブジェクトレベルでの動作ではないことに注意)


ここで、「とりあえず」「ここでは」としたわけですが、

実際のプロジェクトにおいては、

このフェーズのテストは何を保証するべきである

というのは、それぞれのプロジェクトで

議論して決めるべきだと思っています。


インテグレーションテストを実行するにあたって、求められるプロジェクト構造

ここでいうプロジェクト構造とは、

プロジェクトマネージャーは◯◯課長で…

とかいう話ではありません。

書いたコードをどのディレクトリーに配置するかという話です。


求められる構造は次のとおりです。

  • 同じプロジェクトにある
  • プロダクションコードとは別の場所にある
  • ユニットテストとは別の場所にある


というわけで、まあ、project-root/srcの下に

maintestとは別のディレクトリーを作成するのがよいでしょう。

すると、プロジェクトの構造は次のようになります。

project-root
└─src
  ├─integTest
  │ └─java
  │   └─…(以下略)…
  ├─main
  │ ├─java
  │ │ └─…(以下略)…
  │ └─resources
  │   └─…(以下略)…
  └─test
    └─java
      └─…(以下略)…
project-root/src/integTest/java

インテグレーションテストを配置するディレクトリー

project-root/src/main/java

プロダクションコードを配置するディレクトリー

project-root/src/main/resources

プロダクション用のリソースを配置するディレクトリー

project-root/src/test/java

ユニットテストを配置するディレクトリー


インテグレーションテストの設定

多分、今回の話のメインはここです。

ポイントとしては以下のとおりです。

  • インテグレーションテスト用のconfigurationsを追加する
  • インテグレーションテスト用の依存ライブラリーを指定する
  • インテグレーションテストタスクを設定する


インテグレーションテスト用のconfigurationsを追加する

configurationsを追加するだけなら、次のように書けます。

configurations {
    additionalConfiguration
}

ただ、ここではテスト用のconfigurationsの追加なので、

sourceSetsへの追加が必要となってきます。

したがって、configurationsに記述するのではなくて、

次のようにsourceSetsに記述します。

sourceSets {
    integTest {
        java.srcDir file('src/integTest/java')
        resources.srcDir file('src/integTest/resources')
    }
}


インテグレーションテスト用の依存ライブラリーを指定する

先ほどのsourceSetsへの追加によって、

自動でconfigurationsintegTestというconfigurationが追加されます。

そこに必要な依存性を記述していきます。


また、integTestがプロダクションコードへ依存する場合、

プロダクションコードに依存するということを記述しておかないとなりません。

repositories {
    mavenCentral ()
}
dependencies {
    integTestCompile 'junit:junit:4.11'
    integTestCompile sourceSets.main.output
}

Spockを使いたい場合などは、別途Spockやgroovy-allなども

追加しておいたほうがよいでしょう。


インテグレーションテストタスクを設定する

Testタイプのタスクを追加します。

task integTest(type : Test) {
    testClassesDir = sourceSets.integTest.output.classesDir
    classPath = sourceSets.integTest.runtimeClasspath
}


ここまでまとめ

以上の結果をまとめたbuild.gradleの記述は次のようになります。

apply plugin : 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8

sourceSets {
    integTest {
        java.srcDir file('src/integTest/java')
        resources.srcDir file('src/integTest/resources')
    }
}

repositories {
    mavenCentral ()
}
dependencies {
    compile 'org.slf4j:slf4j-api:1.6.6'
    compile 'ch.qos.logback:logback-core:1.0.7'
    compile 'ch.qos.logback:logback-classic:1.0.7'

    testCompile 'junit:junit:4.11'

    integTest 'junit:junit:4.11'
    integTest sourceSets.main.output
}

task integTest(type : Test) {
    testClassesDir = sourceSets.integTest.output.classesDir
    classPath = sourceSets.integTest.runtimeClasspath
}


インテグレーションテストの実行

後はテストを書いて実行するだけです。

インテグレーションテストはintegTestタスクで行います。

$ gradle integTest
:compileJava
:processResources
:classes
:compileIntegTestJava
:processIntegTestResources
:integTestClasses
:integTest

BUILD SUCCESSFUL

Total time: 12.305 secs

だいたいこのように表示されると思います。


なお、もしもユニットテストで使っている超便利クラスなどがあって、

インテグレーションテストでもそれを利用したい場合は、

インテグレーションテストからユニットテストの成果物への参照も

できる用に設定しておく必要があります。

この場合は依存性解決部分に次のような記述を追加するとよいでしょう。

dependencies {
    integTest sourceSets.test.output
}

これによって、ユニットテストコンパイルを実行した後に、

インテグレーションテストのコンパイルが実行されます。

もし、IDEなどで自動的に参照してしまってた場合は、

参考にしてみてください。

以上