Hi Dmitry,
One other explanation that may help you understand the situation is
that what will happen with the existing, original Framework API is
that only test classes that sbt discovers will be run in parallel.
Since sbt doesn't discover the PhasesSpec, because it does not have a
no-arg constructor, that one won't get executed in parallel. What
ScalaTest could do is pass its own distributor down, but I think
that's wrong because sbt should have the thread pool, and besides we
have no way of knowing whether the user asked for sequential execution
in the build file. So it should really be sbt, and this requires the
new Framework API.
I did want to give you one more tweak to the code, though, which is this:
import org.scalatest._
class PhasesSpec(override val suiteName: String) extends FreeSpec with
CancelAfterFailure {
"Configuration for %s".format(suiteName) - {
"Phase 1" in {
for (j <- 0 until 10) {
println("working %s Phase-1 %s".format(suiteName, j))
Thread.sleep(50)
}
}
"Phase 2" in {
for (j <- 0 until 10) {
println("working %s Phase-2 %s".format(suiteName, j))
Thread.sleep(50)
}
}
}
override def suiteId = suiteName
}
class DmitrySpec extends Suites(
(for (alias <- Vector("Config1", "Config2", "Config3"))
yield new PhasesSpec(alias)): _*
)
I fixed a Config2 => Config3 typo in my earlier at-airport-written
code, but main thing is I added an override of suiteId. This enables
sorting of events with -PS. If you run with just plain -P, you get no
special sorting of events:
Run starting. Expected test count is: 6
DmitrySpec:
Config1:
Config2:
Config3:
Configuration for Config3
Configuration for Config1
Configuration for Config2
working Config3 Phase-1 0
working Config1 Phase-1 0
working Config2 Phase-1 0
working Config3 Phase-1 1
working Config2 Phase-1 1
working Config1 Phase-1 1
working Config1 Phase-1 2
working Config3 Phase-1 2
working Config2 Phase-1 2
working Config3 Phase-1 3
working Config1 Phase-1 3
working Config2 Phase-1 3
working Config3 Phase-1 4
working Config2 Phase-1 4
working Config1 Phase-1 4
working Config1 Phase-1 5
working Config3 Phase-1 5
working Config2 Phase-1 5
working Config1 Phase-1 6
working Config2 Phase-1 6
working Config3 Phase-1 6
working Config3 Phase-1 7
working Config2 Phase-1 7
working Config1 Phase-1 7
working Config3 Phase-1 8
working Config2 Phase-1 8
working Config1 Phase-1 8
working Config3 Phase-1 9
working Config1 Phase-1 9
working Config2 Phase-1 9
working Config2 Phase-2 0
working Config1 Phase-2 0
working Config3 Phase-2 0
- Phase 1
- Phase 1
- Phase 1
working Config1 Phase-2 1
working Config2 Phase-2 1
working Config3 Phase-2 1
working Config1 Phase-2 2
working Config3 Phase-2 2
working Config2 Phase-2 2
working Config3 Phase-2 3
working Config2 Phase-2 3
working Config1 Phase-2 3
working Config1 Phase-2 4
working Config2 Phase-2 4
working Config3 Phase-2 4
working Config3 Phase-2 5
working Config1 Phase-2 5
working Config2 Phase-2 5
working Config3 Phase-2 6
working Config1 Phase-2 6
working Config2 Phase-2 6
working Config1 Phase-2 7
working Config3 Phase-2 7
working Config2 Phase-2 7
working Config1 Phase-2 8
working Config2 Phase-2 8
working Config3 Phase-2 8
working Config2 Phase-2 9
working Config1 Phase-2 9
working Config3 Phase-2 9
- Phase 2
- Phase 2
- Phase 2
Run completed in 1 second, 243 milliseconds.
Total number of tests run: 6
Suites: completed 4, aborted 0
Tests: succeeded 6, failed 0, canceled 0, ignored 0, pending 0
All tests passed.
That was as before. If you say -PS, though, it will sort the events.
Even though it goes in parallel, you get sorted output as if you ran
sequentially. You can see it is running in parallel because the
printlns are still coming out in parallel:
$ scala -cp target/jar_contents/ org.scalatest.tools.Runner -s
DmitrySpec -PS -o -R .
Run starting. Expected test count is: 6
DmitrySpec:
Config1:
Configuration for Config1
working Config1 Phase-1 0
working Config3 Phase-1 0
working Config2 Phase-1 0
working Config3 Phase-1 1
working Config2 Phase-1 1
working Config1 Phase-1 1
working Config1 Phase-1 2
working Config2 Phase-1 2
working Config3 Phase-1 2
working Config1 Phase-1 3
working Config2 Phase-1 3
working Config3 Phase-1 3
working Config3 Phase-1 4
working Config1 Phase-1 4
working Config2 Phase-1 4
working Config3 Phase-1 5
working Config1 Phase-1 5
working Config2 Phase-1 5
working Config2 Phase-1 6
working Config1 Phase-1 6
working Config3 Phase-1 6
working Config2 Phase-1 7
working Config3 Phase-1 7
working Config1 Phase-1 7
working Config2 Phase-1 8
working Config3 Phase-1 8
working Config1 Phase-1 8
working Config2 Phase-1 9
working Config3 Phase-1 9
working Config1 Phase-1 9
- Phase 1
working Config1 Phase-2 0
working Config3 Phase-2 0
working Config2 Phase-2 0
working Config1 Phase-2 1
working Config3 Phase-2 1
working Config2 Phase-2 1
working Config1 Phase-2 2
working Config2 Phase-2 2
working Config3 Phase-2 2
working Config1 Phase-2 3
working Config3 Phase-2 3
working Config2 Phase-2 3
working Config1 Phase-2 4
working Config2 Phase-2 4
working Config3 Phase-2 4
working Config1 Phase-2 5
working Config2 Phase-2 5
working Config3 Phase-2 5
working Config1 Phase-2 6
working Config2 Phase-2 6
working Config3 Phase-2 6
working Config1 Phase-2 7
working Config3 Phase-2 7
working Config2 Phase-2 7
working Config1 Phase-2 8
working Config2 Phase-2 8
working Config3 Phase-2 8
working Config1 Phase-2 9
working Config2 Phase-2 9
working Config3 Phase-2 9
- Phase 2
Config2:
Configuration for Config2
- Phase 1
- Phase 2
Config3:
Configuration for Config3
- Phase 1
- Phase 2
Run completed in 1 second, 178 milliseconds.
Total number of tests run: 6
Suites: completed 4, aborted 0
Tests: succeeded 6, failed 0, canceled 0, ignored 0, pending 0
All tests passed.
Once you're convinced it is running in parallel, you can change the
println to info calls, which result in events that will also get
sorted. Now the whole thing is in sequential order at the output, even
though it was run in parallel:
import org.scalatest._
class PhasesSpec(override val suiteName: String) extends FreeSpec with
CancelAfterFailure {
"Configuration for %s".format(suiteName) - {
"Phase 1" in {
for (j <- 0 until 10) {
info("working %s Phase-1 %s".format(suiteName, j))
Thread.sleep(50)
}
}
"Phase 2" in {
for (j <- 0 until 10) {
info("working %s Phase-2 %s".format(suiteName, j))
Thread.sleep(50)
}
}
}
override def suiteId = suiteName
}
class DmitrySpec extends Suites(
(for (alias <- Vector("Config1", "Config2", "Config3"))
yield new PhasesSpec(alias)): _*
)
$ scala -cp target/jar_contents/ org.scalatest.tools.Runner -s
DmitrySpec -PS -o -R .
Run starting. Expected test count is: 6
DmitrySpec:
Config1:
Configuration for Config1
- Phase 1
+ working Config1 Phase-1 0
+ working Config1 Phase-1 1
+ working Config1 Phase-1 2
+ working Config1 Phase-1 3
+ working Config1 Phase-1 4
+ working Config1 Phase-1 5
+ working Config1 Phase-1 6
+ working Config1 Phase-1 7
+ working Config1 Phase-1 8
+ working Config1 Phase-1 9
- Phase 2
+ working Config1 Phase-2 0
+ working Config1 Phase-2 1
+ working Config1 Phase-2 2
+ working Config1 Phase-2 3
+ working Config1 Phase-2 4
+ working Config1 Phase-2 5
+ working Config1 Phase-2 6
+ working Config1 Phase-2 7
+ working Config1 Phase-2 8
+ working Config1 Phase-2 9
Config2:
Configuration for Config2
- Phase 1
+ working Config2 Phase-1 0
+ working Config2 Phase-1 1
+ working Config2 Phase-1 2
+ working Config2 Phase-1 3
+ working Config2 Phase-1 4
+ working Config2 Phase-1 5
+ working Config2 Phase-1 6
+ working Config2 Phase-1 7
+ working Config2 Phase-1 8
+ working Config2 Phase-1 9
- Phase 2
+ working Config2 Phase-2 0
+ working Config2 Phase-2 1
+ working Config2 Phase-2 2
+ working Config2 Phase-2 3
+ working Config2 Phase-2 4
+ working Config2 Phase-2 5
+ working Config2 Phase-2 6
+ working Config2 Phase-2 7
+ working Config2 Phase-2 8
+ working Config2 Phase-2 9
Config3:
Configuration for Config3
- Phase 1
+ working Config3 Phase-1 0
+ working Config3 Phase-1 1
+ working Config3 Phase-1 2
+ working Config3 Phase-1 3
+ working Config3 Phase-1 4
+ working Config3 Phase-1 5
+ working Config3 Phase-1 6
+ working Config3 Phase-1 7
+ working Config3 Phase-1 8
+ working Config3 Phase-1 9
- Phase 2
+ working Config3 Phase-2 0
+ working Config3 Phase-2 1
+ working Config3 Phase-2 2
+ working Config3 Phase-2 3
+ working Config3 Phase-2 4
+ working Config3 Phase-2 5
+ working Config3 Phase-2 6
+ working Config3 Phase-2 7
+ working Config3 Phase-2 8
+ working Config3 Phase-2 9
Run completed in 1 second, 167 milliseconds.
Total number of tests run: 6
Suites: completed 4, aborted 0
Tests: succeeded 6, failed 0, canceled 0, ignored 0, pending 0
All tests passed.
Bill