- Async testing
- Using the runner:
If you include
-Pon the command line,Runnerwill pass aDistributorto theSuites you specify with-s.Runnerwill set up a thread pool to execute anySuites passed to theDistributor'sputmethod in parallel. TraitSuite's implementation ofrunNestedSuiteswill place any nestedSuites into thisDistributor. Thus, if you have aSuiteof tests that must be executed sequentially, you should overriderunNestedSuitesas described in the documentation forDistributor.The
-Poption may optionally be appended with a number (e.g. "-P10" -- no intervening space) to specify the number of threads to be created in the thread pool. If no number (or 0) is specified, the number of threads will be decided based on the number of processors available.
-
AsyncTestSuitemixin:- requires tests to return
Future[Assertion] executionContextby default is serial, i.e tests will run in one queue, single thread per test:
When ScalaTest's serial execution context is called upon to execute a task, that task is recorded in a queue for later execution. For example, one task that will be placed in this queue is the task that transforms the
Future[Assertion]returned by an asynchronous test body to theFutureOutcomereturned from the test function. Other tasks that will be queued are any transformations of, or callbacks registered on,Futures that occur in your test body, including any assertions you map ontoFutures. Once the test body returns, the thread that executed the test body will execute the tasks in that queue one after another, in the order they were enqueued. [...] This thread confinement strategy does mean, however, that when you are using the default execution context on the JVM, you must be sure to never block in the test body waiting for a task to be completed by the execution context. If you block, your test will never complete. This kind of problem will be obvious, because the test will consistently hang every time you run it.- can be overriden by
implicit override def executionContext = ExecutionContext.Implicits.global
- requires tests to return
-
parallel suites execution:
- on by default in sbt:
IntegrationTest / parallelExecution := true - number of threads by defauls is (number of available processors) ✖️ 2
- can be controlled by
IntegrationTest / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-P16")(16 can be any number)
- on by default in sbt:
-
parallel tests execution (within the same suite) is controlled by the
ParallelTestExecutionmixin:By default (unless you mix in
ParallelTestExecution), tests in an asynchronous style traits will be executed one after another, i.e., serially.If
ParallelTestExecutionis mixed in but parallel execution of suites is not enabled, asynchronous tests on the JVM will be started sequentially, by the single thread that invoked run, but without waiting for one test to complete before the next test is started. As a result, asynchronous tests will be allowed to complete in parallel, using threads from theexecutionContext.If you use an execution context backed by a thread-pool, such as global, however, even though tests will be started sequentially by one thread, they will be allowed to run concurrently using threads from the execution context's thread pool.
-
2 thread pools:
Distributorlauncher suites and tests (controlled by-P)executionContextin theAsync...trait collects results
On the JVM, if both
ParallelTestExecutionis mixed in and parallel execution is enabled in the build, tests in an async-style suite will be started in parallel, using threads from theDistributor, and allowed to complete in parallel, using threads from theexecutionContext.