forked from scala/scala-partest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request scala#40 from szeiger/wip/sbt-partest
Updated SBTRunner improvements for passing arguments to partest
- Loading branch information
Showing
7 changed files
with
241 additions
and
206 deletions.
There are no files selected for viewing
180 changes: 180 additions & 0 deletions
180
src/partest/scala/tools/partest/nest/AbstractRunner.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/* NEST (New Scala Test) | ||
* Copyright 2007-2013 LAMP/EPFL | ||
* @author Philipp Haller | ||
*/ | ||
|
||
package scala.tools | ||
package partest | ||
package nest | ||
|
||
import utils.Properties._ | ||
import scala.tools.nsc.Properties.{ versionMsg, propOrFalse, setProp } | ||
import scala.collection.{ mutable, immutable } | ||
import TestKinds._ | ||
import scala.reflect.internal.util.Collections.distinctBy | ||
import scala.tools.cmd.{ CommandLine, CommandLineParser, Instance } | ||
|
||
abstract class AbstractRunner(argstr: String) extends { | ||
val parsed = RunnerSpec.creator(CommandLineParser tokenize argstr) | ||
} with RunnerSpec with Instance { | ||
|
||
val suiteRunner: SuiteRunner | ||
|
||
import suiteRunner._ | ||
import NestUI._ | ||
import NestUI.color._ | ||
|
||
private var totalTests = 0 | ||
private val passedTests = mutable.ListBuffer[TestState]() | ||
private val failedTests = mutable.ListBuffer[TestState]() | ||
|
||
def comment(s: String) = echo(magenta("# " + s)) | ||
def levyJudgment() = { | ||
if (totalTests == 0) echoMixed("No tests to run.") | ||
else if (elapsedMillis == 0) echoMixed("Test Run ABORTED") | ||
else if (isSuccess) echoPassed("Test Run PASSED") | ||
else echoFailed("Test Run FAILED") | ||
} | ||
|
||
def passFailString(passed: Int, failed: Int, skipped: Int): String = { | ||
val total = passed + failed + skipped | ||
val isSuccess = failed == 0 | ||
def p0 = s"$passed/$total" | ||
def p = ( if (isSuccess) bold(green(p0)) else p0 ) + " passed" | ||
def f = if (failed == 0) "" else bold(red("" + failed)) + " failed" | ||
def s = if (skipped == 0) "" else bold(yellow("" + skipped)) + " skipped" | ||
|
||
oempty(p, f, s) mkString ", " | ||
} | ||
|
||
protected var summarizing = false | ||
private var elapsedMillis = 0L | ||
private var expectedFailures = 0 | ||
protected def isSuccess = failedTests.size == expectedFailures | ||
|
||
def issueSummaryReport() { | ||
// Don't run twice | ||
if (!summarizing) { | ||
summarizing = true | ||
|
||
val passed0 = passedTests.toList | ||
val failed0 = failedTests.toList | ||
val passed = passed0.size | ||
val failed = failed0.size | ||
val skipped = totalTests - (passed + failed) | ||
val passFail = passFailString(passed, failed, skipped) | ||
val elapsed = if (elapsedMillis > 0) " (elapsed time: " + elapsedString(elapsedMillis) + ")" else "" | ||
val message = passFail + elapsed | ||
|
||
if (failed0.nonEmpty) { | ||
if (isPartestVerbose) { | ||
echo(bold(cyan("##### Transcripts from failed tests #####\n"))) | ||
failed0 foreach { state => | ||
comment("partest " + state.testFile) | ||
echo(state.transcriptString + "\n") | ||
} | ||
} | ||
|
||
def files_s = failed0.map(_.testFile).mkString(""" \""" + "\n ") | ||
echo("# Failed test paths (this command will update checkfiles)") | ||
echo("test/partest --update-check \\\n " + files_s + "\n") | ||
} | ||
|
||
echo(message) | ||
levyJudgment() | ||
} | ||
} | ||
|
||
def run(): Unit = { | ||
if (optDebug || propOrFalse("partest.debug")) NestUI.setDebug() | ||
if (optVerbose) NestUI.setVerbose() | ||
if (optTerse) NestUI.setTerse() | ||
if (optShowDiff) NestUI.setDiffOnFail() | ||
|
||
// Early return on no args, version, or invalid args | ||
if (optVersion) return echo(versionMsg) | ||
if (optHelp) return NestUI.usage() | ||
|
||
val (individualTests, invalid) = parsed.residualArgs map (p => Path(p)) partition denotesTestPath | ||
if (invalid.nonEmpty) { | ||
if (isPartestVerbose) | ||
invalid foreach (p => echoWarning(s"Discarding invalid test path " + p)) | ||
else if (!isPartestTerse) | ||
echoWarning(s"Discarding ${invalid.size} invalid test paths") | ||
} | ||
|
||
optTimeout foreach (x => setProp("partest.timeout", x)) | ||
|
||
if (!isPartestTerse) | ||
NestUI echo banner | ||
|
||
val partestTests = ( | ||
if (optSelfTest) TestKinds.testsForPartest | ||
else Nil | ||
) | ||
|
||
val grepExpr = optGrep getOrElse "" | ||
|
||
// If --grep is given we suck in every file it matches. | ||
// TODO: intersect results of grep with specified kinds, if any | ||
val greppedTests = if (grepExpr == "") Nil else { | ||
val paths = grepFor(grepExpr) | ||
if (paths.isEmpty) | ||
echoWarning(s"grep string '$grepExpr' matched no tests.\n") | ||
|
||
paths.sortBy(_.toString) | ||
} | ||
|
||
val isRerun = optFailed | ||
val rerunTests = if (isRerun) TestKinds.failedTests else Nil | ||
def miscTests = partestTests ++ individualTests ++ greppedTests ++ rerunTests | ||
|
||
val givenKinds = standardKinds filter parsed.isSet | ||
val kinds = ( | ||
if (givenKinds.nonEmpty) givenKinds | ||
else if (miscTests.isEmpty) standardKinds // If no kinds, --grep, or individual tests were given, assume --all | ||
else Nil | ||
) | ||
val kindsTests = kinds flatMap testsFor | ||
|
||
def testContributors = { | ||
List( | ||
if (partestTests.isEmpty) "" else "partest self-tests", | ||
if (rerunTests.isEmpty) "" else "previously failed tests", | ||
if (kindsTests.isEmpty) "" else s"${kinds.size} named test categories", | ||
if (greppedTests.isEmpty) "" else s"${greppedTests.size} tests matching '$grepExpr'", | ||
if (individualTests.isEmpty) "" else "specified tests" | ||
) filterNot (_ == "") mkString ", " | ||
} | ||
|
||
val allTests: Array[Path] = distinctBy(miscTests ++ kindsTests)(_.toCanonical) sortBy (_.toString) toArray | ||
val grouped = (allTests groupBy kindOf).toArray sortBy (x => standardKinds indexOf x._1) | ||
|
||
totalTests = allTests.size | ||
expectedFailures = propOrNone("partest.errors") match { | ||
case Some(num) => num.toInt | ||
case _ => 0 | ||
} | ||
val expectedFailureMessage = if (expectedFailures == 0) "" else s" (expecting $expectedFailures to fail)" | ||
echo(s"Selected $totalTests tests drawn from $testContributors$expectedFailureMessage\n") | ||
|
||
val (_, millis) = timed { | ||
for ((kind, paths) <- grouped) { | ||
val num = paths.size | ||
val ss = if (num == 1) "" else "s" | ||
comment(s"starting $num test$ss in $kind") | ||
val results = runTestsForFiles(paths map (_.jfile.getAbsoluteFile), kind) | ||
val (passed, failed) = results partition (_.isOk) | ||
|
||
passedTests ++= passed | ||
failedTests ++= failed | ||
if (failed.nonEmpty) { | ||
comment(passFailString(passed.size, failed.size, 0) + " in " + kind) | ||
} | ||
echo("") | ||
} | ||
} | ||
this.elapsedMillis = millis | ||
issueSummaryReport() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.