GradleでCucumber-JVMを使うためのセットアップ for Kotlin

# 概要
GradleプロジェクトでCucumber-JVMを使うための初期セットアップ方法です。
ここではKotlinを使っていますが、Javaの場合も同様です。

# build.gradle
依存ライブラリに `cucumber-java` `cucumber-junit` `junit` を追加します。

```gradle
dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    testCompile 'io.cucumber:cucumber-java:4.2.2'
    testCompile 'io.cucumber:cucumber-junit:4.2.2'
    testCompile 'junit:junit:4.12'
}
```

おまじないとして以下を追加します。（testタスクを実行した際に、 `Cucumber` のログを標準出力に出すため）

```gradle
test {
    testLogging.showStandardStreams = true
    systemProperties System.getProperties()
}
```

# テストクラス
`Cucumber` を実行するためのテストクラスを作成します。

```kotlin
package example

import cucumber.api.CucumberOptions
import cucumber.api.junit.Cucumber
import org.junit.runner.RunWith

@RunWith(
    Cucumber::class)
@CucumberOptions(plugin = ["pretty"])
class RunCucumberTest {
}
```

# フィーチャファイル
`src/test/resources` 配下に、疎通確認用のフィーチャファイルを作成します。
例えば、 `src/test/resources/example/features/Hello.feature` を以下のように作成します。

```gherkin
Feature: Hello Cucumber

  Scenario: Hello
    Given my name is John
    When I say hello to the application
    Then the application replies "Hello, John"
```

# テスト
ターミナルからテストを実行します。

```bash
$./gradlew test
```

以下のような出力が得られれば初期セットアップOKです。

```
> Task :test

example.RunCucumberTest STANDARD_OUT
    Feature: Hello Cucumber

      Scenario: Hello                              # example/features/Hello.feature:3
        Given my name is John                      # null
        When I say hello to the application        # null
        Then the application replies "Hello, John" # null

    Undefined scenarios:
    example/features/Hello.feature:3 # Hello

    1 Scenarios (1 undefined)
    3 Steps (3 undefined)
    0m0.162s


    You can implement missing steps with the snippets below:

    @Given("my name is John")
    public void my_name_is_John() {
        // Write code here that turns the phrase above into concrete actions
        throw new cucumber.api.PendingException();
    }

    @When("I say hello to the application")
    public void i_say_hello_to_the_application() {
        // Write code here that turns the phrase above into concrete actions
        throw new cucumber.api.PendingException();
    }

    @Then("the application replies {string}")
    public void the_application_replies(String string) {
        // Write code here that turns the phrase above into concrete actions
        throw new cucumber.api.PendingException();
    }

```

# ステップ定義クラスの実装
作成したフィーチャ・シナリオに対するステップ定義クラスを `src/test/kotolin` 配下に作成します。
必要なステップ定義メソッドは、先程の　`test` タスク実行時にスニペットが提示されますが、これはJavaコードなので注意。（IDEAならコピペ時にkotlinコードに変換できます）

```kotlin
package stepdefs

import cucumber.api.java.en.Then
import cucumber.api.java.en.Given
import cucumber.api.java.en.When

class HelloSteps {

    private var name: String? = null
    private var hello: Hello? = null

    @Given("my name is (.+)")
    fun my_name_is_John(name: String) {
        this.name = name
    }

    @When("I say hello to the application")
    fun i_say_hello_to_the_application() {
        hello = Hello(this.name!!)
    }

    @Then("the application replies {string}")
    fun the_application_replies(message: String) {
        assert(hello!!.sayHello() == message)
    }
}

class Hello(val name: String) {
    fun sayHello(): String {
        return "Hello, $name"
    }
}
```

# テストクラスの修正
ステップ定義クラスの場所を `Cucumber` に教えるため、先程の　`RunCucumberTest` クラスのアノテーションに修正を加え、 `grue` 属性にステップ定義クラスが属するパッケージ名を指定します。

```kotlin
@CucumberOptions(plugin = ["pretty"], glue = ["stepdefs"])
class RunCucumberTest {
}
```

# 改めて実行
再度、ターミナルからテストを実行します。

```bash
$./gradlew test
```

すべてのシナリオ、ステップがpassしていれば成功です。

```
> Task :test

kotlinca.RunCucumberTest STANDARD_OUT
    Feature: Hello Cucumber

      Scenario: Hello                              # kotlinca/features/Hello.feature:3
        Given my name is John                      # HelloSteps.my_name_is_John(String)
        When I say hello to the application        # HelloSteps.i_say_hello_to_the_application()
        Then the application replies "Hello, John" # HelloSteps.the_application_replies(String)

    1 Scenarios (1 passed)
    3 Steps (3 passed)
    0m0.157s
```