Scalatest - 如何在运行时创建并行测试

Scalatest - how to create parallel test at runtime

运行

package com.thron.qa.tests

import org.scalatest.{FunSuite, ParallelTestExecution}
import org.scalatest.concurrent.Eventually

class ParallelRuntimeTest extends FunSuite with Eventually with ParallelTestExecution{

  Vector.range(0,10).foreach(iteration => {
    test ("test number  n " + iteration.toString) {
      succeed
    }
  })

}

我获得了运行时测试创建:对向量的迭代构建了测试,并且每个测试都有它的成功状态,正如您在 Idea Ide

中看到的那样

现在,我想并行化这些测试

通常我使用 .par 来获得操作的并行化, 所以代码变成

Vector.range(0,10).par.foreach(iteration => {
    test ("test number  n " + iteration.toString) {
      succeed
    }
  })

但在这种情况下, 我得到这个错误:

An exception or error caused a run to abort: Two threads attempted to modify FunSuite's internal data, which should only be modified by the thread that constructs the object. This likely means that a subclass has allowed the this reference to escape during construction, and some other thread attempted to invoke the "testsFor" or "test" methods on the object before the first thread completed its construction. java.util.ConcurrentModificationException: Two threads attempted to modify FunSuite's internal data, which should only be modified by the thread that constructs the object. This likely means that a subclass has allowed the this reference to escape during construction, and some other thread attempted to invoke the "testsFor" or "test" methods on the object before the first thread completed its construction.

如何在运行时创建测试并以并行方式运行它们?

谢谢

test命令不运行任何测试。它只是 注册 一个测试用例,并为其附加一个字符串名称。它不需要任何资源,并且基本上是即时的。因此,没有必要并行注册测试用例。如您的错误消息所示,无论如何也无法并行注册它们。

按顺序创建测试,它们将自动 运行 并行:

import org.scalatest.{FunSuite, ParallelTestExecution}
import org.scalatest.concurrent.Eventually

class ParallelRuntimeTest 
extends FunSuite 
   with Eventually 
   with ParallelTestExecution {

  for (i <- (0 to 59)) {
    test ("test number  n " + i) {
      Thread.sleep(1000)
      succeed
    }
  }

}

如果你测试它,你会注意到它大约需要 15 秒而不是一分钟(我认为这是因为用于测试的默认线程数是四个,所以 60 / 4 = 15)。

正如@Andrey Tyukin 所提到的,默认情况下 sbt 运行s 所有任务都是并行的,并且在与 sbt 本身相同的 JVM 中。因为每个测试都映射到一个任务,所以默认情况下测试也是 运行 并行的。

我们可以关闭多项目构建测试的并行执行,如下所示。

parallelExecution in Test := false,
parallelExecution in IntegrationTest := false

使用 ParallelTestExecution 和 "sbt test" -scalaTest 3.0.x (https://github.com/scalatest/scalatest/issues/898) 似乎有问题。但是,此问题的解决方法是在 Overriding Distributor 中。

class Example extends FunSpec with ParallelTestExecution with StressTest {
  describe("Example") {
    for (i <- 1 to poolSize) {
      it(s"test ${i} should run in parallel") {
        info(s"example ${i} start")
        Thread.sleep(5000)
        info(s"example ${i} end")
      }
    }
  }
}