org.scalatest.Reporter.scala Maven / Gradle / Ivy
Show all versions of scalatest_2.11.0-M3 Show documentation
/*
* Copyright 2001-2008 Artima, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.scalatest
import org.scalatest.events.Event
/**
* Trait whose instances collect the results of a running
* suite of tests and presents those results in some way to the user. Instances of this trait can
* be called "report functions" or "reporters."
*
*
* Reporters receive test results via thirteen events.
* Each event is fired to pass a particular kind of information to
* the reporter. The events are:
*
*
*
* RunStarting
* TestStarting
* TestSucceeded
* TestFailed
* TestIgnored
* TestPending
* SuiteStarting
* SuiteCompleted
* SuiteAborted
* InfoProvided
* RunStopped
* RunAborted
* RunCompleted
*
*
*
* Reporters may be implemented such that they only present some of the reported events to the user. For example, you could
* define a reporter class that doesn nothing in response to SuiteStarting
events.
* Such a class would always ignore SuiteStarting
events.
*
*
*
* The term test as used in the TestStarting
, TestSucceeded
,
* and TestFailed
event names
* is defined abstractly to enable a wide range of test implementations.
* Trait Suite
fires TestStarting
to indicate it is about to invoke one
* of its test methods, TestSucceeded
to indicate a test method returned normally,
* and TestFailed
to indicate a test method completed abruptly with an exception.
* Although the execution of a Suite
's test methods will likely be a common event
* reported via the
* TestStarting
, TestSucceeded
, and TestFailed
methods, because
* of the abstract definition of “test” used by the
* the event classes, these events are not limited to this use. Information about any conceptual test
* may be reported via the TestStarting
, TestSucceeded
, and
* TestFailed
events.
*
*
* Likewise, the term suite as used in the SuiteStarting
, SuiteAborted
,
* and SuiteCompleted
event names
* is defined abstractly to enable a wide range of suite implementations.
* Object Runner
fires SuiteStarting
to indicate it is about to invoke
* run
on a
* Suite
, SuiteCompleted
to indicate a Suite
's
* run
method returned normally,
* and SuiteAborted
to indicate a Suite
's run
* method completed abruptly with an exception.
* Similarly, class Suite
fires SuiteStarting
to indicate it is about to invoke
* run
on a
* nested Suite
, SuiteCompleted
to indicate a nested Suite
's
* run
method returned normally,
* and SuiteAborted
to indicate a nested Suite
's run
* method completed abruptly with an exception.
* Although the execution of a Suite
's run
method will likely be a
* common event reported via the
* SuiteStarting
, SuiteAborted
, and SuiteCompleted
events, because
* of the abstract definition of "suite" used by the
* event classes, these events are not limited to this use. Information about any conceptual suite
* may be reported via the SuiteStarting
, SuiteAborted
, and
* SuiteCompleted
events.
*
*
Extensibility
*
*
* You can create classes that extend Reporter
to report test results in custom ways, and to
* report custom information passed as an event "payload." For more information on the latter
* use case, see the Extensibility section of the Event
documentation.
*
*
*
* Reporter
classes can handle events in any manner, including doing nothing.
*
*
* @author Bill Venners
*/
trait Reporter /* extends (Event => Unit) */ {
/**
* Invoked to report an event that subclasses may wish to report in some way to the user.
*
* @param event the event being reported
*/
def apply(event: Event)
/*
* Release any non-memory finite resources, such as file handles, held by this Reporter
. Clients should
* call this method when they no longer need the Reporter
, before releasing the last reference
* to the Reporter
. After this method is invoked, the Reporter
may be defunct,
* and therefore not usable anymore. If the Reporter
holds no resources, it may do nothing when
* this method is invoked. This trait's implementation of this method does nothing, so that Reporter
* subclasses that hold no non-memory, finite resources can simply inherit this trait's implementation.
def dispose() = ()
*/
}
/**
* Companion object to Reporter that holds a deprecated implicit conversion.
*/
object Reporter {
/**
* Converts a Reporter
to a function type that prior to the ScalaTest 1.5 release the
* Reporter
extended.
*
*
* Prior to ScalaTest 1.5, Reporter
extended function type (Event) => Unit
.
* This inheritance relationship was severed in 1.5 to make it possible to implement Reporter
s in Java, a request by an IDE
* vendor to isolate their ScalaTest integration from binary incompatibility between different Scala/ScalaTest releases.
* To make a trait easily implementable in Java, it needs to have no concrete methods. Reporter
itself does not declare
* any concrete methods, but Function1
does.
*
*
*
* This implicit conversion was added in ScalaTest 1.5 to avoid breaking any source code that was actually using
* Reporter
as an (Event) => Unit
function. It is unlikely anyone was actually doing that, but if you were
* and now get the deprecation warning, please email [email protected] if you believe this implicit conversion should
* be retained. If no one steps forward with a compelling justification, it will be removed in a future version of ScalaTest.
*
*/
@deprecated("See the documentation for Reporter.convertReporterToFunction for information")
implicit def convertReporterToFunction(repo: Reporter): (Event) => Unit =
(e: Event) => repo(e)
private[scalatest] def indentStackTrace(stackTrace: String, level: Int): String = {
val indentation = if (level > 0) " " * level else ""
val withTabsZapped = stackTrace.replaceAll("\t", " ")
val withInitialIndent = indentation + withTabsZapped
withInitialIndent.replaceAll("\n", "\n" + indentation) // I wonder if I need to worry about alternate line endings. Probably.
}
// In the unlikely event that a message is blank, use the throwable's detail message
private[scalatest] def messageOrThrowablesDetailMessage(message: String, throwable: Option[Throwable]): String = {
val trimmedMessage = message.trim
if (!trimmedMessage.isEmpty)
trimmedMessage
else
throwable match {
case Some(t) => t.getMessage.trim
case None => ""
}
}
private[scalatest] def messageToPrint(resourceName: String, message: String, throwable: Option[Throwable], suiteName: Option[String],
testName: Option[String]): String = {
val arg =
suiteName match {
case Some(sn) =>
testName match {
case Some(tn) => sn + ": " + tn
case None => sn
}
case None => ""
}
val msgToPrint = messageOrThrowablesDetailMessage(message, throwable)
if (msgToPrint.isEmpty)
Resources(resourceName + "NoMessage", arg)
else
if (resourceName == "runAborted")
Resources(resourceName, msgToPrint)
else
Resources(resourceName, arg, msgToPrint)
}
}
/*
case RunStarting(ordinal, testCount, formatter, payload, threadName, timeStamp) => runStarting(testCount)
case TestStarting(ordinal, suiteName, suiteClassName, testName, formatter, rerunnable, payload, threadName, timeStamp) =>
case TestSucceeded(ordinal, suiteName, suiteClassName, testName, duration, formatter, rerunnable, payload, threadName, timeStamp) =>
case TestFailed(ordinal, message, suiteName, suiteClassName, testName, throwable, duration, formatter, rerunnable, payload, threadName, timeStamp) =>
case TestIgnored(ordinal, suiteName, suiteClassName, testName, formatter, payload, threadName, timeStamp) =>
case TestPending(ordinal, suiteName, suiteClassName, testName, formatter, payload, threadName, timeStamp) =>
case SuiteStarting(ordinal, suiteName, suiteClassName, formatter, rerunnable, payload, threadName, timeStamp) =>
case SuiteCompleted(ordinal, suiteName, suiteClassName, duration, formatter, rerunnable, payload, threadName, timeStamp) =>
case SuiteAborted(ordinal, message, suiteName, suiteClassName, throwable, duration, formatter, rerunnable, payload, threadName, timeStamp) =>
case InfoProvided(ordinal, message, nameInfo, throwable, formatter, payload, threadName, timeStamp) => {
case RunStopped(ordinal, duration, summary, formatter, payload, threadName, timeStamp) => runStopped()
case RunAborted(ordinal, message, throwable, duration, summary, formatter, payload, threadName, timeStamp) =>
case RunCompleted(ordinal, duration, summary, formatter, payload, threadName, timeStamp) => runCompleted()
*/