330 |
331 |
332 |
333 |
334 |
335 |
--------------------------------------------------------------------------------
/example/build.sbt:
--------------------------------------------------------------------------------
1 | name := "cucumber-test"
2 |
3 | organization := "com.waioeka.sbt"
4 |
5 | version := "0.0.6"
6 |
7 | scalaVersion := "2.12.13"
8 |
9 | libraryDependencies ++= Seq (
10 | "io.cucumber" % "cucumber-core" % "6.10.3" % Test,
11 | "io.cucumber" %% "cucumber-scala" % "6.10.3" % Test,
12 | "io.cucumber" % "cucumber-jvm" % "6.10.3" % Test,
13 | "io.cucumber" % "cucumber-junit" % "6.10.3" % Test,
14 | "org.scalatest" %% "scalatest" % "3.2.8" % Test)
15 |
16 | enablePlugins(CucumberPlugin)
17 |
18 |
19 | CucumberPlugin.envProperties := Map("K"->"2049")
20 |
21 | CucumberPlugin.monochrome := false
22 | CucumberPlugin.glues := List("com.waioeka.sbt")
23 |
24 | def before() : Unit = { println("beforeAll") }
25 | def after() : Unit = { println("afterAll") }
26 |
27 | CucumberPlugin.beforeAll := before
28 | CucumberPlugin.afterAll := after
29 |
--------------------------------------------------------------------------------
/example/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.2.8
2 |
--------------------------------------------------------------------------------
/example/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.waioeka.sbt" % "cucumber-plugin" % "0.3.0")
2 |
--------------------------------------------------------------------------------
/example/src/test/resources/Multiplication.feature:
--------------------------------------------------------------------------------
1 | @my-tag
2 | Feature: Multiplication
3 | In order to avoid making mistakes
4 | As a dummy
5 | I want to multiply numbers
6 |
7 | Scenario: Multiply two variables
8 | Given a variable x with value 2
9 | And a variable y with value 3
10 | When I multiply x * y
11 | Then I get 6
12 |
--------------------------------------------------------------------------------
/example/src/test/resources/cucumber.properties:
--------------------------------------------------------------------------------
1 | cucumber.publish.quiet=true
2 |
--------------------------------------------------------------------------------
/example/src/test/scala/com/waioeka/sbt/MultiplicationSteps.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Michael Lewis
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | package com.waioeka.sbt
27 |
28 | import io.cucumber.scala.{EN, ScalaDsl}
29 | import org.scalatest.matchers.should.Matchers
30 |
31 | /**
32 | * AddAndMultiplySteps
33 | *
34 | */
35 | class MultiplicationSteps extends ScalaDsl with EN with Matchers {
36 | var x : Int = 0
37 | var y : Int = 0
38 | var z : Int = 0
39 |
40 |
41 | Given("""^a variable x with value (\d+)$""") { (arg0: Int) =>
42 | x = arg0
43 | }
44 |
45 | Given("""^a variable y with value (\d+)$""") { (arg0: Int) =>
46 | y = arg0
47 | }
48 |
49 | When("""^I multiply x \* y$""") { () =>
50 | z = x * y
51 | }
52 |
53 | Then("""^I get (\d+)$""") { (arg0: Int) =>
54 | z should be (arg0)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.2.8
2 |
--------------------------------------------------------------------------------
/src/main/scala/com/waioeka/sbt/CucumberParameters.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Michael Lewis
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | package com.waioeka.sbt
27 |
28 | import java.io.File
29 |
30 |
31 | /**
32 | * Cucumber Options
33 | *
34 | * This case class defines the Cucumber options.
35 | *
36 | * @param dryRun true, if run should be a dry run.
37 | * @param features the path(s) to the features.
38 | * @param monochrome whether or not to use monochrome output.
39 | * @param plugins what plugin(s) to use.
40 | * @param glues where glue code is loaded from.
41 | * @param tags what tag(s) to use.
42 | * @param additionalArgs additional arguments to pass through to Cucumber.
43 | */
44 | case class CucumberParameters(
45 | dryRun : Boolean,
46 | features : List[String],
47 | monochrome : Boolean,
48 | plugins : List[Plugin],
49 | glues : List[String],
50 | tags : List[String],
51 | additionalArgs: List[String]) {
52 |
53 | /**
54 | * Create a list of one element
55 | *
56 | * @param parameter the boolean parameter.
57 | * @param parameterName the name of the parameter.
58 | * @return a list containing the parameter if true, false otherwise.
59 | */
60 | def boolToParameter(parameter: Boolean, parameterName: String) = parameter match {
61 | case true => List(s"--$parameterName")
62 | case _ => List()
63 | }
64 |
65 | /**
66 | * Return the Cucumber parameters as a list of strings.
67 | *
68 | * @return a list of string parameters.
69 | */
70 | def toList : List[String] = {
71 | boolToParameter(dryRun,"dry-run") :::
72 | boolToParameter(monochrome,"monochrome") :::
73 | glues.flatMap(glue => Seq("--glue", glue)) :::
74 | plugins.map(_.toCucumberPlugin).flatMap(plugin => Seq("--plugin", plugin)) :::
75 | tags.flatMap(tag => Seq("--tags", tag)) :::
76 | additionalArgs :::
77 | features
78 | }
79 |
80 | }
81 |
82 | trait Plugin {
83 | def toCucumberPlugin : String
84 | }
85 |
86 | sealed abstract class FilePlugin(name: String, file: File) extends Plugin {
87 | override def toCucumberPlugin: String = s"$name:${file.getAbsolutePath}"
88 | }
89 |
90 | object Plugin {
91 |
92 | case object PrettyPlugin extends Plugin {
93 | override def toCucumberPlugin: String = "pretty"
94 | }
95 |
96 | case class HtmlPlugin(file: File) extends FilePlugin("html", file)
97 |
98 | case class JsonPlugin(file: File) extends FilePlugin("json", file)
99 |
100 | case class JunitPlugin(file: File) extends FilePlugin("junit", file)
101 |
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/scala/com/waioeka/sbt/CucumberPlugin.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Michael Lewis
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | package com.waioeka.sbt
27 |
28 | import sbt._
29 | import Keys._
30 | import sbt.complete.DefaultParsers._
31 |
32 | import scala.util.Try
33 |
34 | /**
35 | * CucumberPlugin
36 | * This class implements the AutoPlugin interface. The Cucumber plugin
37 | * will invoke Cucumber for Scala.
38 | */
39 | object CucumberPlugin extends AutoPlugin {
40 |
41 | /** TaskKey for the cucumber plugin. */
42 | lazy val cucumber = InputKey[Unit]("cucumber", "[Cucumber] Runs Scala Cucumber.")
43 |
44 | /** The main class of the Cucumber test runner. */
45 | val mainClass = SettingKey[String]("cucumber-main-class")
46 |
47 | /** True, if run should be a dry run. */
48 | val dryRun = SettingKey[Boolean]("cucumber-dry-run")
49 |
50 | /** The path(s) to the features. */
51 | val features = SettingKey[List[String]]("cucumber-features")
52 |
53 | /** Whether or not to use monochrome output. */
54 | val monochrome = SettingKey[Boolean]("cucumber-monochrome")
55 |
56 | /** What plugin(s) to use. */
57 | val plugin = SettingKey[List[Plugin]]("cucumber-plugins")
58 |
59 | /** What tag(s) to use. */
60 | val tags = SettingKey[List[String]]("cucumber-tags")
61 |
62 | val cucumberTestReports = settingKey[File]("The location for test reports")
63 |
64 | /** Any additional properties. */
65 | val envProperties = SettingKey[Map[String, String]]("properties")
66 |
67 | /**
68 | * Where glue code (step definitions, hooks and plugins)
69 | * are loaded from.
70 | */
71 | val glues = SettingKey[List[String]]("cucumber-glues")
72 |
73 | /** A beforeAll hook for Cucumber tests. */
74 | val beforeAll = SettingKey[() => Unit]("cucumber-before")
75 |
76 | /** An afterAll hook for Cucumber tests. */
77 | val afterAll = SettingKey[() => Unit]("cucumber-after")
78 |
79 | /** The Java options */
80 | val javaOptions = taskKey[Seq[String]]("Options passed to a new JVM when forking.")
81 |
82 | /** Classpath to be used by cucumber (defaults to test classpath). */
83 | val classpath = taskKey[Classpath]("Classpath to be used by cucumber.")
84 |
85 | /** Default hook for beforeAll, afterAll. */
86 | private def noOp(): Unit = {}
87 |
88 | /**
89 | * Defines the project settings for this plugin.
90 | *
91 | * @return a Sequence of SBT settings.
92 | */
93 | override def projectSettings: Seq[Setting[_]] = Seq(
94 |
95 | envProperties := Map.empty,
96 |
97 | cucumber := {
98 |
99 | val args: Seq[String] = spaceDelimited("").parsed
100 |
101 | val logger = streams.value.log
102 |
103 | val classPath = (classpath map { cp => cp.toList.map(_.data) }).value
104 |
105 | val cucumberParams = CucumberParameters(
106 | dryRun.value,
107 | features.value,
108 | monochrome.value,
109 | plugin.value,
110 | glues.value,
111 | tags.value,
112 | args.toList
113 | )
114 |
115 | import scala.collection.JavaConverters._
116 | val envParams = System.getenv.asScala.toMap ++ envProperties.value
117 |
118 | beforeAll.value
119 | val result = run(classPath, envParams, mainClass.value, javaOptions.value, cucumberParams, logger)
120 | afterAll.value
121 | if (result != 0) {
122 | throw new IllegalStateException("Cucumber did not succeed and returned error =" + result)
123 | }
124 | },
125 |
126 | mainClass := "io.cucumber.core.cli.Main",
127 | dryRun := false,
128 | features := List("classpath:"),
129 | monochrome := false,
130 | tags := Nil,
131 | cucumberTestReports := new File(new File(target.value, "test-reports"), "cucumber"),
132 | plugin := {
133 | import Plugin._
134 | val cucumberDir = cucumberTestReports.value
135 | IO.createDirectory(cucumberDir)
136 | List(PrettyPlugin,
137 | HtmlPlugin(new File(cucumberDir, "cucumber.html")),
138 | JsonPlugin(new File(cucumberDir, "cucumber.json")),
139 | JunitPlugin(new File(cucumberDir, "junit-report.xml"))
140 | )
141 | },
142 | beforeAll := noOp,
143 | afterAll := noOp,
144 | classpath := (fullClasspath in Test).value
145 | )
146 |
147 | def run(classPath: List[File],
148 | env: Map[String, String],
149 | mainClass: String,
150 | javaOptions: Seq[String],
151 | cucumberParams: CucumberParameters,
152 | logger: Logger): Int =
153 | Try {
154 | Jvm(classPath, env, javaOptions).run(mainClass, cucumberParams.toList, logger)
155 | }.recover {
156 | case t: Throwable =>
157 | println(s"[CucumberPlugin] Caught exception: ${t.getMessage}")
158 | -1
159 | }.get
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/src/main/scala/com/waioeka/sbt/Jvm.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Michael Lewis
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | *
8 | * 1. Redistributions of source code must retain the above copyright notice, this
9 | * list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright notice,
11 | * this list of conditions and the following disclaimer in the documentation
12 | * and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 | */
25 |
26 | package com.waioeka.sbt
27 |
28 | import java.io.File
29 | import java.lang.management.ManagementFactory
30 |
31 | import org.apache.commons.lang3.SystemUtils
32 | import sbt._
33 |
34 | case class Jvm(classPath: List[File], envParams: Map[String, String], javaOptions: Seq[String]) {
35 |
36 | /** Classpath separator, must be ';' for Windows, otherwise : */
37 | private val sep = if (SystemUtils.IS_OS_WINDOWS) ";" else ":"
38 |
39 | /** The Jvm parameters. */
40 | private val jvmArgs: Vector[String]
41 | = Vector("-classpath", classPath map (_.toPath) mkString sep) ++ javaOptions
42 |
43 | /**
44 | * Invoke the main class.
45 | *
46 | * @param mainClass the class name containing the main method.
47 | * @param parameters the parameters to pass to the main method.
48 | * @param logger SBT logger for debugging.
49 | * @return the return code of the Jvm.
50 | */
51 | def run(mainClass: String, parameters: List[String], logger: Logger): Int = {
52 |
53 | val args = jvmArgs :+ mainClass
54 |
55 | logger.debug(s"args ${args mkString " "}, env: $envParams, parameters: ${parameters.mkString(",")}")
56 |
57 | val opts = ForkOptions(
58 | javaHome = None,
59 | outputStrategy = Some(StdoutOutput),
60 | bootJars = Vector.empty,
61 | workingDirectory = None,
62 | runJVMOptions = args,
63 | connectInput = false,
64 | envVars = envParams
65 | )
66 |
67 | Fork.java(opts, parameters)
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------