Cucumber と Scala でテストを書いてみた

Cucumber を使ってみたい衝動に駆られて sbt で Cucumber のテストを実行するのを試してみた.

環境

Scala 2.10 だと違うところとかあるみたい. なので Cucumber-JVM, xsbt-cucumber-plugin の github とかをみて適宜修正する必要がある.

xsbt-cucumber-plugin の使い方

xsbt-cucumber-plugin を使ってテスト実行するのは,

% sbt cucumber

と実行する.

構成

関係するファイルのディレクトリ構成は以下:

$(SBT_ROOT)/
  build.sbt
  project/
    build.properties
    build.sbt
  src/
    test/
      resources/
        Addition.feature  <- Cucumber のテスト
      scala/
        Addition.scala    <- Addition.feature の実装
    main/
      scala/
        Calculator.scala  <- Production コード

それぞれのファイルはこんな感じになった.

$(SBT_ROOT)/build.sbt:

name := "project-name"

version := "1.0"

scalaVersion := "2.9.2"

libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1" % "test"

seq(cucumberSettings : _*)

$(SBT_ROOT)/project/build.sbt:

resolvers += "Templemore Repository" at "http://templemore.co.uk/repo"

addSbtPlugin("templemore" % "sbt-cucumber-plugin" % "0.7.2")

$(SBT_ROOT)/project/build.properties:

sbt.version=0.12.0

$(SBT_ROOT)/src/test/resources/Addtion.feature:

Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 50 into the calculator
    And I have entered 70 into the calculator
    When I press add
    Then the result should be 120 on the screen

$(SBT_ROOT)/src/test/scala/Addition.scala:

import cucumber.runtime.{ScalaDsl, EN}
import org.scalatest._
import org.scalatest.matchers.ShouldMatchers
import scala.collection.mutable.MutableList

class Addition extends ScalaDsl with EN with ShouldMatchers {
  val numbers = MutableList.empty[Int]
  var result = 0

  Given ("""^I have entered (\d+) into the calculator$""") { (arg0: Int) =>
    numbers += arg0
  }

  When ("""^I press add$""") { () =>
    result = Calculator.add(numbers(0))(numbers(1))
  }

  Then("""^the result should be (\d+) on the screen$""") { (arg0: Int) =>
    assert(result === arg0)
  }
}

$(SBT_ROOT)/src/main/scala/Calculator.scala:

object Calculator {

  def add(a: Int)(b: Int) = a + b

}

スニペット

Addition.feature だけがある状態でテストを実行すると,スニペットが得られる.

% sbt
> cucumber
[info] Running cucumber…
[info] Feature: Addition
[info] In order to avoid silly mistakes
[info] As a math idiot
[info] I want to be told the sum of two numbers
[info] 
[info] Scenario: Add two numbers # Addition.feature:6
[info] Given I have entered 50 into the calculator
[info] And I have entered 70 into the calculator
[info] When I press add
[info] Then the result should be 120 on the screen
[info] 
[info] 
[info] You can implement missing steps with the snippets below:
[info] 
[info] Given("""^I have entered (\d+) into the calculator$"""){ (arg0:Int) =>
[info] //// Express the Regexp above with the code you wish you had
[info] throw new PendingException()
[info] }
[info] When("""^I press add$"""){ () =>
[info] //// Express the Regexp above with the code you wish you had
[info] throw new PendingException()
[info] }
[info] Then("""^the result should be (\d+) on the screen$"""){ (arg0:Int) =>
[info] //// Express the Regexp above with the code you wish you had
[info] throw new PendingException()
[info] }
[success] Total time: 1 s, completed 2013/02/02 12:34:26

その他

今回は Basic Configuration しかやらなかったけど sbt test で実行できるようにとか sbt cucumber 以外で実行する方法とかもある.

感想

Scala で書くのは辛いという印象をもった. Cucumber で各部分は手続き的な内容になりがちだと思うので別な言語で書いた方がいいのかも知れない.