JMK
JMK

Reputation: 239

How to add scalatest tags to a report?

My scalatest tests use tagging functionality and look like the following:

"A test" should "test something" taggedAs (Smoke) in {
 ....
}

Is there a chance to add tags to junit report which is generated using -u option from scalatest runner?

Was trying to look everywhere but couldn't find any answer except how to disable/enable tests based on these Tags objects.

Upvotes: 5

Views: 1221

Answers (1)

Mario Galic
Mario Galic

Reputation: 48420

scalatest-custom-reporter-example is a working example showing how to create custom Reporter and pass tags as custom information to the reporter.

JUnitXmlReporter generates report in JUnit's XML format when configured via -u argument:

Test / testOptions += Tests.Argument("-u", "target")

Given the following test:

class HelloSpec extends FlatSpec with Matchers  {

 object Slow extends Tag("Slow")
 object Unreliable extends Tag("Unreliable")

 "The Hello object" should "say hello" taggedAs (Slow) in {
   assert(true)
 }

 it should "sing lullaby" taggedAs (Unreliable, Slow) in {
   assert(true)
 }
}

by default, JUnitXmlReporter.xmlify outputs the following string:

...
  <testcase 
    name="The Hello object should say hello" classname="example.HelloSpec" time="0.011">
  </testcase>
  <testcase 
    name="The Hello object should sing lullaby" classname="example.HelloSpec" time="0.001">
  </testcase>
...

while we would like to add test's tags to the report like so:

...
  <testcase 
    name="The Hello object should say hello" tag="Set(Slow)" classname="example.HelloSpec" time="0.011">
  </testcase>
  <testcase 
    name="The Hello object should sing lullaby" tag="Set(Unreliable, Slow)" classname="example.HelloSpec" time="0.001">
</testcase>
...

How to create custom reporter?

  1. Create custom reporter by extending JUnitXmlReporter:

    package org.scalatest.tools
    class JUnitReporterWithTags extends JUnitXmlReporter("target")
    
  2. Add member map to hold suite's tags by test name:

    private var tags: Map[String, Set[String]] = Map.empty
    
  3. Override xmlify to inject the tags in the output string:

      override def xmlify(testsuite: Testsuite): String = {
        var xml = super.xmlify(testsuite)
        for (testcase <- testsuite.testcases) yield {
          xml = xml.replace(s""""${testcase.name}"""", s""""${testcase.name}" tag="${tags(testcase.name)}"""" )
        }
        xml
      }
    
    

How to pass suite's tags as custom information to the reporter?

  1. Mixin BeforeAndAfterAll trait in the test:
    class HelloSpec extends FlatSpec with Matchers with BeforeAndAfterAll {
    
  2. Piggyback Suite.tags as payload argument of InfoProvided event which gets passed to reporter via Informer:
    override def beforeAll(): Unit = {
        info("", Some(tags))
      }
    
  3. Override JUnitXmlReporter.apply to extract and store tags payload:

      override def apply(event: Event): Unit = {
        super.apply(event)
        event match {
          case e: InfoProvided =>
            e.payload.foreach { providedTags =>
              tags ++= providedTags.asInstanceOf[Map[String, Set[String]]]
            }
    
          case _ =>
        }
      }
    

How to configure SBT to produce the report via custom reporter?

  1. Give fully qualified name of custom reporter JUnitReporterWithTags to -C argument:
    Test / testOptions += Tests.Argument("-C", "org.scalatest.tools.JUnitReporterWithTags")
    
  2. Produce the report with sbt test
  3. Report should be created at target/TEST-example.HelloSpec.xml

Upvotes: 6

Related Questions