多JVM测试

    同时在多个 Jvm 中运行应用程序 (main方法的对象) 和 ScalaTest 测试的支持。对于需要多个系统相互沟通的集成测试很有用。

    多JVM测试是 sbt 插件,你可以在 http://github.com/typesafehub/sbt-multi-jvm 找到。

    你可以作为一个插件添加它,在 project/plugins.sbt 添加以下内容:

    然后,你可以通过在 或 project/Build.scala包含MultiJvm和设置添加多JVM 测试。请注意 MultiJvm 测试源代码位于 src/multi-jvm/...而不是在src/test/...

    下面是使用 MultiJvm 插件的 sbt 0.13 下的 build.sbt 文件示例:

    1. import com.typesafe.sbt.SbtMultiJvm
    2. import com.typesafe.sbt.SbtMultiJvm.MultiJvmKeys.MultiJvm
    3. val akkaVersion = "2.3.6"
    4. val project = Project(
    5. id = "akka-sample-multi-node-scala",
    6. base = file("."),
    7. settings = Project.defaultSettings ++ SbtMultiJvm.multiJvmSettings ++ Seq(
    8. name := "akka-sample-multi-node-scala",
    9. version := "2.3.6",
    10. scalaVersion := "2.10.4",
    11. libraryDependencies ++= Seq(
    12. "com.typesafe.akka" %% "akka-remote" % akkaVersion,
    13. "com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion,
    14. "org.scalatest" %% "scalatest" % "2.0" % "test"),
    15. // make sure that MultiJvm test are compiled by the default test compilation
    16. compile in MultiJvm <<= (compile in MultiJvm) triggeredBy (compile in Test),
    17. parallelExecution in Test := false,
    18. // make sure that MultiJvm tests are executed by the default test target,
    19. // and combine the results from ordinary test and multi-jvm tests
    20. executeTests in Test <<= (executeTests in Test, executeTests in MultiJvm) map {
    21. case (testResults, multiNodeResults) =>
    22. val overall =
    23. if (testResults.overall.id < multiNodeResults.overall.id)
    24. multiNodeResults.overall
    25. else
    26. testResults.overall
    27. testResults.events ++ multiNodeResults.events,
    28. testResults.summaries ++ multiNodeResults.summaries)
    29. }
    30. )
    31. ) configs (MultiJvm)

    你可以为分支 Jvm 指定 JVM 选项:

    1. jvmOptions in MultiJvm := Seq("-Xmx256M")

    运行测试

    多JVM任务是类似于正常的任务:test, test-onlyrun,但在multi-jvm配置下。

    所以在Akka中,要运行akka-remote 中的所有多JVM测试(在sbt 提示符中):

    1. akka-remote-tests/multi-jvm:test
    1. project akka-remote-tests
    2. multi-jvm:test

    使用test-only运行单个测试:

    可以列出多个测试名称来运行多个特定的测试。使用sbt的 tab 键可以很容易地完成测试的名称。

    也可以通过在测试名称后和--包括这些选项,来指定 JVM 选项为test-only。举个例子:

    1. multi-jvm:test-only akka.remote.RandomRoutedRemoteActor -- -Dsome.option=something

    测试通过一种命名约定被发现并结合起来。MultiJvm 测试源代码位于src/multi-jvm/...。测试按以下模式命名:

    1. {TestName}MultiJvm{NodeName}

    也就是,每个测试在其名字中有MultiJvm。前面的部分将测试/应用划分在单个TestName组下并将一起运行。后面的部分NodeName,是为每个分叉的 JVM分配的不同的名称。

    因此若要创建名为Sample的3-节点测试,你可以如下创建三个应用程序:

    1. package sample
    2. object SampleMultiJvmNode1 {
    3. println("Hello from node 1")
    4. }
    5. }
    6. object SampleMultiJvmNode2 {
    7. println("Hello from node 2")
    8. }
    9. }
    10. object SampleMultiJvmNode3 {
    11. def main(args: Array[String]) {
    12. println("Hello from node 3")
    13. }
    14. }

    当你在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: ...

    更改默认设置

    你可以通过在项目中添加以下配置来更改多JVM测试的源代码目录的名称:

    1. multiJvmMarker in MultiJvm := "ClusterTest"

    现在,你的测试应该命名为 {TestName}ClusterTest{NodeName}

    你可以为每个生成的 Jvm定义特定 JVM 选项。通过创建一个以节点的名字命名的带有.opts后缀的文件,把它们放在测试的同一个目录中。

    例如,为SampleMultiJvmNode1提供 JVM 选项-Dakka.remote.port=9991-Xmx256m,让我们创建三个 *.opts 文件并向其中添加选项。使用空格分隔多个选项。

    SampleMultiJvmNode1.opts:

    1. -Dakka.remote.port=9991 -Xmx256m

    SampleMultiJvmNode2.opts:

    1. -Dakka.remote.port=9992 -Xmx256m

    SampleMultiJvmNode3.opts:

      ScalaTest

      除了应用程序外,它还支持创建 ScalaTest 测试。要这样做,要如上所述使用相同的命名约定,但创建 ScalaTest 套件,而不是对象的main方法。你需要在类路径上有 ScalaTest。这里是一个类似于上面例子的ScalaTest代码:

      你需要在sbt提示中运行来执行这些测试。