Initial working version of makeParallel that support nested tasks.

This commit is contained in:
cheeseng 2013-04-03 17:04:40 +08:00
parent a920c739d6
commit 48fb0c4ed6
5 changed files with 128 additions and 7 deletions

View File

@ -112,7 +112,7 @@ object Tests
val setupTasks = fj(partApp(userSetup) :+ frameworkSetup)
val mainTasks =
if(config.parallel)
makeParallel(runnables, setupTasks, config.tags).toSeq.join
makeParallel(loader, runnables, setupTasks, config.tags)//.toSeq.join
else
makeSerial(loader, runnables, setupTasks, config.tags)
val taggedMainTasks = mainTasks.tagw(config.tags : _*)
@ -122,8 +122,30 @@ object Tests
}
}
type TestRunnable = (String, TestFunction)
def makeParallel(runnables: Iterable[TestRunnable], setupTasks: Task[Unit], tags: Seq[(Tag,Int)]) =
runnables map { case (name, test) => task { (name, test.apply()._1) } tagw(tags : _*) tag(test.tags map (ConcurrentRestrictions.Tag(_)) : _*) dependsOn setupTasks named name }
private def createNestedRunnables(name: String, loader: ClassLoader, testFun: TestFunction, nestedTasks: Seq[TestTask]): Seq[(String, TestFunction)] =
nestedTasks.view.zipWithIndex map { case (nt, idx) =>
(name, TestFramework.createTestFunction(loader, new TestDefinition(testFun.testDefinition.name + "-" + idx, testFun.testDefinition.fingerprint), testFun.runner, nt))
}
def makeParallel(loader: ClassLoader, runnables: Iterable[TestRunnable], setupTasks: Task[Unit], tags: Seq[(Tag,Int)]): Task[Map[String,SuiteResult]] =
toTasks(loader, runnables.toSeq, tags).dependsOn(setupTasks)
def toTasks(loader: ClassLoader, runnables: Seq[TestRunnable], tags: Seq[(Tag,Int)]): Task[Map[String, SuiteResult]] = {
val tasks = runnables.map { case (name, test) => toTask(loader, name, test, tags) }
tasks.join.map( _.foldLeft(Map.empty[String, SuiteResult]) { case (sum, e) =>
sum ++ e
} )
}
def toTask(loader: ClassLoader, name: String, fun: TestFunction, tags: Seq[(Tag,Int)]): Task[Map[String, SuiteResult]] = {
val base = task { (name, fun.apply()) }
val taggedBase = base.tagw(tags : _*).tag(fun.tags.map(ConcurrentRestrictions.Tag(_)) : _*)
taggedBase flatMap { case (name, (result, nested)) =>
val nestedRunnables = createNestedRunnables(fun.testDefinition.name, loader, fun, nested)
toTasks(loader, nestedRunnables, tags).map( _.updated(name, result) )
}
}
def makeSerial(loader: ClassLoader, runnables: Seq[TestRunnable], setupTasks: Task[Unit], tags: Seq[(Tag,Int)]): Task[List[(String, SuiteResult)]] =
{
@ -133,10 +155,7 @@ object Tests
case hd :: rst =>
val testFun = hd._2
val (result, nestedTasks) = testFun.apply()
val nestedRunnables =
nestedTasks.view.zipWithIndex map { case (nt, idx) =>
(hd._1, TestFramework.createTestFunction(loader, new TestDefinition(testFun.testDefinition.name + "-" + idx, testFun.testDefinition.fingerprint), testFun.runner, nt))
}
val nestedRunnables = createNestedRunnables(testFun.testDefinition.name, loader, testFun, nestedTasks)
processRunnable(nestedRunnables.toList ::: rst, (hd._1, result) :: acc)
case Nil => acc
}

View File

@ -0,0 +1,7 @@
scalaVersion := "2.10.1"
libraryDependencies += "org.scalatest" %% "scalatest" % "2.0.M6-SNAP15"
testOptions in Test += Tests.Argument("-r", "custom.CustomReporter")
parallelExecution in Test := true

View File

@ -0,0 +1,30 @@
package custom
import java.io._
import org.scalatest._
import events._
class CustomReporter extends Reporter {
private def writeFile(filePath: String, content: String) {
val file = new File(filePath)
val writer =
if (!file.exists)
new FileWriter(new File(filePath))
else
new FileWriter(new File(filePath + "-2"))
writer.write(content)
writer.flush()
writer.close()
}
def apply(event: Event) {
event match {
case SuiteStarting(_, suiteName, _, _, _, _, _, _, _, _) => writeFile("target/SuiteStarting-" + suiteName, suiteName)
case SuiteCompleted(_, suiteName, _, _, _, _, _, _, _, _, _) => writeFile("target/SuiteCompleted-" + suiteName, suiteName)
case TestStarting(_, _, _, _, testName, _, _, _, _, _, _, _) => writeFile("target/TestStarting-" + testName, testName)
case TestSucceeded(_, _, _, _, testName, _, _, _, _, _, _, _, _, _) => writeFile("target/TestSucceeded-" + testName, testName)
case _ =>
}
}
}

View File

@ -0,0 +1,17 @@
package com.test
import org.scalatest._
class NestedSpecs extends Suites (
new TestSpec
)
@DoNotDiscover
class TestSpec extends Spec {
def `TestSpec-test-1 ` {}
def `TestSpec-test-2 ` {}
def `TestSpec-test-3 ` {}
}

View File

@ -0,0 +1,48 @@
#This test that the framework will execute ScalaTest nested suites as parallel nested task (InProcess) properly.
#A CustomReporter is used to report expected ScalaTest's events by writing out to files in target/,
#it is then used to check for their existence, and if the expected event is fired > 1 (which is unexpected),
#a xxxx-2 file will be written, thus here we also check for 'absent' of such file.
> clean
> test
$ exists target/SuiteStarting-NestedSpecs
$ absent target/SuiteStarting-NestedSpecs-2
$ exists target/SuiteCompleted-NestedSpecs
$ absent target/SuiteCompleted-NestedSpecs-2
$ exists target/SuiteStarting-TestSpec
$ absent target/SuiteStarting-TestSpec-2
$ exists target/SuiteCompleted-TestSpec
$ absent target/SuiteCompleted-TestSpec-2
$ exists target/TestStarting-TestSpec-test-1
$ absent target/TestStarting-TestSpec-test-1-2
$ exists target/TestSucceeded-TestSpec-test-1
$ absent target/TestSucceeded-TestSpec-test-1-2
$ exists target/TestStarting-TestSpec-test-2
$ absent target/TestStarting-TestSpec-test-2-2
$ exists target/TestSucceeded-TestSpec-test-2
$ absent target/TestSucceeded-TestSpec-test-2-2
$ exists target/TestStarting-TestSpec-test-3
$ absent target/TestStarting-TestSpec-test-3-2
$ exists target/TestSucceeded-TestSpec-test-3
$ absent target/TestSucceeded-TestSpec-test-3-2