Merge pull request #6425 from ashleymercer/issues/2853-junit-config

Allow output directory for JUnitXmlTestsListener to be configured
This commit is contained in:
eugene yokota 2021-04-12 10:15:56 -04:00 committed by GitHub
commit 627f72ef87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 20 deletions

View File

@ -8,9 +8,16 @@
package sbt
package plugins
import Def.Setting
import java.io.File
import Def.{ Setting, settingKey }
import Defaults._
import Keys._
import sbt.internal.SysProp
import KeyRanks._
import sbt.Project.inConfig
import sbt.internal._
import sbt.io.syntax._
import sbt.librarymanagement.Configurations.{ IntegrationTest, Test }
/**
* An experimental plugin that adds the ability for junit-xml to be generated.
@ -27,14 +34,23 @@ object JUnitXmlReportPlugin extends AutoPlugin {
override def requires = JvmPlugin
override def trigger = allRequirements
// Right now we add to the global test listeners which should capture *all* tests.
// It might be a good idea to derive this setting into specific test scopes.
override lazy val projectSettings: Seq[Setting[_]] =
Seq(
object autoImport {
val testReportsDirectory =
settingKey[File]("Directory for outputting junit test reports.").withRank(AMinusSetting)
lazy val testReportSettings: Seq[Setting[_]] = Seq(
testReportsDirectory := target.value / (prefix(configuration.value.name) + "reports"),
testListeners += new JUnitXmlTestsListener(
target.value.getAbsolutePath,
testReportsDirectory.value,
SysProp.legacyTestReport,
streams.value.log
)
)
}
import autoImport._
override lazy val projectSettings: Seq[Setting[_]] =
inConfig(Test)(testReportSettings) ++
inConfig(IntegrationTest)(testReportSettings)
}

View File

@ -0,0 +1,15 @@
[@ashleymercer]: https://github.com/ashleymercer
[#2853]: https://github.com/sbt/sbt/issues/2853
### Fixes with compatibility implications
- Add a new setting `testReportsDirectory` to allow output directory for JUnitXmlTestsListener to be configured,
and expose `testReportSettings` which provides defaults for new configurations [#2853][] by [@ashleymercer][]
- output directory now uses the configuration name as a prefix so `target/test-reports` for the `Test` configuration
but `target/it-reports` for the `IntegrationTest` configuration (previously this was hardcoded to always use
`target/test-reports`). To override this set e.g. `Test / testReportsDirectory := target.value / "my-custom-dir"`
- the `JunitXmlTestsListener` is now only attached to the `Test` and `IntegrationTest` configurations by default
(previously it was added to the global configuration object). Any configurations which inherit from one of these
will therefore continue to have the listener attached; but completely custom configurations will need to re-add
it with `.settings(testReportSettings)`

View File

@ -31,14 +31,20 @@ import sbt.protocol.testing.TestResult
/**
* A tests listener that outputs the results it receives in junit xml
* report format.
* @param outputDir path to the dir in which a folder with results is generated
* @param targetDir directory in which test reports are generated
*/
class JUnitXmlTestsListener(val outputDir: String, legacyTestReport: Boolean, logger: Logger)
class JUnitXmlTestsListener(val targetDir: File, legacyTestReport: Boolean, logger: Logger)
extends TestsListener {
// These constructors are for binary compatibility with older versions of sbt.
// These constructors are for binary compatibility with older versions of sbt
// Use old hard-coded behaviour for constructing `targetDir` from `outputDir`
def this(outputDir: String, legacyTestReport: Boolean, logger: Logger) =
this(new File(outputDir, "test-reports"), legacyTestReport, logger)
def this(outputDir: String, logger: Logger) = this(outputDir, false, logger)
def this(outputDir: String) = this(outputDir, false, null)
@deprecated("Provided for binary compatibility: please use `targetDir` instead", "1.6.0")
def outputDir: String = targetDir.getParent
/**Current hostname so we know which machine executed the tests*/
val hostname: String = {
val start = System.nanoTime
@ -57,9 +63,6 @@ class JUnitXmlTestsListener(val outputDir: String, legacyTestReport: Boolean, lo
name
}
/**The dir in which we put all result files. Is equal to the given dir + "/test-reports"*/
val targetDir = new File(outputDir + "/test-reports/")
/**all system properties as XML*/
val properties: Elem =
<properties>
@ -114,8 +117,8 @@ class JUnitXmlTestsListener(val outputDir: String, legacyTestReport: Boolean, lo
} skipped={ignoredSkippedPending + ""} time={(duration / 1000.0).toString} timestamp={
formatISO8601DateTime(timestamp)
}>
{properties}
{
{properties}
{
for (e <- events)
yield <testcase classname={
e.selector match {
@ -132,7 +135,7 @@ class JUnitXmlTestsListener(val outputDir: String, legacyTestReport: Boolean, lo
case other => s"(It is not a test it is a ${other.getClass.getCanonicalName})"
}
} time={(e.duration() / 1000.0).toString}>
{
{
val trace: String = if (e.throwable.isDefined) {
val stringWriter = new StringWriter()
val writer = new PrintWriter(stringWriter)
@ -157,12 +160,12 @@ class JUnitXmlTestsListener(val outputDir: String, legacyTestReport: Boolean, lo
case _ => {}
}
}
</testcase>
</testcase>
}
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>
<system-out><![CDATA[]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>
result
}