Groovy, Spockを使ってJavaのテストを作成する

Gradleをインストールする

公式のインストールガイドを読むと、Chocolateyでインストールできるようなのでこちらでインストールした。 gradle.org

choco install gradle

プロジェクト作成

プロジェクト用のディレクトリを作成してその中で以下のコマンドを実行し、プロジェクトの雛形を作成する。

gradle init --type java-application
  • build.gradleファイルにSpockを追加する。
  • plugins, dependenciesにGroovyを追加する。
plugins {
    id 'java'
    id 'groovy'
}

dependencies {
    compile "org.codehaus.groovy:groovy-all:2.4.15"
    testCompile "org.spockframework:spock-core:1.1-groovy-2.4"
}

テスト対象のクラスを追加

Integerのコレクションを受け取り、合計値を返却する関数を作成した。中身は未実装なのでとりあえず0を返却する。

package app;

import java.util.Collection;

public class Calculator {
    public int sum(Collection<Integer> list) {
        return 0;
    }
}

Specificationを追加

import app.Calculator
import spock.lang.*

class CalculatorSpec extends Specification {
  def "リストの各要素を合計した値を返すこと"() {
    given:
      def calculator = new Calculator()
    when:
      def actual = calculator.sum(list)
    then:
      actual == expected
    where:
      list                   | expected
      Arrays.asList(1)       | 1
      Arrays.asList(1, 2, 3) | 6
  }
}

テストを実行

以下のコマンドでテストを実行する。

gradlew test

未実装なので当然テストが失敗する。

CalculatorSpec > リストの各要素を合計した値を返すこと FAILED
    org.spockframework.runtime.SpockComparisonFailure at CalculatorSpec.groovy:11
Condition not satisfied:

ret == expected
|   |  |
0   |  1
    false

Condition not satisfied:

ret == expected
|   |  |
0   |  1
    false

    at CalculatorSpec.リストの各要素を合計した値を返すこと(CalculatorSpec.groovy:11)

テストが通るように実装

public class Calculator {
    public int sum(Collection<Integer> list) {
        return list.stream()
                .reduce((x, y) -> x + y)
                .orElse(0);
    }
}

テストが通るようになった。

gradlew test
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 up-to-date

例外のテスト

素数が0のリストは受け付けないようにしたい。まずは要素数0の場合のテストを追加する。

  def "リストが空の場合はエラー"() {
    given:
      def calculator = new Calculator()
    when:
      calculator.sum(Arrays.asList())
    then:
      thrown(IllegalArgumentException)
  }

テストが失敗することを確認

Expected exception of type 'java.lang.IllegalArgumentException', but no exception was thrown
Expected exception of type 'java.lang.IllegalArgumentException', but no exception was thrown
    at org.spockframework.lang.SpecInternals.checkExceptionThrown(SpecInternals.java:85)
    at org.spockframework.lang.SpecInternals.thrownImpl(SpecInternals.java:72)
    at CalculatorSpec.リストが空の場合はエラー(CalculatorSpec.groovy:24)

    org.spockframework.runtime.WrongExceptionThrownError at CalculatorSpec.groovy:24
2 tests completed, 1 failed
:test FAILED

リストの要素が空の場合に例外を投げるように実装を修正

public int sum(Collection<Integer> list) {
    return list.stream()
            .reduce((x, y) -> x + y)
            .orElseThrow(() -> new IllegalArgumentException("list is empty"));
}

再度テストを実行して成功することを確認

BUILD SUCCESSFUL in 3s
3 actionable tasks: 3 executed

テストレポート

テストを実行する度にHTMLのテストレポートが生成される。
生成場所は{プロジェクトディレクトリ}/build/reports/tests/test/index.html

f:id:hkou:20180415111557p:plain