GeekFactory

int128.hatenablog.com

Gradleで特定の条件を満たした場合にのみテストケースを実行

Gradleで特定の場合にのみテストケースを実行する方法を説明します。例えば、通常のテストケースはH2 Databaseを利用するけど、一部はテスト環境上のMySQLで実行したいといった場合を考えます。

基本的な考え方

JUnitのカテゴリ機能でテストケースをフィルタします。もしくは、パッケージ名でテストケースをフィルタします。

Gradleでは以下の2タスクを作成します。

  1. カテゴリの付いていないテストケースを実行するタスク
  2. カテゴリの付いているテストケースを実行するタスク

開発環境では1だけ実行します。テスト環境では1と2の両者を実行します。

実装例

以下の例はGradleとSpockで書いていますが、JavaJUnitでも同様です。

Spec

ここでは、MySQLが必要なテストケースには RequireDatabase カテゴリを付けることにします。

interface RequireDatabase {
}
import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(RequireDatabase)
class FooSpec extends Specification {
}

build.gradle

環境変数 INTEGRATION_TEST_DB_URL が設定されている場合にのみ RequireDatabase カテゴリのテストを実行することにします。RequireDatabase カテゴリが付いていないテストケースは環境変数の有無に関わらず実行します。

単純にTestタスクを追加しただけではテストレポートが上書きされてしまうため、テストレポートを生成するタスクを新設します。

dependencies {
    testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
}

test {
    useJUnit {
        excludeCategories 'com.example.test.RequireDatabase'
    }
}

task testWithDatabase(type: Test) {
    useJUnit {
        includeCategories 'com.example.test.RequireDatabase'
    }
    onlyIf { System.getenv('INTEGRATION_TEST_DB_URL') }
}

task testReport(type: TestReport) {
    destinationDir = testReportDir
    reportOn tasks.withType(Test)*.binResultsDir
}

tasks.withType(Test) {
    reports.html.enabled = false
    finalizedBy testReport
}

check.dependsOn tasks.withType(Test)

なお、テストが失敗しても確実にtestReportタスクが実行されるようにするため finalizedBy を利用しています。将来のGradleでは修正されるかもしれません。

Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築

Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築