多虚拟机测试
支持同时在多个 JVM 中运行应用程序(具有main方法的对象)和ScalaTest测试。对于多个系统相互通信的集成测试很有用。
安装程序
多 JVM 测试是一个sbt插件,可以在 <https://github.com/sbt/sbt-multi-jvm> 中找到。要在项目中配置它,应执行以下步骤:
- 将它作为插件添加到你的
project/plugins.sbt中:
1. addSbtPlugin("com.typesafe.sbt" % "sbt-multi-jvm" % "0.4.0")
- 通过启用
MultiJvmPlugin并设置MultiJvm配置,将多 JVM 测试添加到build.sbt或project/Build.scala。
1. lazy val root = (project in file("."))
2. .enablePlugins(MultiJvmPlugin)
3. .configs(MultiJvm)
请注意,默认情况下,MultiJvm测试源位于src/multi-jvm/...,而不是位于src/test/....。
下面是一个使用sbt-multi-jvm插件的「示例项目」。
运行测试
多 JVM 任务类似于常规任务:test、testOnly和run,但在多 JVM 配置下。
因此,在 Akka 中,要运行akka-remote项目使用中的所有多 JVM 测试(在sbt提示下):
1. akka-remote-tests/multi-jvm:test
或者可以先切换到akka-remote-tests项目,然后运行测试:
1. project akka-remote-tests
2. multi-jvm:test
要运行单个测试,请使用testOnly:
1. multi-jvm:testOnly akka.remote.RandomRoutedRemoteActor
可以列出多个测试名称以运行多个特定测试。sbt中的制表符使完成测试名称变得容易。
也可以使用testOnly指定 JVM 选项,方法是在测试名称和--之后包含这些选项。例如:
1. multi-jvm:testOnly akka.remote.RandomRoutedRemoteActor -- -Dsome.option=something
创建应用程序测试
通过命名约定,可以发现并组合这些测试。MultiJvm测试源位于src/multi-jvm/...。使用以下模式命名测试:
1. {TestName}MultiJvm{NodeName}
也就是说,每个测试的名称中间都有MultiJvm。前面的部分将测试/应用程序分组在一起,使用一个将一起运行的TestName。后面的部分NodeName是每个分叉的 JVM 的一个区别名称。
因此,要创建一个名为Sample的 3 节点测试,可以创建三个应用程序,如下所示:
1. package sample
3. object SampleMultiJvmNode1 {
4. def main(args: Array[String]) {
5. println("Hello from node 1")
6. }
7. }
9. object SampleMultiJvmNode2 {
10. def main(args: Array[String]) {
11. println("Hello from node 2")
12. }
13. }
15. object SampleMultiJvmNode3 {
16. def main(args: Array[String]) {
17. println("Hello from node 3")
18. }
19. }
当你在sbt提示下调用multi-jvm:run sample.Sample时,将生成三个 JVM,每个节点一个。它看起来像这样:
1. > multi-jvm:run sample.Sample
2. ...
3. [info] * sample.Sample
4. [JVM-1] Hello from node 1
5. [JVM-2] Hello from node 2
6. [JVM-3] Hello from node 3
7. [success] Total time: ...
更改默认值
你可以为分叉(forked)的 JVM 指定 JVM 选项:
1. jvmOptions in MultiJvm := Seq("-Xmx256M")
你可以通过向项目中添加以下配置来更改多 JVM 测试源目录的名称:
1. unmanagedSourceDirectories in MultiJvm :=
2. Seq(baseDirectory(_ / "src/some_directory_here")).join.value
你可以更改MultiJvm标识符。例如,要将其更改为ClusterTest,请使用multiJvmMarker设置:
1. multiJvmMarker in MultiJvm := "ClusterTest"
你的测试现在应该命名为{TestName}ClusterTest{NodeName}。
JVM 实例的配置
你可以为每个生成的 JVM 定义特定的 JVM 选项。通过在测试中创建一个后缀为.opts的文件,并将其放在与测试相同的目录中,可以做到这一点。
例如,要将 JVM 选项-Dakka.remote.port=9991和-Xmx256m送到SampleMultiJvmNode1,让我们创建三个*.opts文件并将这些选项添加到它们中。用空格分隔多个选项。
SampleMultiJvmNode1.opts:
1. -Dakka.remote.port=9991 -Xmx256m
SampleMultiJvmNode2.opts:
1. -Dakka.remote.port=9992 -Xmx256m
SampleMultiJvmNode3.opts:
1. -Dakka.remote.port=9993 -Xmx256m
ScalaTest
还支持创建ScalaTest测试,而不是应用程序。要做到这一点,请使用与上面相同的命名约定,但要使用main方法创建ScalaTest套件,而不是对象。你需要在classpath上有ScalaTest。这里有一个类似于上面的例子,但是使用ScalaTest:
1. package sample
3. import org.scalatest.WordSpec
4. import org.scalatest.matchers.MustMatchers
6. class SpecMultiJvmNode1 extends WordSpec with MustMatchers {
7. "A node" should {
8. "be able to say hello" in {
9. val message = "Hello from node 1"
10. message must be("Hello from node 1")
11. }
12. }
13. }
15. class SpecMultiJvmNode2 extends WordSpec with MustMatchers {
16. "A node" should {
17. "be able to say hello" in {
18. val message = "Hello from node 2"
19. message must be("Hello from node 2")
20. }
21. }
22. }
为了运行这些测试,你可以在sbt提示下调用multi-jvm:testOnly sample.Spec。
多节点添加
还对SbtMultiJvm插件进行了一些添加,以适应「可能更改」模块的「多节点测试」,如该部分所述。
英文原文链接:Multi JVM Testing.
