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) {}
}
}
在下面的代码中,名为 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) {}
}
}