ScalaTest 可以在没有同步调用的情况下检测超时吗(比如在无限循环中?)

Can ScalaTest detect timeout without synchronization calls (like in an infinite loop?)

在下面的代码中,名为 sleep 的测试正常失败,而测试 freeze 导致测试永远不会结束。

import org.scalatest.FunSuite
import org.scalatest.concurrent.TimeLimitedTests
import org.scalatest.time.SpanSugar._
import scala.language.postfixOps

class MainTest extends FunSuite with TimeLimitedTests {
  def timeLimit = 1 second

  test("sleep") {
    Thread.sleep(10000)
  }

  test("unintentional freeze") {
    var i = 100
    var j = 0
    while (i>0) {
      i += 1 // a bug: should be j += 1
      i -= 1
    }
  }

}

我理解这一点是因为 TimeLimitedTests 使用 ThreadInterruptor 中止超时测试的方式。有没有其他方法可以让 ScalaTest 检测到并使此类代码失败?如果没有,是否有一些常见的做法如何避免或检测测试代码中的此类错误?

当我 运行 在 IDE 中手动测试时,我可以手动中止它们,那些具有无限循环的将被标记为未启动,但我担心当代码中发生这种情况时已提交,因此 Jenkins 构建过程被冻结,需要在构建服务器上手动中止。

首先你的例子是人为的。在现实生活中,即使是无限循环也会调用线程休眠至少毫秒:Thread.sleep(1)。在这种情况下 interrupt 将正常工作。

但假设没有睡觉。所以你需要重写 defaultInterrruptor 以更多 "reliable" 方式杀死线程。

import org.scalatest.FunSuite
import org.scalatest.concurrent.{Interruptor, TimeLimitedTests, ThreadInterruptor, Timeouts}
import org.scalatest.time.SpanSugar._

import scala.language.postfixOps

class MainTest extends FunSuite with TimeLimitedTests {

  override val defaultTestInterruptor: Interruptor = new Interruptor {
    override def apply(testThread: Thread): Unit = {
      println("Kindly die")
      testThread.stop() // deprecated. unsafe. do not use
    }
  }

  def timeLimit = 1 second


  test("sleep") {
    Thread.sleep(10000)
  }

  test("freeze") {
    while (true) {}
  }


}