Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions source/TestFramework/Assert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,43 @@ public static void ThrowsException(Type exception, Action action, [CallerArgumen
HandleFail("Assert.ThrowsException", $"No exception thrown. {exception.Name} exception was expected. {ReplaceNulls(message)}");
}

/// <summary>
/// Executes multiple assertions and collects any failures encountered.
/// If one or more assertions fail, a <see cref="MultipleAssertionException"/> is thrown containing all the failures.
/// </summary>
/// <param name="assertions">The actions containing the assertions to execute.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="assertions"/> is null.</exception>
/// <exception cref="MultipleAssertionException">Thrown when one or more assertions fail.</exception>
public static void Multiple(params Action[] assertions)
{
if (assertions == null)
{
throw new ArgumentNullException(nameof(assertions));
}

Exception[] failures = new Exception[assertions.Length];
int failuresIndex = 0;

foreach (Action assertion in assertions)
{
try
{
assertion();
}
catch (Exception ex)
{
failures[failuresIndex++] = ex;
}
}

if (failuresIndex > 0)
{
throw new MultipleAssertionException(failures, failuresIndex);
}

return;
}

[DoesNotReturn]
internal static void HandleFail(string assertion, string message)
{
Expand Down
51 changes: 51 additions & 0 deletions source/TestFrameworkShared/MultipleAssertionException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace TestFrameworkShared
{
/// <summary>
/// Represents an exception that encapsulates multiple assertion failures.
/// </summary>
public class MultipleAssertionException : Exception
{
private readonly Exception[] _failures;
private readonly int _failureCount;

/// <summary>
/// Initializes a new instance of the <see cref="MultipleAssertionException"/> class.
/// </summary>
/// <param name="failures">The array of exceptions representing assertion failures.</param>
/// <param name="failureCount">The number of failures in the <paramref name="failures"/> array.</param>
public MultipleAssertionException(Exception[] failures, int failureCount)
: base("One or more assertions failed.")
{
_failures = failures;
_failureCount = failureCount;

Console.WriteLine(ToString());
}

/// <summary>
/// Returns a string representation of the exception, including all assertion failures.
/// </summary>
/// <returns>A string describing the exception and all failures.</returns>
public override string ToString()
{
string message = base.ToString();

for (int i = 0; i < _failureCount; i++)
{
if(_failures[i] == null)
{
continue;
}

message += "\n" + _failures[i].ToString();
}

return message;
}
}
}
1 change: 1 addition & 0 deletions source/TestFrameworkShared/TestFrameworkShared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<Compile Include="$(MSBuildThisFileDirectory)CleanupAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DataRowAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Helper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)MultipleAssertionException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SetupAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SkipTestException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)TestClassAttribute.cs" />
Expand Down