TimeLimitedTests
Trait that when mixed into a suite class establishes a time limit for its tests.
Unfortunately this trait experienced a potentially breaking change in 3.0: previously this trait declared adefaultTestInterruptor val of type Interruptor, in 3.0 that was renamed to defaultTestSignaler and given type Signaler. The reason is that the default Interruptor, ThreadInterruptor, did not make sense on Scala.js—in fact, the entire notion of interruption did not make sense on Scala.js. Signaler's default is DoNotSignal, which is a better default on Scala.js, and works fine as a default on the JVM. Timeouts was left the same in 3.0, so existing code using it would continue to work as before, but after a deprecation period Timeouts will be supplanted by TimeLimits, which uses Signaler. TimeLimitedTests now uses TimeLimits instead of Timeouts, so if you overrode the default Interruptor before, you'll need to change it to the equivalent Signaler. And if you were depending on the default being a ThreadInterruptor, you'll need to override defaultTestSignaler and set it to ThreadSignaler.
This trait overrides withFixture, wrapping a super.withFixture(test) call in a failAfter invocation, specifying a time limit obtained by invoking timeLimit and a Signaler by invoking defaultTestSignaler:
failAfter(timeLimit) {
super.withFixture(test)
} (defaultTestSignaler)
Note that the failAfter method executes the body of the by-name passed to it using the same thread that invoked failAfter. This means that the same thread will run the withFixture method as well as each test, so no extra synchronization is required. A second thread is used to run a timer, and if the timeout expires, that second thread will attempt to signal the main test thread via the defaultTestSignaler.
The timeLimit field is abstract in this trait. Thus you must specify a time limit when you use it. For example, the following code specifies that each test must complete within 200 milliseconds:
import org.scalatest.FunSpec
import org.scalatest.concurrent.TimeLimitedTests
import org.scalatest.time.SpanSugar._
class ExampleSpec extends FunSpec with TimeLimitedTests {
// Note: You may need to either write 200.millis or (200 millis), or
// place a semicolon or blank line after plain old 200 millis, to
// avoid the semicolon inference problems of postfix operator notation.
val timeLimit = 200 millis
describe("A time-limited test") {
it("should succeed if it completes within the time limit") {
Thread.sleep(100)
}
it("should fail if it is taking too darn long") {
Thread.sleep(300)
}
}
}
If you run the above ExampleSpec, the second test will fail with the error message:
The test did not complete within the specified 200 millisecond time limit.
The failAfter method uses an Signaler to attempt to signal the main test thread if the timeout expires. The default Signaler returned by the defaultTestSignaler method is a DoNotSignal, which does not signal the main test thread to stop. If you wish to change this signaling strategy, override defaultTestSignaler to return a different Signaler. For example, here's how you'd change the default to ThreadSignaler, which will interrupt the main test thread when time is up:
import org.scalatest.FunSpec
import org.scalatest.concurrent.{ThreadSignaler, TimeLimitedTests}
import org.scalatest.time.SpanSugar._
class ExampleSignalerSpec extends FunSpec with TimeLimitedTests {
val timeLimit = 200 millis
override val defaultTestSignaler = ThreadSignaler
describe("A time-limited test") {
it("should succeed if it completes within the time limit") {
Thread.sleep(100)
}
it("should fail if it is taking too darn long") {
Thread.sleep(300)
}
}
}
Like the previous incarnation of ExampleSuite, the second test will fail with an error message that indicates a timeout expired. But whereas in the previous case, the Thread.sleep would be interrupted after 200 milliseconds, in this case it is never interrupted. In the previous case, the failed test requires a little over 200 milliseconds to run. In this case, because the sleep(300) is never interrupted, the failed test requires a little over 300 milliseconds to run.
Attributes
- Graph
-
- Supertypes
- Self type