Merge pull request #3155 from jameskoch/bug-fix

Fixes Issue #3154 - "It is not a test" in JUnit XML reports.
This commit is contained in:
eugene yokota 2017-05-05 11:03:35 -04:00 committed by GitHub
commit 762a0e72dd
6 changed files with 76 additions and 15 deletions

View File

@ -0,0 +1,5 @@
### Bug fixes
- Fixes ScalaTest nested suite test names being reported as "(It is not a test)". [#3154][3154] by [@jameskoch][@jameskoch]
[@jameskoch]: https://github.com/jameskoch

View File

@ -0,0 +1,3 @@
scalaVersion := "2.11.8"
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.6" % "test"

View File

@ -8,34 +8,61 @@ object JUnitXmlReportTest extends Build {
val checkReport = taskKey[Unit]("Check the test reports") val checkReport = taskKey[Unit]("Check the test reports")
val checkNoReport = taskKey[Unit]("Check that no reports are present") val checkNoReport = taskKey[Unit]("Check that no reports are present")
private val oneSecondReportFile = "target/test-reports/a.pkg.OneSecondTest.xml" private object JUnit {
private val failingReportFile = "target/test-reports/another.pkg.FailingTest.xml" val oneSecondReportFile = "target/test-reports/a.pkg.OneSecondTest.xml"
val failingReportFile = "target/test-reports/another.pkg.FailingTest.xml"
}
private object ScalaTest {
val flatSuiteReportFile = "target/test-reports/my.scalatest.MyFlatSuite.xml"
val nestedSuitesReportFile = "target/test-reports/my.scalatest.MyNestedSuites.xml"
}
lazy val root = Project("root", file("."), settings = defaultSettings ++ Seq( lazy val root = Project("root", file("."), settings = defaultSettings ++ Seq(
scalaVersion := "2.9.2", scalaVersion := "2.11.8",
libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test", libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test",
// TODO use matchers instead of sys.error // TODO use matchers instead of sys.error
checkReport := { checkReport := {
val oneSecondReport = XML.loadFile(oneSecondReportFile) val oneSecondReport = XML.loadFile(JUnit.oneSecondReportFile)
if( oneSecondReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.") if( oneSecondReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.")
// somehow the 'success' event doesn't go through... TODO investigate // somehow the 'success' event doesn't go through... TODO investigate
// if( (oneSecondReport \ "@time").text.toFloat < 1f ) sys.error("expected test to take at least 1 sec") // if( (oneSecondReport \ "@time").text.toFloat < 1f ) sys.error("expected test to take at least 1 sec")
if( (oneSecondReport \ "@name").text != "a.pkg.OneSecondTest" ) sys.error("wrong test name: " + (oneSecondReport \ "@name").text) if( (oneSecondReport \ "@name").text != "a.pkg.OneSecondTest" ) sys.error("wrong fixture name: " + (oneSecondReport \ "@name").text)
// TODO more checks // TODO more checks
val failingReport = XML.loadFile(failingReportFile) val failingReport = XML.loadFile(JUnit.failingReportFile)
if( failingReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.") if( failingReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.")
if( (failingReport \ "@failures").text != "2" ) sys.error("expected 2 failures") if( (failingReport \ "@failures").text != "2" ) sys.error("expected 2 failures")
if( (failingReport \ "@name").text != "another.pkg.FailingTest" ) sys.error("wrong test name: " + (failingReport \ "@name").text) if( (failingReport \ "@name").text != "another.pkg.FailingTest" ) sys.error("wrong fixture name: " + (failingReport \ "@name").text)
// TODO more checks -> the two test cases with time etc.. // TODO more checks -> the two test cases with time etc..
val scalaTestFlatReport = XML.loadFile(ScalaTest.flatSuiteReportFile)
if( scalaTestFlatReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.")
if( (scalaTestFlatReport \ "@tests").text != "2" ) sys.error("expected 2 tests")
if( (scalaTestFlatReport \ "@failures").text != "1" ) sys.error("expected 1 failures")
if( (scalaTestFlatReport \ "@name").text != "my.scalatest.MyFlatSuite" ) sys.error("wrong fixture name: " + (scalaTestFlatReport \ "@name").text)
val nestedSuitesReport = XML.loadFile(ScalaTest.nestedSuitesReportFile)
if( nestedSuitesReport.label != "testsuite" ) sys.error("Report should have a root <testsuite> element.")
if( (nestedSuitesReport \ "@tests").text != "2" ) sys.error("expected 2 tests")
if( (nestedSuitesReport \ "@failures").text != "1" ) sys.error("expected 1 failures")
if( (nestedSuitesReport \ "@name").text != "my.scalatest.MyNestedSuites" ) sys.error("wrong fixture name: " + (nestedSuitesReport \ "@name").text)
val actualTestName = (nestedSuitesReport \ "testcase").map(t => (t \ "@name").text)
if( actualTestName.toSet != Set("MyInnerSuite.Inner passing test should pass", "MyInnerSuite.Inner failing test should fail")) sys.error(s"wrong test names: ${actualTestName.mkString(", ")}")
// TODO check console output is in the report // TODO check console output is in the report
}, },
checkNoReport := { checkNoReport := {
if( file(oneSecondReportFile).exists() ) sys.error(oneSecondReportFile + " should not exist") for (f <- Seq(
if( file(failingReportFile).exists() ) sys.error(failingReportFile + " should not exist") JUnit.oneSecondReportFile,
JUnit.failingReportFile,
ScalaTest.flatSuiteReportFile,
ScalaTest.nestedSuitesReportFile
)) {
if( file(f).exists() ) sys.error(f + " should not exist")
}
} }
)) ))
} }

View File

@ -0,0 +1,25 @@
import org.scalatest._
package my.scalatest {
class MyFlatSuite extends FlatSpec {
"Passing test" should "pass" in {
}
"Failing test" should "fail" in {
sys.error("wah wah")
}
}
class MyInnerSuite(arg: String) extends FlatSpec {
"Inner passing test" should "pass" in {
}
"Inner failing test" should "fail" in {
sys.error("wah wah")
}
}
class MyNestedSuites extends Suites(new MyInnerSuite("arrrrrg!"))
}

View File

@ -1,13 +1,13 @@
package sbt package sbt
import java.io.{ IOException, StringWriter, PrintWriter, File } import java.io.{ File, IOException, PrintWriter, StringWriter }
import java.net.InetAddress import java.net.InetAddress
import java.util.Hashtable import java.util.Hashtable
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
import scala.util.DynamicVariable import scala.util.DynamicVariable
import scala.xml.{ Elem, Node => XNode, XML } import scala.xml.{ Elem, XML, Node => XNode }
import testing.{ Event => TEvent, Status => TStatus, OptionalThrowable, TestSelector } import testing.{ NestedTestSelector, OptionalThrowable, TestSelector, Event => TEvent, Status => TStatus }
/** /**
* A tests listener that outputs the results it receives in junit xml * A tests listener that outputs the results it receives in junit xml
@ -71,7 +71,8 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener {
for (e <- events) yield <testcase classname={ name } name={ for (e <- events) yield <testcase classname={ name } name={
e.selector match { e.selector match {
case selector: TestSelector => selector.testName.split('.').last case selector: TestSelector => selector.testName.split('.').last
case _ => "(It is not a test)" case nested: NestedTestSelector => nested.suiteId().split('.').last + "." + nested.testName()
case other => s"(It is not a test it is a ${other.getClass.getCanonicalName})"
} }
} time={ (e.duration() / 1000.0).toString }> } time={ (e.duration() / 1000.0).toString }>
{ {