在开始对该服务器进行测试之前,是否有一种简单的方法可以在 sbt 中分叉服务器进程?
Is there a simple way to fork a server process in sbt before starting test against that server?
我的端到端测试任务向服务器发送了一些 http 请求。我想在单独的 jvm 上启动该服务器(基于 Play 框架),然后启动命中服务器的测试并让它完成,然后停止服务器。
到目前为止,我浏览了许多 SO 线程发现了这些选项:
- 使用sbt-sequential
- 使用sbt-revolver
- 使用alias
但在我的实验中设置 fork 不起作用,即它在服务器启动时仍然阻止执行
fork := true
fork in run := true
fork in Test := true
fork in IntegrationTest := true
sbt docs 中的 startServer/stopServer 示例似乎也被阻止了
我也试过从 shell 在后台启动服务器,但服务器很快就关闭了,类似于
nohup sbt -Djline.terminal=jline.UnsupportedTerminal web/run < /dev/null > /tmp/sbt.log 2>&1 &
相关问题:
scala sbt test run setup and cleanup command once on multi project
How do I start a server before running a test suite in SBT?
fork
不会 运行 并行任务 - 它只是确保测试 运行 在单独的 JVM 中,这有助于关闭 webhooks 或断开与服务的连接没有正确处理资源释放(例如,从不调用断开连接的数据库连接)。
如果你想使用相同的 sbt 来启动服务器并且 运行 测试那个实例(这听起来很容易破解反模式顺便说一句)你可以使用类似的东西:
reStart
it:test
reStop
但是这会很棘手,因为 reStart
会立即产生,因此测试会在服务器设置开始但不一定完成时开始。竞争条件、测试失败或阻止 所有 测试直到服务器完成启动。
这就是为什么没有人这样做的原因。更容易处理的解决方案是:
- 在某些
beforeAll
方法中启动测试服务器,并仅在服务器响应查询后才完成此方法
- 在某些
afterAll
方法中关闭它(或者使用 cats.effect.Resource
或类似方法以某种方式处理这两者)
- 视情况而定:
- 运行ning 顺序测试以避免同时启动两个实例或
- 为每个测试生成配置,以便它们可以 运行 并行,而不会在端口分配上发生冲突
其他任何事情都只是一个黑客,迟早会失败。
回答我自己的问题,我们最终做的是
- 使用“sbt stage”为 Play 网络应用创建独立服务器 jar 和 运行 脚本(在 web/target/universal/stage/bin/ 中)
- 创建 run_integration_tests.sh shell 启动服务器的脚本,等待 30 秒并启动测试
- 在调用run_integration_tests.sh的build.sbt中添加运行IntegrationTests任务,并将其添加到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
)
在 CI/jenkins 中调用 sbt:
sh 'sbt clean coverage test stage it:test'
我的端到端测试任务向服务器发送了一些 http 请求。我想在单独的 jvm 上启动该服务器(基于 Play 框架),然后启动命中服务器的测试并让它完成,然后停止服务器。
到目前为止,我浏览了许多 SO 线程发现了这些选项:
- 使用sbt-sequential
- 使用sbt-revolver
- 使用alias
但在我的实验中设置 fork 不起作用,即它在服务器启动时仍然阻止执行
fork := true
fork in run := true
fork in Test := true
fork in IntegrationTest := true
sbt docs 中的 startServer/stopServer 示例似乎也被阻止了
我也试过从 shell 在后台启动服务器,但服务器很快就关闭了,类似于
nohup sbt -Djline.terminal=jline.UnsupportedTerminal web/run < /dev/null > /tmp/sbt.log 2>&1 &
相关问题:
scala sbt test run setup and cleanup command once on multi project
How do I start a server before running a test suite in SBT?
fork
不会 运行 并行任务 - 它只是确保测试 运行 在单独的 JVM 中,这有助于关闭 webhooks 或断开与服务的连接没有正确处理资源释放(例如,从不调用断开连接的数据库连接)。
如果你想使用相同的 sbt 来启动服务器并且 运行 测试那个实例(这听起来很容易破解反模式顺便说一句)你可以使用类似的东西:
reStart
it:test
reStop
但是这会很棘手,因为 reStart
会立即产生,因此测试会在服务器设置开始但不一定完成时开始。竞争条件、测试失败或阻止 所有 测试直到服务器完成启动。
这就是为什么没有人这样做的原因。更容易处理的解决方案是:
- 在某些
beforeAll
方法中启动测试服务器,并仅在服务器响应查询后才完成此方法 - 在某些
afterAll
方法中关闭它(或者使用cats.effect.Resource
或类似方法以某种方式处理这两者) - 视情况而定:
- 运行ning 顺序测试以避免同时启动两个实例或
- 为每个测试生成配置,以便它们可以 运行 并行,而不会在端口分配上发生冲突
其他任何事情都只是一个黑客,迟早会失败。
回答我自己的问题,我们最终做的是
- 使用“sbt stage”为 Play 网络应用创建独立服务器 jar 和 运行 脚本(在 web/target/universal/stage/bin/ 中)
- 创建 run_integration_tests.sh shell 启动服务器的脚本,等待 30 秒并启动测试
- 在调用run_integration_tests.sh的build.sbt中添加运行IntegrationTests任务,并将其添加到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
)
在 CI/jenkins 中调用 sbt:
sh 'sbt clean coverage test stage it:test'