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.Runtime.CompilerServices;
using System.Text;
using System.Threading;
namespace NUnit.Framework.Internal
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class TestResult : LongLivedMarshalByRefObject, ITestResult, IXmlNodeBuilder
{
[System.Runtime.CompilerServices.Nullable(0)]
private struct ExceptionResult
{
public ResultState ResultState {
[IsReadOnly]
get;
}
public string Message {
[IsReadOnly]
get;
}
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public string StackTrace {
[IsReadOnly]
[System.Runtime.CompilerServices.NullableContext(2)]
get;
}
public ExceptionResult(Exception ex, FailureSite site)
{
ex = ValidateAndUnwrap(ex);
ResultStateException ex2 = ex as ResultStateException;
if (ex2 != null) {
ResultState = ex2.ResultState.WithSite(site);
Message = ex.GetMessageWithoutThrowing();
StackTrace = StackFilter.DefaultFilter.Filter(ex.GetStackTraceWithoutThrowing());
} else if (ex is OperationCanceledException && TestExecutionContext.CurrentContext.CancellationToken.IsCancellationRequested) {
ResultState = ResultState.Failure.WithSite(site);
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(37, 1);
defaultInterpolatedStringHandler.AppendLiteral("Test exceeded CancelAfter value of ");
defaultInterpolatedStringHandler.AppendFormatted(TestExecutionContext.CurrentContext.TestCaseTimeout);
defaultInterpolatedStringHandler.AppendLiteral("ms");
Message = defaultInterpolatedStringHandler.ToStringAndClear();
StackTrace = ExceptionHelper.BuildStackTrace(ex);
} else {
ResultState = ResultState.Error.WithSite(site);
Message = ExceptionHelper.BuildMessage(ex, false);
StackTrace = ExceptionHelper.BuildStackTrace(ex);
}
}
}
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 string USER_CANCELLED_MESSAGE = "Test run cancelled by user";
internal const double MIN_DURATION = 1E-06;
private readonly StringBuilder _output = new StringBuilder();
private double _duration;
protected int InternalAssertCount;
private ResultState _resultState;
private string _message;
[System.Runtime.CompilerServices.Nullable(2)]
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; }
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;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public virtual string StackTrace {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
RwLock.EnterReadLock();
try {
return _stackTrace;
} finally {
RwLock.ExitReadLock();
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
private set {
_stackTrace = value;
}
}
public int AssertCount {
get {
RwLock.EnterReadLock();
try {
return InternalAssertCount;
} finally {
RwLock.ExitReadLock();
}
}
internal set {
InternalAssertCount = value;
}
}
public abstract int TotalCount { get; }
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; }
public string Output {
get {
lock (OutWriter) {
return _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;
_message = string.Empty;
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.AddAttribute("result", ResultState.Status.ToString());
if (ResultState.Label != string.Empty)
tNode.AddAttribute("label", ResultState.Label);
if (ResultState.Site != 0)
tNode.AddAttribute("site", ResultState.Site.ToString());
TNode tNode2 = tNode;
DateTime dateTime = StartTime;
tNode2.AddAttribute("start-time", dateTime.ToString("o"));
TNode tNode3 = tNode;
dateTime = EndTime;
tNode3.AddAttribute("end-time", dateTime.ToString("o"));
tNode.AddAttribute("duration", Duration.ToString("0.000000", NumberFormatInfo.InvariantInfo));
int num;
if (Test is TestSuite) {
TNode tNode4 = tNode;
num = TotalCount;
tNode4.AddAttribute("total", num.ToString());
TNode tNode5 = tNode;
num = PassCount;
tNode5.AddAttribute("passed", num.ToString());
TNode tNode6 = tNode;
num = FailCount;
tNode6.AddAttribute("failed", num.ToString());
TNode tNode7 = tNode;
num = WarningCount;
tNode7.AddAttribute("warnings", num.ToString());
TNode tNode8 = tNode;
num = InconclusiveCount;
tNode8.AddAttribute("inconclusive", num.ToString());
TNode tNode9 = tNode;
num = SkipCount;
tNode9.AddAttribute("skipped", num.ToString());
}
TNode tNode10 = tNode;
num = AssertCount;
tNode10.AddAttribute("asserts", num.ToString());
TestStatus status = ResultState.Status;
if ((uint)status > 3) {
if (status == TestStatus.Failed)
AddFailureElement(tNode);
} else if (!string.IsNullOrWhiteSpace(Message)) {
TNode tNode11 = tNode.AddElement("reason");
tNode11.AddElementWithCDATA("message", Message);
}
string output = Output;
if (output.Length > 0)
AddOutputElement(tNode, output);
if (_assertionResults.Count > 0)
AddAssertionsElement(tNode);
if (_testAttachments.Count > 0)
AddAttachmentsElement(tNode);
if (recursive && HasChildren) {
foreach (ITestResult child in Children) {
child.AddToXml(tNode, recursive);
}
return tNode;
}
return tNode;
}
public void SetResult(ResultState resultState)
{
SetResult(resultState, string.Empty, null);
}
public void SetResult(ResultState resultState, string message)
{
SetResult(resultState, message, null);
}
public void SetResult(ResultState resultState, string message, [System.Runtime.CompilerServices.Nullable(2)] string stackTrace)
{
RwLock.EnterWriteLock();
try {
ResultState = resultState;
Message = message;
StackTrace = stackTrace;
} finally {
RwLock.ExitWriteLock();
}
}
public void RecordException(Exception ex)
{
ExceptionResult exceptionResult = new ExceptionResult(ex, FailureSite.Test);
SetResult(exceptionResult.ResultState, exceptionResult.Message, exceptionResult.StackTrace);
if (_assertionResults.Count > 0 && exceptionResult.ResultState == ResultState.Error) {
Message = Message + Environment.NewLine + Environment.NewLine + CreateLegacyFailureMessage();
_assertionResults.Add(new AssertionResult(AssertionStatus.Error, exceptionResult.Message, exceptionResult.StackTrace));
}
}
public void RecordException(Exception ex, FailureSite site)
{
ExceptionResult exceptionResult = new ExceptionResult(ex, site);
SetResult(exceptionResult.ResultState, exceptionResult.Message, exceptionResult.StackTrace);
}
public void RecordTearDownException(Exception ex)
{
ExceptionResult exceptionResult = new ExceptionResult(ex, FailureSite.TearDown);
ResultState resultState = (ResultState == ResultState.Cancelled) ? ResultState.Cancelled : ResultState.Error;
if (Test.IsSuite)
resultState = resultState.WithSite(FailureSite.TearDown);
string text = "TearDown : " + exceptionResult.Message;
if (!string.IsNullOrEmpty(Message))
text = Message + Environment.NewLine + text;
string text2 = "--TearDown" + Environment.NewLine + exceptionResult.StackTrace;
if (StackTrace != null)
text2 = StackTrace + Environment.NewLine + text2;
SetResult(resultState, text, text2);
}
private static Exception ValidateAndUnwrap(Exception ex)
{
Guard.ArgumentNotNull(ex, "ex");
return ex.Unwrap();
}
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, [System.Runtime.CompilerServices.Nullable(2)] 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 stringWriter2 = stringWriter;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 2);
defaultInterpolatedStringHandler.AppendLiteral(" ");
defaultInterpolatedStringHandler.AppendFormatted(++num);
defaultInterpolatedStringHandler.AppendLiteral(") ");
defaultInterpolatedStringHandler.AppendFormatted(assertionResult.Message);
stringWriter2.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
}
return stringWriter.ToString();
}
private TNode AddFailureElement(TNode targetNode)
{
TNode tNode = targetNode.AddElement("failure");
if (!string.IsNullOrWhiteSpace(Message))
tNode.AddElementWithCDATA("message", Message);
if (!string.IsNullOrWhiteSpace(StackTrace))
tNode.AddElementWithCDATA("stack-trace", StackTrace);
return tNode;
}
private TNode AddOutputElement(TNode targetNode, string output)
{
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;
}
}
}