Sam Starling
9 August 2013

Cucumber and the Scala Play Framework

At work, I’ve recently embarked upon a new project which we’re building using the Scala version of the Play Framework. We’re also using Cucumber for behaviour-driven development. It took me a small amount of fiddling to get set up, so I thought it’d be worth documenting it in case anyone else found it helpful.

Note: I wrote this tutorial against Play 2.1.2 and the versions of the plugins and libraries listed below. Your mileage may vary with other versions. It’s also specific to the Scala version of Play.

Dependencies

The play command is essentially sbt, so by installing the Cucumber plugin for sbt, you’ll be able to run play cucumber.

To do so, add the following lines to project/plugins.sbt:

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

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

Next, you’ll need to add some settings to project/Build.scala:

val main = play.Project(appName, appVersion, appDependencies)
  .settings(CucumberPlugin.cucumberSettings: _*)
  .settings(
    CucumberPlugin.cucumberFeaturesLocation := "cucumber",
    CucumberPlugin.cucumberStepsBasePackage := "cucumber.steps"
  )

All these changes will be picked up when you restart Play.

File Locations

The settings we gave above tell Cucumber where to look for feature files and step definitions. Feature files go in a folder at the root of your project called cucumber, whereas step definitions go in a steps folder inside the test directory, with a package of cucumber.steps. Feel free to change either of these two things – they’re just personal preference.

Step Definitions

Next: the actual testing. We need to spin up our Play app, navigate to a particular page, and make assertions over that page. The IntegrationSpec that comes with the initial app that Play generates helped me here.

I ended up writing this small helper object to run our Play app and point a headless browser at it:

object Driver {
  private val port = 3333
  private val testServer = TestServer(port)
  val browser = TestBrowser.of(HTMLUNIT)
  testServer.start

  def visit(path: String) = {
    browser.goTo("http://localhost:" + port + path)
  }
}

Then I used that in my step definitions:

package cucumber.steps

import cucumber.api.scala.{EN, ScalaDsl}
import org.scalatest.matchers.MustMatchers
import steps.helpers.Driver

class HomepageSteps extends ScalaDsl with EN with MustMatchers {
  When("""^I visit the homepage$"""){ () =>
    Driver.visit("/")
  }

  Then("""^I should be welcomes$"""){ () =>
    Driver.browser.pageSource must include("Welcome!")
  }
}

Bonus points: I’m using ScalaTest’s MustMatchers here to provide slightly nicer ways to perform test assertions. That’s a separate dependency you’ll need to add to Build.scala.

Running the Tests

That’s pretty much it – you can then run play cucumber, and it should scan your folder for features and run those.

This is a bit of a rough and ready guide, but hopefully it’ll help you work out some of the things I bashed my head against recently. If anything is incorrect, or you’ve got any improvements to suggest, then just leave a comment. Thanks!