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

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

The newest version!
package org.specs2
package reporter

import execute._
import specification._
import Levels._
import org.specs2.internal.scalaz.{Tree, Scalaz}
import data.Trees._
import main.Arguments

/**
 * Report a Specification by notifying execution events to a Notifier
 */
trait NotifierReporter extends DefaultReporter with NotifierExporting

trait NotifierExporting extends Exporting with Exporters {

  val notifier: Notifier
  /** @return a function exporting ExecutedFragments */
  def export(implicit args: Arguments): ExecutingSpecification => ExecutedSpecification = (spec: ExecutingSpecification) => {
    val executed = spec.execute
    notifyExport(executed.fragments)
    executed
  }

  private def notifyExport(fs: Seq[ExecutedFragment])(implicit args: Arguments) = {
    def notify(fs: Seq[ExecutedFragment]) = {
      val tree = Levels.foldAll(fs).toTree(mapper)
      if (args.noindent) export(tree.flattenSubForests)
      else               export(tree)
    }

    if (fs.nonEmpty) notify(fs)
    else {             
      val empty = Fragments().specTitleIs(SpecName("empty specification"))
      Seq(ExecutedSpecStart(empty.specStart), ExecutedSpecEnd(empty.specEnd))
    }

  }

  private val mapper = (f: ExecutedFragment, i: Int) => f match {
    case e: ExecutedStandardFragment => None
    case other                       => Some(other)
  }

  private def export(tree: Tree[ExecutedFragment])(implicit args: Arguments) {
    tree.rootLabel match {
      case f @ ExecutedSpecStart(_,_,_)                                      => {
        notifier.specStart(f.name, f.location.toString)
        tree.subForest.foreach(export)
      }
      case f @ ExecutedSpecEnd(_,_,_)                                        => {
        notifier.specEnd(f.name, f.location.toString)
      }
      case f @ ExecutedText(t, _)  if tree.subForest.isEmpty && !args.xonly => notifier.text(t, f.location.toString)
      case f @ ExecutedText(t, _)                                           => {
        notifier.contextStart(t, f.location.toString)
        tree.subForest.foreach(export)
        notifier.contextEnd(t, f.location.toString)
      }
      case f @ ExecutedResult(s, r, t, l, st)                               => {
        notifier.exampleStarted(s.toString, l.toString)
        def notifyResult(result: Result) {
          result match {
            case Success(_,_)            if !args.xonly    => notifier.exampleSuccess(s.toString, t.totalMillis)
            case fail @ Failure(_,_,_,_)                   => notifier.exampleFailure(s.toString, args.removeColors(fail.message),
                                                                                    fail.location, args.traceFilter(fail.exception), fail.details, t.totalMillis)
            case err  @ Error(_,_)                         => notifier.exampleError(s.toString, args.removeColors(err.message), err.location,
                                                                                   args.traceFilter(err.exception), t.totalMillis)
            case Skipped(_,_)            if !args.xonly    => notifier.exampleSkipped(s.toString, args.removeColors(r.message), t.totalMillis)
            case Pending(_)              if !args.xonly    => notifier.examplePending(s.toString, args.removeColors(r.message), t.totalMillis)
            case DecoratedResult(t, res)                   => notifyResult(res)
            case Success(_,_) | Skipped(_, _) | Pending(_) => ()
          }
        }
        notifyResult(r)
      }
      case other                           => tree.subForest.foreach(export)
    }
  }
}

/**
 * This trait can be used for any event concerning the execution of examples
 * seen as a Tree of Fragments.
 *
 * A pair of contextStart/contextEnd calls delimits a sequence of children in that tree.
 */
trait Notifier {
  def specStart(title: String, location: String)
  def specEnd(title: String, location: String)
  def contextStart(text: String, location: String)
  def contextEnd(text: String, location: String)
  def text(text: String, location: String)
  def exampleStarted(name: String, location: String)
  def exampleSuccess(name: String, duration: Long)
  def exampleFailure(name: String, message: String, location: String, f: Throwable, details: Details, duration: Long)
  def exampleError  (name: String, message: String, location: String, f: Throwable, duration: Long)
  def exampleSkipped(name: String, message: String, duration: Long)
  def examplePending(name: String, message: String, duration: Long)
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy