Skip to content
This repository was archived by the owner on Apr 29, 2024. It is now read-only.

Commit 0fdfa13

Browse files
authored
Merge pull request #97 from aaronp/cucumber
Partial fix for issue #44 — added cucumber support
2 parents 74b6876 + b58ec47 commit 0fdfa13

19 files changed

+482
-79
lines changed

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ plugin will attempt to locate it in one of three places with the precedence orde
7474
testCasesJar := // The path to the Jar file containing the tests to execute. This defaults to the Jar file with the tests from the current sbt project.
7575
testCasesPackageTask := // The sbt Task to package the test cases used when running 'dockerComposeTest'. This defaults to the 'packageBin' task in the 'Test' Scope.
7676
testPassUseSpecs2 := // True if Specs2 is to be used to execute the test pass. This defaults to False and ScalaTest is used.
77+
testPassUseCucumber := // True if cucumber is to be used to execute the test pass. This defaults to False and ScalaTest is used.
7778
variablesForSubstitution := // A Map[String,String] of variables to substitute in your docker-compose file. These are substituted substituted by the plugin and not using environment variables.
7879
variablesForSubstitutionTask := // An sbt task that returns a Map[String,String] of variables to substitute in your docker-compose file. These are substituted by the plugin and not using environment variables.
7980
```
@@ -368,9 +369,17 @@ by setting the following property in build.sbt:
368369
Additionally, you can override the default Specs2 file runner properties as follows:
369370
370371
```
371-
testExecutionExtraConfigTask := Map("filesrunner.verbose" -> s"true")
372+
testExecutionExtraConfigTask := Map("filesrunner.verbose" -> "true")
372373
```
373374
375+
8) [**basic-with-tests-cucumber**](examples/basic-with-tests-cucumber): This project shows how to execute cucumber based test cases
376+
by setting the following property in build.sbt:
377+
378+
```
379+
testPassUseCucumber := true
380+
```
381+
382+
374383
Currently Unsupported Docker Compose Fields
375384
-------------------------------------------
376385
1) "build:" - All docker compose services need to specify an "image:" field.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name := "basic-cucumber"
2+
3+
version := "1.0.0"
4+
5+
scalaVersion := "2.11.11"
6+
7+
enablePlugins(DockerPlugin, DockerComposePlugin, CucumberPlugin)
8+
9+
libraryDependencies ++= {
10+
val cucumber = List("core", "jvm", "junit").map(suffix =>
11+
"info.cukes" % s"cucumber-$suffix" % "1.2.5" % "test") :+ ("info.cukes" %% "cucumber-scala" % "1.2.5" % "test")
12+
13+
cucumber ::: List(
14+
"org.scalactic" %% "scalactic" % "3.0.4" % "test",
15+
"org.scalatest" %% "scalatest" % "3.0.4" % ("test->*"),
16+
"org.pegdown" % "pegdown" % "1.6.0" % ("test->*"),
17+
"junit" % "junit" % "4.12" % "test"
18+
)
19+
}
20+
21+
CucumberPlugin.glue := "classpath:"
22+
CucumberPlugin.features += "classpath:"
23+
24+
//Set the image creation Task to be the one used by sbt-docker
25+
dockerImageCreationTask := docker.value
26+
27+
testPassUseCucumber := true
28+
29+
imageNames in docker := Seq(ImageName(
30+
repository = name.value.toLowerCase,
31+
tag = Some(version.value))
32+
)
33+
34+
// create a docker file with a file /inputs/example.input
35+
dockerfile in docker := {
36+
37+
val classpath: Classpath = (fullClasspath in Test).value
38+
sLog.value.debug(s"Classpath is ${classpath.files.mkString("\n")}\n")
39+
40+
new Dockerfile {
41+
val dockerAppPath = "/app/"
42+
from("java")
43+
add(classpath.files, dockerAppPath)
44+
45+
entryPoint("java", "-cp", s"$dockerAppPath:$dockerAppPath*", "example.CalculatorServer")
46+
}
47+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: '3'
2+
services:
3+
basic-cucumber:
4+
image: basic-cucumber:1.0.0
5+
ports:
6+
- 8080:8080
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version=0.13.16
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
addSbtPlugin("se.marcuslonnberg" % "sbt-docker" % "1.4.1")
2+
addSbtPlugin("com.tapad" % "sbt-docker-compose" % "1.0.29-SNAPSHOT")
3+
addSbtPlugin("com.waioeka.sbt" % "cucumber-plugin" % "0.1.2")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package example
2+
3+
import java.nio.file.{Files, Path, Paths}
4+
5+
import scala.collection.JavaConverters._
6+
7+
object Calculator {
8+
9+
def main(args: Array[String]): Unit = {
10+
args.toList match {
11+
case Nil => println(s"Usage: Expected either two ints or a file path")
12+
case List(filePath) =>
13+
println(apply(Paths.get(filePath)))
14+
case List(a, b) =>
15+
println(add(a.toInt, b.toInt))
16+
case err => println(s"Usage: Expected either two ints or a file path, but got $err")
17+
}
18+
}
19+
20+
def add(x: Int, y: Int): Int = x + y
21+
22+
def subtract(x: Int, y: Int): Int = x - y
23+
24+
val PlusR = """(\d+)\s*\+\s*(\d+)""".r
25+
val MinusR = """(\d+)\s*-\s*(\d+)""".r
26+
27+
/**
28+
* Evaluates the first line of the input file to be an addition or subtration operation.
29+
*
30+
* This is just added to demonstrate e.g. composing two containers w/ shared volumes
31+
*/
32+
def apply(input: Path): Int = {
33+
Files.readAllLines(input).asScala.headOption match {
34+
case Some(PlusR(a, b)) => add(a.toInt, b.toInt)
35+
case Some(MinusR(a, b)) => subtract(a.toInt, b.toInt)
36+
case _ => sys.error("Whacha talkin' bout, willis?")
37+
}
38+
}
39+
40+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package example
2+
3+
import scala.sys.process._
4+
5+
case class CalculatorClient(hostPort: String) {
6+
7+
def add(x: Int, y: Int) = curl("add", x, y)
8+
9+
def subtract(x: Int, y: Int) = curl("subtract", x, y)
10+
11+
private def curl(path: String, x: Int, y: Int) = {
12+
val url = s"${hostPort}/$path/$x/$y"
13+
println(s"curling $url")
14+
val output = s"curl $url".!!
15+
try {
16+
output.trim.toInt
17+
} catch{
18+
case nfe : NumberFormatException =>
19+
println(output)
20+
throw new Exception(s"$url responded with: >${output}< : $nfe", nfe)
21+
}
22+
}
23+
24+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package example
2+
3+
import java.net.InetSocketAddress
4+
5+
import com.sun.net.httpserver.{HttpExchange, HttpHandler, HttpServer}
6+
7+
object CalculatorServer extends App {
8+
def start(port: Int) = {
9+
val server = HttpServer.create(new InetSocketAddress(port), 0)
10+
server.createContext("/", Handler)
11+
server.start()
12+
server
13+
}
14+
15+
16+
object Handler extends HttpHandler {
17+
18+
val AddInput = """/add/([-0-9]+)/([-0-9]+)/?""".r
19+
val SubtractInput = """/subtract/([-0-9]+)/([-0-9]+)/?""".r
20+
21+
override def handle(ex: HttpExchange): Unit = {
22+
val path = ex.getRequestURI.toString
23+
24+
val resultOpt = path match {
25+
case AddInput(a, b) => Option(Calculator.add(a.toInt, b.toInt))
26+
case SubtractInput(a, b) =>
27+
Option(Calculator.subtract(a.toInt, b.toInt))
28+
case _ => None
29+
}
30+
31+
val replyString = resultOpt match {
32+
case Some(x) =>
33+
val response = x.toString
34+
ex.sendResponseHeaders(200, response.length)
35+
response
36+
case None =>
37+
val response = s"Unknown path: $path"
38+
ex.sendResponseHeaders(404, response.length)
39+
response
40+
}
41+
42+
ex.getResponseBody.write(replyString.getBytes)
43+
}
44+
}
45+
46+
47+
val port = args.headOption.map(_.toInt).getOrElse(8080)
48+
println(s"Starting calculator server on port $port w/ user args ${args.mkString(": [", ",", "]")}")
49+
start(port)
50+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package example
2+
3+
object ClientApp extends App {
4+
val client = CalculatorClient("http://localhost:8080")
5+
6+
println(client.add(5, 6))
7+
println(client.subtract(5, 6))
8+
9+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Feature: Remote Server/Client contract
2+
3+
Background:
4+
And a calculator client against http://localhost:8080
5+
6+
Scenario Outline: Addition
7+
Given a remote request to add <lhs> and <rhs>
8+
Then The response should be <sum>
9+
Examples:
10+
| lhs | rhs | sum |
11+
| -1 | 1 | 0 |
12+
| 0 | 0 | 0 |
13+
| 1 | 0 | 1 |
14+
| 0 | 1 | 1 |
15+
| 1 | 2 | 3 |
16+
17+
Scenario Outline: Subtraction
18+
Given a remote request to subtract <rhs> from <lhs>
19+
Then The response should be <result>
20+
Examples:
21+
| lhs | rhs | result |
22+
| -1 | 1 | -2 |
23+
| 0 | 0 | 0 |
24+
| 1 | 0 | 1 |
25+
| 0 | 1 | -1 |
26+
| 1 | 2 | -1 |

0 commit comments

Comments
 (0)