Issue #3154 - ScalaTest nested suites reported in JUnit XML reports as "(It is not a test)".

This commit is contained in:
James Koch 2017-04-30 13:08:44 -04:00
parent f9c0187870
commit ecf14d6ad5
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 checkNoReport = taskKey[Unit]("Check that no reports are present")
private val oneSecondReportFile = "target/test-reports/a.pkg.OneSecondTest.xml"
private val failingReportFile = "target/test-reports/another.pkg.FailingTest.xml"
private object JUnit {
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(
scalaVersion := "2.9.2",
libraryDependencies += "com.novocode" % "junit-interface" % "0.10" % "test",
scalaVersion := "2.11.8",
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test",
// TODO use matchers instead of sys.error
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.")
// 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 \ "@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
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 \ "@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..
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
},
checkNoReport := {
if( file(oneSecondReportFile).exists() ) sys.error(oneSecondReportFile + " should not exist")
if( file(failingReportFile).exists() ) sys.error(failingReportFile + " should not exist")
for (f <- Seq(
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
import java.io.{ IOException, StringWriter, PrintWriter, File }
import java.io.{ File, IOException, PrintWriter, StringWriter }
import java.net.InetAddress
import java.util.Hashtable
import scala.collection.mutable.ListBuffer
import scala.util.DynamicVariable
import scala.xml.{ Elem, Node => XNode, XML }
import testing.{ Event => TEvent, Status => TStatus, OptionalThrowable, TestSelector }
import scala.xml.{ Elem, XML, Node => XNode }
import testing.{ NestedTestSelector, OptionalThrowable, TestSelector, Event => TEvent, Status => TStatus }
/**
* A tests listener that outputs the results it receives in junit xml
@ -70,8 +70,9 @@ class JUnitXmlTestsListener(val outputDir: String) extends TestsListener {
{
for (e <- events) yield <testcase classname={ name } name={
e.selector match {
case selector: TestSelector=> selector.testName.split('.').last
case _ => "(It is not a test)"
case selector: TestSelector => selector.testName.split('.').last
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 }>
{