answering my own question, what we ended up doing is
- use "sbt stage" to create standalone server jar & run script for the Play web app (in web/target/universal/stage/bin/)
- create run_integration_tests.sh shell script that starts the server, waits 30 sec and starts test
- add runIntegrationTests task in build.sbt which calls run_integration_tests.sh, and add it to it:test
run_integration_tests.sh:
#! /bin/bash
CURDIR=$(pwd)
echo "Starting integration/e2e test runner"
date >runner.log
export JAVA_OPTS="-Dplay.server.http.port=9195 -Dconfig.file=$CURDIR/web/conf/application_test.conf -Xmx2G"
rm -f "$CURDIR/web/target/universal/stage/RUNNING_PID"
echo "Starting server"
nohup web/target/universal/stage/bin/myapp >>runner.log 2>&1 &
echo "Webserver PID is $pid"
echo "Waiting for server start"
sleep 30
echo "Running the tests"
sbt "service/test:run-main com.blah.myapp.E2ETest"
ERR="$?"
echo "Tests Done at $(date), killing server"
kill $pid
echo "Waiting for server exit"
wait $pid
echo "All done"
if [ $ERR -ne 0 ]; then
cat runner.log
exit "$ERR"
fi
build.sbt:
lazy val runIntegrationTests = taskKey[Unit]("Run integration tests")
runIntegrationTests := {
val s: TaskStreams = streams.value
s.log.info("Running integration tests...")
val shell: Seq[String] = Seq("bash", "-c")
val runTests: Seq[String] = shell :+ "./run_integration_tests.sh"
if ((runTests !) == 0) {
s.log.success("Integration tests successful!")
} else {
s.log.error("Integration tests failed!")
throw new IllegalStateException("Integration tests failed!")
}
}
lazy val root = project.in(file("."))
.aggregate(service, web, tools)
.configs(IntegrationTest)
.settings(Defaults.itSettings)
.settings(
publishLocal := {},
publish := {},
(test in IntegrationTest) := (runIntegrationTests dependsOn (test in IntegrationTest)).value
)
calling sbt in CI/jenkins:
sh 'sbt clean coverage test stage it:test'