TestResult
The TestResult class represents the result of a test.
using NUnit.Compatibility;
using NUnit.Framework.Interfaces;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
namespace NUnit.Framework.Internal
{
public abstract class TestResult : LongLivedMarshalByRefObject, ITestResult, IXmlNodeBuilder
{
internal static readonly string CHILD_ERRORS_MESSAGE = "One or more child tests had errors";
internal static readonly string CHILD_WARNINGS_MESSAGE = "One or more child tests had warnings";
internal static readonly string CHILD_IGNORE_MESSAGE = "One or more child tests were ignored";
internal const double MIN_DURATION = 1E-06;
private StringBuilder _output = new StringBuilder();
private double _duration;
protected int InternalAssertCount;
private ResultState _resultState;
private string _message;
private string _stackTrace;
private readonly List<AssertionResult> _assertionResults = new List<AssertionResult>();
private readonly List<TestAttachment> _testAttachments = new List<TestAttachment>();
protected ReaderWriterLockSlim RwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
public ITest Test { get; set; }
public ResultState ResultState {
get {
RwLock.EnterReadLock();
try {
return _resultState;
} finally {
RwLock.ExitReadLock();
}
}
private set {
_resultState = value;
}
}
public virtual string Name => Test.Name;
public virtual string FullName => Test.FullName;
public double Duration {
get {
return _duration;
}
set {
_duration = ((value >= 1E-06) ? value : 1E-06);
}
}
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public ICollection<TestAttachment> TestAttachments => new ReadOnlyCollection<TestAttachment>(_testAttachments);
public string Message {
get {
RwLock.EnterReadLock();
try {
return _message;
} finally {
RwLock.ExitReadLock();
}
}
private set {
_message = value;
}
}
public virtual string StackTrace {
get {
RwLock.EnterReadLock();
try {
return _stackTrace;
} finally {
RwLock.ExitReadLock();
}
}
private set {
_stackTrace = value;
}
}
public int AssertCount {
get {
RwLock.EnterReadLock();
try {
return InternalAssertCount;
} finally {
RwLock.ExitReadLock();
}
}
internal set {
InternalAssertCount = value;
}
}
public abstract int FailCount { get; }
public abstract int WarningCount { get; }
public abstract int PassCount { get; }
public abstract int SkipCount { get; }
public abstract int InconclusiveCount { get; }
public abstract bool HasChildren { get; }
public abstract IEnumerable<ITestResult> Children { get; }
public TextWriter OutWriter { get; set; }
public string Output => _output.ToString();
public IList<AssertionResult> AssertionResults => _assertionResults;
public int PendingFailures => AssertionResults.Count((AssertionResult ar) => ar.Status == AssertionStatus.Failed);
public AssertionStatus WorstAssertionStatus => AssertionResults.Aggregate(delegate(AssertionResult ar1, AssertionResult ar2) {
if (ar1.Status <= ar2.Status)
return ar2;
return ar1;
}).Status;
public TestResult(ITest test)
{
Test = test;
ResultState = ResultState.Inconclusive;
OutWriter = TextWriter.Synchronized(new StringWriter(_output));
}
internal void AddTestAttachment(TestAttachment attachment)
{
_testAttachments.Add(attachment);
}
public TNode ToXml(bool recursive)
{
return AddToXml(new TNode("dummy"), recursive);
}
public virtual TNode AddToXml(TNode parentNode, bool recursive)
{
TNode tNode = Test.AddToXml(parentNode, false);
TNode tNode2 = tNode;
TestStatus status = ResultState.Status;
tNode2.AddAttribute("result", status.ToString());
if (ResultState.Label != string.Empty)
tNode.AddAttribute("label", ResultState.Label);
if (ResultState.Site != 0)
tNode.AddAttribute("site", ResultState.Site.ToString());
TNode tNode3 = tNode;
DateTime dateTime = StartTime;
tNode3.AddAttribute("start-time", dateTime.ToString("u"));
TNode tNode4 = tNode;
dateTime = EndTime;
tNode4.AddAttribute("end-time", dateTime.ToString("u"));
tNode.AddAttribute("duration", Duration.ToString("0.000000", NumberFormatInfo.InvariantInfo));
int num;
if (Test is TestSuite) {
TNode tNode5 = tNode;
num = PassCount + FailCount + SkipCount + InconclusiveCount;
tNode5.AddAttribute("total", num.ToString());
TNode tNode6 = tNode;
num = PassCount;
tNode6.AddAttribute("passed", num.ToString());
TNode tNode7 = tNode;
num = FailCount;
tNode7.AddAttribute("failed", num.ToString());
TNode tNode8 = tNode;
num = WarningCount;
tNode8.AddAttribute("warnings", num.ToString());
TNode tNode9 = tNode;
num = InconclusiveCount;
tNode9.AddAttribute("inconclusive", num.ToString());
TNode tNode10 = tNode;
num = SkipCount;
tNode10.AddAttribute("skipped", num.ToString());
}
TNode tNode11 = tNode;
num = AssertCount;
tNode11.AddAttribute("asserts", num.ToString());
status = ResultState.Status;
if ((uint)status > 3) {
if (status == TestStatus.Failed)
AddFailureElement(tNode);
} else if (Message != null && Message.Trim().Length > 0) {
AddReasonElement(tNode);
}
if (Output.Length > 0)
AddOutputElement(tNode);
if (AssertionResults.Count > 0)
AddAssertionsElement(tNode);
if (_testAttachments.Count > 0)
AddAttachmentsElement(tNode);
if (recursive && HasChildren) {
foreach (TestResult child in Children) {
child.AddToXml(tNode, recursive);
}
return tNode;
}
return tNode;
}
public void SetResult(ResultState resultState)
{
SetResult(resultState, null, null);
}
public void SetResult(ResultState resultState, string message)
{
SetResult(resultState, message, null);
}
public void SetResult(ResultState resultState, string message, string stackTrace)
{
RwLock.EnterWriteLock();
try {
ResultState = resultState;
Message = message;
StackTrace = stackTrace;
} finally {
RwLock.ExitWriteLock();
}
}
public void RecordException(Exception ex)
{
if (ex is NUnitException || ex is TargetInvocationException)
ex = ex.InnerException;
if (ex is ResultStateException)
SetResult(((ResultStateException)ex).ResultState, ex.Message, StackFilter.DefaultFilter.Filter(ex.StackTrace));
else if (ex is ThreadAbortException) {
SetResult(ResultState.Cancelled, "Test cancelled by user", ex.StackTrace);
} else {
string message = ExceptionHelper.BuildMessage(ex, false);
string stackTrace = ExceptionHelper.BuildStackTrace(ex);
SetResult(ResultState.Error, message, stackTrace);
if (AssertionResults.Count > 0) {
Message += CreateLegacyFailureMessage();
AssertionResults.Add(new AssertionResult(AssertionStatus.Error, message, stackTrace));
}
}
}
public void RecordException(Exception ex, FailureSite site)
{
if (ex is NUnitException)
ex = ex.InnerException;
if (ex is ResultStateException)
SetResult(((ResultStateException)ex).ResultState.WithSite(site), ex.Message, StackFilter.DefaultFilter.Filter(ex.StackTrace));
else if (ex is ThreadAbortException) {
SetResult(ResultState.Cancelled.WithSite(site), "Test cancelled by user", ex.StackTrace);
} else {
SetResult(ResultState.Error.WithSite(site), ExceptionHelper.BuildMessage(ex, false), ExceptionHelper.BuildStackTrace(ex));
}
}
public void RecordTearDownException(Exception ex)
{
if (ex is NUnitException)
ex = ex.InnerException;
ResultState resultState = (ResultState == ResultState.Cancelled) ? ResultState.Cancelled : ResultState.Error;
if (Test.IsSuite)
resultState = resultState.WithSite(FailureSite.TearDown);
string text = "TearDown : " + ExceptionHelper.BuildMessage(ex, false);
if (Message != null)
text = Message + Environment.NewLine + text;
string text2 = "--TearDown" + Environment.NewLine + ExceptionHelper.BuildStackTrace(ex);
if (StackTrace != null)
text2 = StackTrace + Environment.NewLine + text2;
SetResult(resultState, text, text2);
}
public void RecordTestCompletion()
{
switch (AssertionResults.Count) {
case 0:
SetResult(ResultState.Success);
break;
case 1:
SetResult(AssertionStatusToResultState(AssertionResults[0].Status), AssertionResults[0].Message, AssertionResults[0].StackTrace);
break;
default:
SetResult(AssertionStatusToResultState(WorstAssertionStatus), CreateLegacyFailureMessage());
break;
}
}
public void RecordAssertion(AssertionResult assertion)
{
_assertionResults.Add(assertion);
}
public void RecordAssertion(AssertionStatus status, string message, string stackTrace)
{
RecordAssertion(new AssertionResult(status, message, stackTrace));
}
public void RecordAssertion(AssertionStatus status, string message)
{
RecordAssertion(status, message, null);
}
private string CreateLegacyFailureMessage()
{
StringWriter stringWriter = new StringWriter();
if (AssertionResults.Count > 1)
stringWriter.WriteLine("Multiple failures or warnings in test:");
int num = 0;
foreach (AssertionResult assertionResult in AssertionResults) {
stringWriter.WriteLine($"""{++num}""{assertionResult.Message}");
}
return stringWriter.ToString();
}
private TNode AddReasonElement(TNode targetNode)
{
return targetNode.AddElement("reason").AddElementWithCDATA("message", Message);
}
private TNode AddFailureElement(TNode targetNode)
{
TNode tNode = targetNode.AddElement("failure");
if (Message != null && Message.Trim().Length > 0)
tNode.AddElementWithCDATA("message", Message);
if (StackTrace != null && StackTrace.Trim().Length > 0)
tNode.AddElementWithCDATA("stack-trace", StackTrace);
return tNode;
}
private TNode AddOutputElement(TNode targetNode)
{
return targetNode.AddElementWithCDATA("output", Output);
}
private TNode AddAssertionsElement(TNode targetNode)
{
TNode tNode = targetNode.AddElement("assertions");
foreach (AssertionResult assertionResult in AssertionResults) {
TNode tNode2 = tNode.AddElement("assertion");
tNode2.AddAttribute("result", assertionResult.Status.ToString());
if (assertionResult.Message != null)
tNode2.AddElementWithCDATA("message", assertionResult.Message);
if (assertionResult.StackTrace != null)
tNode2.AddElementWithCDATA("stack-trace", assertionResult.StackTrace);
}
return tNode;
}
private ResultState AssertionStatusToResultState(AssertionStatus status)
{
switch (status) {
case AssertionStatus.Inconclusive:
return ResultState.Inconclusive;
default:
return ResultState.Success;
case AssertionStatus.Warning:
return ResultState.Warning;
case AssertionStatus.Failed:
return ResultState.Failure;
case AssertionStatus.Error:
return ResultState.Error;
}
}
private TNode AddAttachmentsElement(TNode targetNode)
{
TNode tNode = targetNode.AddElement("attachments");
foreach (TestAttachment testAttachment in _testAttachments) {
TNode tNode2 = tNode.AddElement("attachment");
tNode2.AddElement("filePath", testAttachment.FilePath);
if (testAttachment.Description != null)
tNode2.AddElementWithCDATA("description", testAttachment.Description);
}
return tNode;
}
}
}