-
-
Notifications
You must be signed in to change notification settings - Fork 119
Expand file tree
/
Copy pathTestExecutionException.cs
More file actions
135 lines (122 loc) · 5.03 KB
/
TestExecutionException.cs
File metadata and controls
135 lines (122 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
namespace TUnit.Core.Exceptions;
/// <summary>
/// Exception thrown when one or more failures occur during test execution, including the test itself,
/// hooks (before/after test methods), or event receivers.
/// This exception aggregates multiple failure types to provide comprehensive error reporting.
/// </summary>
/// <remarks>
/// This exception is thrown in the following scenarios:
/// <list type="bullet">
/// <item><description>The test itself fails and one or more hooks or event receivers also fail</description></item>
/// <item><description>The test passes but one or more hooks or event receivers fail during cleanup</description></item>
/// <item><description>Multiple hooks fail during test execution</description></item>
/// <item><description>Multiple event receivers fail during test execution</description></item>
/// </list>
/// The <see cref="InnerException"/> property contains either a single exception or an <see cref="AggregateException"/>
/// when multiple failures occur.
/// </remarks>
public class TestExecutionException : TUnitException
{
/// <summary>
/// Gets the exception thrown by the test itself, or null if the test passed.
/// </summary>
public Exception? TestException { get; }
/// <summary>
/// Gets the collection of exceptions thrown by hooks during test execution.
/// </summary>
public IReadOnlyList<Exception> HookExceptions { get; }
/// <summary>
/// Gets the collection of exceptions thrown by event receivers during test execution.
/// </summary>
public IReadOnlyList<Exception> EventReceiverExceptions { get; }
/// <summary>
/// Initializes a new instance of the <see cref="TestExecutionException"/> class.
/// </summary>
/// <param name="testException">The exception thrown by the test, or null if the test passed.</param>
/// <param name="hookExceptions">The collection of exceptions thrown by hooks.</param>
/// <param name="eventReceiverExceptions">The collection of exceptions thrown by event receivers.</param>
public TestExecutionException(
Exception? testException,
IReadOnlyList<Exception> hookExceptions,
IReadOnlyList<Exception> eventReceiverExceptions)
: base(BuildMessage(testException, hookExceptions, eventReceiverExceptions),
BuildInnerException(testException, hookExceptions, eventReceiverExceptions))
{
TestException = testException;
HookExceptions = hookExceptions;
EventReceiverExceptions = eventReceiverExceptions;
}
private static string BuildMessage(
Exception? testException,
IReadOnlyList<Exception> hookExceptions,
IReadOnlyList<Exception> eventReceiverExceptions)
{
var parts = new List<string>();
if (testException is not null)
{
parts.Add($"Test failed: {testException.Message}");
}
if (hookExceptions.Count > 0)
{
if (hookExceptions.Count == 1)
{
parts.Add(hookExceptions[0].Message);
}
else
{
var messageBuilder = new System.Text.StringBuilder();
messageBuilder.Append("Multiple hooks failed: ");
for (var i = 0; i < hookExceptions.Count; i++)
{
if (i > 0)
{
messageBuilder.Append("; ");
}
messageBuilder.Append(hookExceptions[i].Message);
}
parts.Add(messageBuilder.ToString());
}
}
if (eventReceiverExceptions.Count > 0)
{
if (eventReceiverExceptions.Count == 1)
{
parts.Add($"Test end event receiver failed: {eventReceiverExceptions[0].Message}");
}
else
{
var messageBuilder = new System.Text.StringBuilder();
messageBuilder.Append($"{eventReceiverExceptions.Count} test end event receivers failed: ");
for (var i = 0; i < eventReceiverExceptions.Count; i++)
{
if (i > 0)
{
messageBuilder.Append("; ");
}
messageBuilder.Append(eventReceiverExceptions[i].Message);
}
parts.Add(messageBuilder.ToString());
}
}
return string.Join(" | ", parts);
}
private static Exception? BuildInnerException(
Exception? testException,
IReadOnlyList<Exception> hookExceptions,
IReadOnlyList<Exception> eventReceiverExceptions)
{
var allExceptions = new List<Exception>();
if (testException is not null)
{
allExceptions.Add(testException);
}
allExceptions.AddRange(hookExceptions);
allExceptions.AddRange(eventReceiverExceptions);
return allExceptions.Count switch
{
0 => null,
1 => allExceptions[0],
_ => new AggregateException(allExceptions)
};
}
}