// ****************************************************************
// This is free software licensed under the NUnit license. You
// may obtain a copy of the license as well as information regarding
// copyright ownership at http://nunit.org/?p=license&r=2.4.
// ****************************************************************
namespace NUnit.Core
{
using System;
using System.Text;
///
/// The TestResult abstract class represents
/// the result of a test and is used to
/// communicate results across AppDomains.
///
///
[Serializable]
public abstract class TestResult
{
#region Fields
///
/// Indicates whether the test was executed or not
///
private RunState runState;
///
/// Indicates the result of the test
///
private ResultState resultState;
///
/// Indicates the location of a failure
///
private FailureSite failureSite;
///
/// The elapsed time for executing this test
///
private double time = 0.0;
///
/// The name of the test
///
private string name;
///
/// The test that this result pertains to
///
private TestInfo test;
///
/// The stacktrace at the point of failure
///
private string stackTrace;
///
/// Description of this test
///
private string description;
///
/// Message giving the reason for failure
///
protected string messageString;
///
/// Number of asserts executed by this test
///
private int assertCount = 0;
#endregion
#region Protected Constructor
///
/// Protected constructor constructs a test result given
/// a test and a name.
///
/// The test to be used
/// Name for this result
protected TestResult(TestInfo test, string name)
{
this.name = name;
this.test = test;
this.RunState = RunState.Runnable;
if (test != null)
{
this.description = test.Description;
this.runState = test.RunState;
this.messageString = test.IgnoreReason;
}
}
#endregion
#region Properties
///
/// Gets the RunState of the result, which indicates
/// whether or not it has executed and why.
///
public RunState RunState
{
get { return runState; }
set { runState = value; }
}
///
/// Gets the ResultState of the test result, which
/// indicates the success or failure of the test.
///
public ResultState ResultState
{
get { return resultState; }
}
///
/// Gets the stage of the test in which a failure
/// or error occured.
///
public FailureSite FailureSite
{
get { return failureSite; }
}
///
/// Indicates whether the test executed
///
public bool Executed
{
get { return runState == RunState.Executed; }
}
///
/// Gets the name of the test result
///
public virtual string Name
{
get { return name; }
}
///
/// Gets the test associated with this result
///
public ITest Test
{
get { return test; }
}
///
/// Indicates whether the test ran successfully
///
public virtual bool IsSuccess
{
// TODO: Redefine this more precisely
get { return !IsFailure; }
//get { return resultState == ResultState.Success; }
}
///
/// Indicates whether the test failed
///
// TODO: Distinguish errors from failures
public virtual bool IsFailure
{
get { return resultState == ResultState.Failure || resultState == ResultState.Error; }
}
///
/// Gets a description associated with the test
///
public virtual string Description
{
get { return description; }
set { description = value; }
}
///
/// Gets the elapsed time for running the test
///
public double Time
{
get { return time; }
set { time = value; }
}
///
/// Gets the message associated with a test
/// failure or with not running the test
///
public string Message
{
get { return messageString; }
}
///
/// Gets any stacktrace associated with an
/// error or failure.
///
public virtual string StackTrace
{
get
{
return stackTrace;
}
set
{
stackTrace = value;
}
}
///
/// Gets or sets the count of asserts executed
/// when running the test.
///
public int AssertCount
{
get { return assertCount; }
set { assertCount = value; }
}
#endregion
#region Public Methods
///
/// Mark the test as succeeding
///
public void Success()
{
this.runState = RunState.Executed;
this.resultState = ResultState.Success;
}
///
/// Mark the test as ignored.
///
/// The reason the test was not run
public void Ignore(string reason)
{
Ignore( reason, null );
}
///
/// Mark the test as ignored.
///
/// The ignore exception that was thrown
public void Ignore( Exception ex )
{
Ignore( ex.Message, BuildStackTrace( ex ) );
}
///
/// Mark the test as ignored.
///
/// The reason the test was not run
/// Stack trace giving the location of the command
public void Ignore(string reason, string stackTrace)
{
NotRun( RunState.Ignored, reason, stackTrace );
}
///
/// Mark the test as skipped.
///
/// The reason the test was not run
public void Skip(string reason)
{
Skip( reason, null );
}
///
/// Mark the test as ignored.
///
/// The ignore exception that was thrown
public void Skip( Exception ex )
{
Skip( ex.Message, BuildStackTrace( ex ) );
}
///
/// Mark the test as skipped.
///
/// The reason the test was not run
/// Stack trace giving the location of the command
public void Skip(string reason, string stackTrace)
{
NotRun( RunState.Skipped, reason, stackTrace );
}
///
/// Mark the test as Not Run - either skipped or ignored
///
/// The RunState to use in the result
/// The reason the test was not run
/// Stack trace giving the location of the command
public void NotRun(RunState runState, string reason, string stackTrace)
{
this.runState = runState;
this.messageString = reason;
this.stackTrace = stackTrace;
}
///
/// Mark the test as a failure due to an
/// assertion having failed.
///
/// Message to display
/// Stack trace giving the location of the failure
public void Failure(string message, string stackTrace)
{
Failure(message, stackTrace, FailureSite.Test);
}
///
/// Mark the test as a failure due to an
/// assertion having failed.
///
/// Message to display
/// Stack trace giving the location of the failure
/// The site of the failure
public void Failure(string message, string stackTrace, FailureSite failureSite )
{
this.runState = RunState.Executed;
this.resultState = ResultState.Failure;
this.failureSite = failureSite;
this.messageString = message;
this.stackTrace = stackTrace;
}
///
/// Marks the result as an error due to an exception thrown
/// by the test.
///
/// The exception that was caught
public void Error(Exception exception)
{
Error(exception, FailureSite.Test);
}
///
/// Marks the result as an error due to an exception thrown
/// from the indicated FailureSite.
///
/// The exception that was caught
/// The site from which it was thrown
public void Error( Exception exception, FailureSite failureSite )
{
this.runState = RunState.Executed;
this.resultState = ResultState.Error;
this.failureSite = failureSite;
string message = BuildMessage(exception);
string stackTrace = BuildStackTrace(exception);
if (failureSite == FailureSite.TearDown)
{
message = "TearDown : " + message;
stackTrace = "--TearDown" + Environment.NewLine + stackTrace;
if (this.messageString != null)
message = this.messageString + Environment.NewLine + message;
if (this.stackTrace != null)
stackTrace = this.stackTrace + Environment.NewLine + stackTrace;
}
this.messageString = message;
this.stackTrace = stackTrace;
}
#endregion
#region Exception Helpers
private string BuildMessage(Exception exception)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat( "{0} : {1}", exception.GetType().ToString(), exception.Message );
Exception inner = exception.InnerException;
while( inner != null )
{
sb.Append( Environment.NewLine );
sb.AppendFormat( " ----> {0} : {1}", inner.GetType().ToString(), inner.Message );
inner = inner.InnerException;
}
return sb.ToString();
}
private string BuildStackTrace(Exception exception)
{
StringBuilder sb = new StringBuilder( GetStackTrace( exception ) );
Exception inner = exception.InnerException;
while( inner != null )
{
sb.Append( Environment.NewLine );
sb.Append( "--" );
sb.Append( inner.GetType().Name );
sb.Append( Environment.NewLine );
sb.Append( GetStackTrace( inner ) );
inner = inner.InnerException;
}
return sb.ToString();
}
private string GetStackTrace(Exception exception)
{
try
{
return exception.StackTrace;
}
catch( Exception )
{
return "No stack trace available";
}
}
#endregion
///
/// Abstract method that accepts a ResultVisitor
///
/// The visitor
public abstract void Accept(ResultVisitor visitor);
}
}