All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.specs2.reporter.JUnitXmlPrinter.scala Maven / Gradle / Ivy

There is a newer version: 4.10.6
Show newest version
package org.specs2
package reporter

import org.junit.runner.Description
import java.net.InetAddress

import main.Arguments
import execute._
import io.FileName
import control._
import Actions._
import io._

import scala.collection.JavaConverters._
import Exceptions._
import specification.core._
import specification.process._
import text.NotNullStrings._
import JUnitDescriptions._
import org.specs2.concurrent.ExecutionEnv
import origami._

/**
 * The JUnitXmlPrinter creates an xml file with the specification execution results
 */
trait JUnitXmlPrinter extends Printer {
  def prepare(env: Env, specs: List[SpecStructure]): Action[Unit]  = Actions.unit
  def finalize(env: Env, specs: List[SpecStructure]): Action[Unit] = Actions.unit

  def sink(env: Env, spec: SpecStructure): AsyncSink[Fragment] =
    (Statistics.fold zip fold.list[Fragment].into[Action]).
      mapFlatten(saveResults(env, spec))

  def saveResults(env: Env, spec: SpecStructure): ((Stats, List[Fragment])) =>  Action[Unit] = { case (stats, fs) =>
    descriptionFold(spec, stats, env).run(descriptions(spec, fs)(env.specs2ExecutionEnv).toList).flatMap { suite =>
       env.fileSystem.writeFile(outputDirectory(env.arguments) | FileName.unsafe(spec.specClassName+".xml"), suite.xml)
    }
  }

  def descriptionFold(spec: SpecStructure, stats: Stats, env: Env): AsyncFold[(Fragment, Description), TestSuite] = {
    val suite = TestSuite(specDescription(spec), spec.specClassName, stats.errors, stats.failures, stats.skipped, stats.timer.totalMillis)
    fold.fromFoldLeft[Action, (Fragment, Description), TestSuite](suite) { case (res, (f, d)) =>
      if (Fragment.isExample(f))
        f.executedResult.map { case ExecutedResult(result, timer) =>
          res.addTest(new TestCase(d, result, timer.totalMillis)(env.arguments))
        }
      else ok(res)
    }
  }

  def descriptions(spec: SpecStructure, fragments: List[Fragment])(ee: ExecutionEnv) =
    JUnitDescriptions.fragmentDescriptions(spec.setFragments(Fragments(fragments:_*)))(ee)

  def outputDirectory(arguments: Arguments): DirectoryPath =
    arguments.commandLine.directoryOr("junit.outdir", "target" / "test-reports")

  case class TestSuite(description: Description, className: String, errors: Int, failures: Int, skipped: Int, time: Long = 0, tests: Seq[TestCase] = Seq()) {
    def addTest(t: TestCase) = copy(tests = tests :+ t)

    def xml =
      s"""|
          |
          |  $properties
          |  ${tests.map(_.xml).mkString("\n")}
          |  
          |  
          |""".stripMargin

    /**
     * output properties
     */
    def properties =
      s"""
            ${System.getProperties.entrySet.asScala.toSeq.map(p => s"""""").mkString("\n")}
          """
  }

  case class TestCase(desc: Description, result: Result, time: Long)(implicit args: Arguments) {
    def xml =
      s"""
            $testError$testFailure$testSkipped$testPending
          """

    def testError = result match {
      case er @ Error(m, e) => s"""${escape(args.traceFilter(er.stackTrace).mkString("\n"))}"""
      case _ => ""
    }

    def testFailure = result match {
      case f @ Failure(m, e, st, d) => s"""${escape(args.traceFilter(st).mkString("\n"))}"""
      case _ => ""
    }

    def testPending = result match {
      case Pending(m) => ""
      case _ => ""
    }

    def testSkipped = result match {
      case Skipped(m, e) => """"""
      case _ => ""
    }
  }

  private def escape(s: =>String): String =
    scala.xml.Utility.escape(s.notNull)

  private def formatTime(t: Long) = "%.3f" format (t / 1000.0)
}

object JUnitXmlPrinter extends JUnitXmlPrinter




© 2015 - 2024 Weber Informatics LLC | Privacy Policy