Skip to content

Commit dc389d2

Browse files
committed
Finaliased the new cucumber framework:
- added support for specifying tags and names as part of the test-only task - added publishing settings to the build - cross builds to Scala 2.10.0-RCx - testes with a Scala 2.10 project
1 parent 42d0f01 commit dc389d2

File tree

9 files changed

+36
-31
lines changed

9 files changed

+36
-31
lines changed

README.markdown

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,12 @@ An [sbt 0.12.x](https://github.com/harrah/xsbt/wiki) plugin for running [Cucumbe
66
### IMPORTANT NOTES ABOUT THIS RELEASE (0.7.0) ###
77
It adds the ability to run cucumber as a standalone SBT task but also as a test runner within the standard 'test' task. To facilitate this, there has been one significant change that you should be aware of: the default location for feature files has changed from the src/test/features directory to the classpath. This is required as running as a test framework only has access to the test classpath. Features should therefore now live under src/test/resources. It is possible to change this back to another location by overriding the cucumberFeaturesLocation setting, but if you change this to anything other than the classpath then the 'test' task will not be able to find features.
88

9-
### EXPERIMENTAL RELEASE ###
10-
This is currently an experimental release of the ability to run cucumber as a standard SBT test framework. The basic mechanisms are in place, but currently the following are broken / do not work:
11-
12-
* Currently MAY not work with Scala 2.10.0-RC1 (I've only been testing against 2.9.2 projects and need to cross-build the integration project to allow it to work)
13-
* There is currently no support for 'test-only' and no way to just run features with specific names or tags
14-
* When running in a multi-project setup, the cucumbers for each project are run in parallel and the output is interleaved and thus unreadable.
15-
16-
This version is not published to any repository. You can build it locally using the SBT tasks: package and publish-local.
17-
189
## Overview ##
1910
Provides the ability to run Cucumber-jvm within the SBT environment. Originally based on the [cuke4duke-sbt-plugin](https://github.com/rubbish/cuke4duke-sbt-plugin) by rubbish and my original implementation for SBT 0.7.x. Specifics for this release:
2011

2112
* Works with xsbt 0.12.0
22-
* Works with cucumber-jvm (version 1.0.9 for Scala 2.9.x and version 1.1.1 for Scala 2.10.0-RC1)
23-
* Allows projects compiled and running against Scala 2.9.1, 2.9.2 and 2.10.0-RC1
13+
* Works with cucumber-jvm (version 1.0.9 for Scala 2.9.x and version 1.1.1 for Scala 2.10.0-RC1/RC2)
14+
* Allows projects compiled and running against Scala 2.9.1, 2.9.2 and 2.10.0-RC1/RC2
2415

2516
## Usage - Standalone Task ##
2617
Install the plugin (see later). By default features files go in the 'src/test/resources' directory. Step definitions go in 'src/test/scala'. Finally from the sbt console call the task:
@@ -53,7 +44,10 @@ This is required to trigger cucumber to run (as SBT only runs tests that extends
5344

5445
Note that none of the configuration options apply when running via a test framework. This is because the SBT test integration does not allow any access to these settings. Cucumber will be executed with pretty output to the console, searching the classpath from its root for features and executing all tests found in packages.
5546

56-
TODO: Support for test-only that runs cucumber just once but supporting tag and name arguments.
47+
It is also possible to filter exactly which features get executed by using the test-only task. To do this, specify the CucumberSuite that you defined above as the test to run and then use either the tag or name approach already described as the test arguments:
48+
49+
test-only mypackage.CucumberSuite -- @demo
50+
test-only mypackage.CucumberSuite -- "User admin"
5751

5852
## Writing Features ##
5953
Features are written in text format and are placed in .feature files inside the 'src/test/resources' directory. For more info on writing features please see the [Cucumber](http://cukes.info) website.
@@ -139,6 +133,8 @@ To add the cucumber plugin settings to a full configuration (often a multi-modul
139133

140134
The testProjects/multiModuleTestProject in the plugin source repository shows this setup in a multi-module project.
141135

136+
Note that because SBT runs builds for different projects in parallel it will often try to run cucumber/test goals for multiple modules at once. This results in interleaving of the output written to the console. For multi-module builds using the cucumber task it is best to change the output settings to generate reports rather than console output. Unfortunately this is not possible when using the test task, so the recommended approach is to run the test task against each project module individually.
137+
142138
#### Running as a test framework ####
143139
If you wish to support cucumber running as a test framework (via the test task) then the following settings should be placed in the build file instead:
144140

integration/src/main/scala/templemore/sbt/cucumber/CucumberFramework.scala

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ class CucumberRunner(testClassLoader: ClassLoader, loggers: Array[Logger]) exten
2424
private val cucumber = new CucumberLauncher(debug = logDebug, error = logError)
2525

2626
def run(testClassName: String, fingerprint: Fingerprint, eventHandler: EventHandler, args: Array[String]) = try {
27-
val arguments = Array("--glue", "", "--format", "pretty", "classpath:")
28-
27+
val arguments = Array("--glue", "", "--format", "pretty") ++ processArgs(args) ++ Array("classpath:")
2928
cucumber(arguments, testClassLoader) match {
3029
case 0 =>
3130
logDebug("Cucumber tests completed successfully")
@@ -35,7 +34,17 @@ class CucumberRunner(testClassLoader: ClassLoader, loggers: Array[Logger]) exten
3534
eventHandler.handle(FailureEvent(testClassName))
3635
}
3736
} catch {
38-
case e => eventHandler.handle(ErrorEvent(testClassName, e))
37+
case e: Exception => eventHandler.handle(ErrorEvent(testClassName, e))
38+
}
39+
40+
private def processArgs(args: Array[String]): Array[String] = {
41+
def isATag(arg: String) = arg.startsWith("@") || arg.startsWith("~")
42+
def isNotATag(arg: String) = !isATag(arg)
43+
def makeOptionsList(options: Array[String], flag: String) = options flatMap(List(flag, _))
44+
45+
val tagsFromArgs = args.filter(isATag)
46+
val namesFromArgs = args.filter(isNotATag)
47+
makeOptionsList(tagsFromArgs, "--tags") ++ makeOptionsList(namesFromArgs, "--name")
3948
}
4049

4150
private def logError(message: String) = loggers foreach (_ error message)

integration/src/main/scala/templemore/sbt/cucumber/CucumberLauncher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class CucumberLauncher(debug: (String) => Unit, error: (String) => Unit) {
7070
CucumberRuntime(runtime, options, loader,
7171
options.formatter(classLoader), options.reporter(classLoader), new SummaryPrinter(System.out))
7272
} catch {
73-
case e =>
73+
case e: Exception =>
7474
error("Unable to construct cucumber runtime. Please report this as an error. (Details: " + e.getMessage + ")")
7575
throw e
7676
}

project/Build.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ object Settings {
1010
Seq (organization := buildOrganization,
1111
scalaVersion := buildScalaVersion,
1212
version := buildVersion,
13-
scalacOptions += "-deprecation")
13+
scalacOptions += "-deprecation",
14+
publishTo := Some(Resolver.file("file", new File("deploy-repo"))))
1415
}
1516

1617
object Dependencies {
@@ -32,15 +33,16 @@ object Build extends Build {
3233
import Settings._
3334

3435
lazy val parentProject = Project("sbt-cucumber-parent", file ("."),
35-
settings = buildSettings) aggregate (pluginProject, integrationProject)
36+
settings = buildSettings ++
37+
Seq(crossScalaVersions := Seq("2.9.2", "2.10.0-RC2"))) aggregate (pluginProject, integrationProject)
3638

3739
lazy val pluginProject = Project("sbt-cucumber-plugin", file ("plugin"),
3840
settings = buildSettings ++
3941
Seq(sbtPlugin := true))
4042

4143
lazy val integrationProject = Project ("sbt-cucumber-integration", file ("integration"),
4244
settings = buildSettings ++
43-
Seq(crossScalaVersions := Seq("2.9.2", "2.10.0-RC1", "2.10.0-RC2"),
45+
Seq(crossScalaVersions := Seq("2.9.2", "2.10.0-RC2"),
4446
libraryDependencies <+= scalaVersion { sv => cucumberScala(sv) },
4547
libraryDependencies += testInterface))
4648
}

testProjects/multiModuleTestProject/project/Build.scala

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,6 @@ object BuildSettings {
2222
object Dependencies {
2323

2424
val scalaTest = "org.scalatest" %% "scalatest" % "1.7.2" % "test"
25-
26-
// NOTE: This dependency is only required when using 'test' task integration
27-
val testIntegration = "templemore" %% "sbt-cucumber-integration" % "0.7.0" % "test"
28-
29-
val testDeps = Seq(scalaTest, testIntegration)
3025
}
3126

3227
object TestProjectBuild extends Build {
@@ -38,8 +33,8 @@ object TestProjectBuild extends Build {
3833

3934

4035
lazy val jarProject = Project ("jar-project", file ("jar-project"),
41-
settings = buildSettings ++ cucumberSettings ++ Seq (libraryDependencies ++= testDeps))
36+
settings = buildSettings ++ cucumberSettings ++ Seq (libraryDependencies += scalaTest))
4237

4338
lazy val warProject = Project ("war-project", file ("war-project"),
44-
settings = buildSettings ++ cucumberSettings ++ Seq (libraryDependencies ++= testDeps)) dependsOn (jarProject)
39+
settings = buildSettings ++ cucumberSettings ++ Seq (libraryDependencies += scalaTest)) dependsOn (jarProject)
4540
}

testProjects/testProject2_10/build.sbt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
name := "test-project"
1+
name := "test-project2_10"
22

33
version := "0.7.0"
44

55
organization := "templemore"
66

7-
scalaVersion := "2.10.0-RC1"
7+
scalaVersion := "2.10.0-RC2"
88

99
libraryDependencies ++= Seq(
10-
"org.scalatest" % "scalatest_2.10.0-RC1" % "1.8-2.10.0-RC1-B1" % "test"
10+
"org.scalatest" % "scalatest_2.10.0-RC2" % "1.8" % "test"
1111
)
1212

13-
seq(cucumberSettings : _*)
13+
seq(cucumberSettingsWithTestPhaseIntegration : _*)
1414

1515
cucumberStepsBasePackage := "test"
1616

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
resolvers += Resolver.file("Local Repo", file((Path.userHome / ".m2" / "repository").toString))
1+
resolvers += "Templemore Repository" at "http://templemore.co.uk/repo"
22

33
addSbtPlugin("templemore" % "sbt-cucumber-plugin" % "0.7.0")

testProjects/testProject2_10/src/test/scala/test/CucumberJarStepDefinitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package test
22

33
import cucumber.api.scala.{ScalaDsl, EN}
44
import org.scalatest.matchers.ShouldMatchers
5+
import templemore.sbt.cucumber.RunCucumber
56

67
class CucumberJarStepDefinitions extends ScalaDsl with EN with ShouldMatchers {
78

@@ -21,3 +22,5 @@ class CucumberJarStepDefinitions extends ScalaDsl with EN with ShouldMatchers {
2122
whenCalled should be (true)
2223
}
2324
}
25+
26+
class CucumberSuite extends RunCucumber

0 commit comments

Comments
 (0)