Skip to content
Open
Show file tree
Hide file tree
Changes from 13 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
261 changes: 261 additions & 0 deletions docs/RFCs/011-Soft-Assertions-Nullability-Design.md

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.ComponentModel;
Expand Down Expand Up @@ -662,7 +662,7 @@ private static void ThrowAssertAreEqualFailed(object? expected, object? actual,
userMessage,
ReplaceNulls(expected),
ReplaceNulls(actual));
ThrowAssertFailed("Assert.AreEqual", finalMessage);
ReportAssertFailed("Assert.AreEqual", finalMessage);
}

[DoesNotReturn]
Expand All @@ -676,7 +676,7 @@ private static void ThrowAssertAreEqualFailed<T>(T expected, T actual, T delta,
expected.ToString(CultureInfo.CurrentCulture.NumberFormat),
actual.ToString(CultureInfo.CurrentCulture.NumberFormat),
delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
ThrowAssertFailed("Assert.AreEqual", finalMessage);
ReportAssertFailed("Assert.AreEqual", finalMessage);
}

[DoesNotReturn]
Expand All @@ -700,7 +700,7 @@ private static void ThrowAssertAreEqualFailed(string? expected, string? actual,
finalMessage = FormatStringComparisonMessage(expected, actual, userMessage);
}

ThrowAssertFailed("Assert.AreEqual", finalMessage);
ReportAssertFailed("Assert.AreEqual", finalMessage);
}

/// <summary>
Expand Down Expand Up @@ -1229,7 +1229,7 @@ private static void ThrowAssertAreNotEqualFailed<T>(T notExpected, T actual, T d
notExpected.ToString(CultureInfo.CurrentCulture.NumberFormat),
actual.ToString(CultureInfo.CurrentCulture.NumberFormat),
delta.ToString(CultureInfo.CurrentCulture.NumberFormat));
ThrowAssertFailed("Assert.AreNotEqual", finalMessage);
ReportAssertFailed("Assert.AreNotEqual", finalMessage);
}

/// <summary>
Expand Down Expand Up @@ -1437,7 +1437,7 @@ private static void ThrowAssertAreNotEqualFailed(object? notExpected, object? ac
userMessage,
ReplaceNulls(notExpected),
ReplaceNulls(actual));
ThrowAssertFailed("Assert.AreNotEqual", finalMessage);
ReportAssertFailed("Assert.AreNotEqual", finalMessage);
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.ComponentModel;
Expand Down Expand Up @@ -196,7 +196,7 @@ private static void ThrowAssertAreSameFailed<T>(T? expected, T? actual, string u
userMessage);
}

ThrowAssertFailed("Assert.AreSame", finalMessage);
ReportAssertFailed("Assert.AreSame", finalMessage);
}

/// <inheritdoc cref="AreNotSame{T}(T, T, string?, string, string)" />
Expand Down Expand Up @@ -249,5 +249,5 @@ private static bool IsAreNotSameFailing<T>(T? notExpected, T? actual)

[DoesNotReturn]
private static void ThrowAssertAreNotSameFailed(string userMessage)
=> ThrowAssertFailed("Assert.AreNotSame", userMessage);
=> ReportAssertFailed("Assert.AreNotSame", userMessage);
}
18 changes: 9 additions & 9 deletions src/TestFramework/TestFramework/Assertions/Assert.Contains.cs
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ public static void Contains(string substring, string value, StringComparison com
{
string userMessage = BuildUserMessageForSubstringExpressionAndValueExpression(message, substringExpression, valueExpression);
string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.ContainsFail, value, substring, userMessage);
ThrowAssertFailed("Assert.Contains", finalMessage);
ReportAssertFailed("Assert.Contains", finalMessage);
}
}

Expand Down Expand Up @@ -717,7 +717,7 @@ public static void DoesNotContain(string substring, string value, StringComparis
{
string userMessage = BuildUserMessageForSubstringExpressionAndValueExpression(message, substringExpression, valueExpression);
string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DoesNotContainFail, value, substring, userMessage);
ThrowAssertFailed("Assert.DoesNotContain", finalMessage);
ReportAssertFailed("Assert.DoesNotContain", finalMessage);
}
}

Expand Down Expand Up @@ -758,7 +758,7 @@ public static void IsInRange<T>(T minValue, T maxValue, T value, string? message
{
string userMessage = BuildUserMessageForMinValueExpressionAndMaxValueExpressionAndValueExpression(message, minValueExpression, maxValueExpression, valueExpression);
string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsInRangeFail, value, minValue, maxValue, userMessage);
ThrowAssertFailed("IsInRange", finalMessage);
ReportAssertFailed("IsInRange", finalMessage);
}
}

Expand All @@ -772,7 +772,7 @@ private static void ThrowAssertSingleMatchFailed(int actualCount, string userMes
FrameworkMessages.ContainsSingleMatchFailMsg,
userMessage,
actualCount);
ThrowAssertFailed("Assert.ContainsSingle", finalMessage);
ReportAssertFailed("Assert.ContainsSingle", finalMessage);
}

[DoesNotReturn]
Expand All @@ -783,7 +783,7 @@ private static void ThrowAssertContainsSingleFailed(int actualCount, string user
FrameworkMessages.ContainsSingleFailMsg,
userMessage,
actualCount);
ThrowAssertFailed("Assert.ContainsSingle", finalMessage);
ReportAssertFailed("Assert.ContainsSingle", finalMessage);
}

[DoesNotReturn]
Expand All @@ -793,7 +793,7 @@ private static void ThrowAssertContainsItemFailed(string userMessage)
CultureInfo.CurrentCulture,
FrameworkMessages.ContainsItemFailMsg,
userMessage);
ThrowAssertFailed("Assert.Contains", finalMessage);
ReportAssertFailed("Assert.Contains", finalMessage);
}

[DoesNotReturn]
Expand All @@ -803,7 +803,7 @@ private static void ThrowAssertContainsPredicateFailed(string userMessage)
CultureInfo.CurrentCulture,
FrameworkMessages.ContainsPredicateFailMsg,
userMessage);
ThrowAssertFailed("Assert.Contains", finalMessage);
ReportAssertFailed("Assert.Contains", finalMessage);
}

[DoesNotReturn]
Expand All @@ -813,7 +813,7 @@ private static void ThrowAssertDoesNotContainItemFailed(string userMessage)
CultureInfo.CurrentCulture,
FrameworkMessages.DoesNotContainItemFailMsg,
userMessage);
ThrowAssertFailed("Assert.DoesNotContain", finalMessage);
ReportAssertFailed("Assert.DoesNotContain", finalMessage);
}

[DoesNotReturn]
Expand All @@ -823,6 +823,6 @@ private static void ThrowAssertDoesNotContainPredicateFailed(string userMessage)
CultureInfo.CurrentCulture,
FrameworkMessages.DoesNotContainPredicateFailMsg,
userMessage);
ThrowAssertFailed("Assert.DoesNotContain", finalMessage);
ReportAssertFailed("Assert.DoesNotContain", finalMessage);
}
}
6 changes: 3 additions & 3 deletions src/TestFramework/TestFramework/Assertions/Assert.Count.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.ComponentModel;
Expand Down Expand Up @@ -342,7 +342,7 @@
userMessage,
expectedCount,
actualCount);
ThrowAssertFailed($"Assert.{assertionName}", finalMessage);
ReportAssertFailed($"Assert.{assertionName}", finalMessage);

Check failure on line 345 in src/TestFramework/TestFramework/Assertions/Assert.Count.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Windows Release)

src/TestFramework/TestFramework/Assertions/Assert.Count.cs#L345

src/TestFramework/TestFramework/Assertions/Assert.Count.cs(345,1): error : [GenerateCSharpEntryPointAndVerifyTheCacheUsage ("net10.0",Release,build)] Assert.HasCount failed. Expected collection of size 1. Actual: 0. 'collection' expression: 'generateTestingPlatformEntryPointTargets'. Expected exactly one _GenerateTestingPlatformEntryPoint target
}

[DoesNotReturn]
Expand All @@ -352,6 +352,6 @@
CultureInfo.CurrentCulture,
FrameworkMessages.IsNotEmptyFailMsg,
userMessage);
ThrowAssertFailed("Assert.IsNotEmpty", finalMessage);
ReportAssertFailed("Assert.IsNotEmpty", finalMessage);
}
}
6 changes: 3 additions & 3 deletions src/TestFramework/TestFramework/Assertions/Assert.EndsWith.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -78,7 +78,7 @@ public static void EndsWith([NotNull] string? expectedSuffix, [NotNull] string?
{
string userMessage = BuildUserMessageForExpectedSuffixExpressionAndValueExpression(message, expectedSuffixExpression, valueExpression);
string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.EndsWithFail, value, expectedSuffix, userMessage);
ThrowAssertFailed("Assert.EndsWith", finalMessage);
ReportAssertFailed("Assert.EndsWith", finalMessage);
}
}

Expand Down Expand Up @@ -152,7 +152,7 @@ public static void DoesNotEndWith([NotNull] string? notExpectedSuffix, [NotNull]
{
string userMessage = BuildUserMessageForNotExpectedSuffixExpressionAndValueExpression(message, notExpectedSuffixExpression, valueExpression);
string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DoesNotEndWithFail, value, notExpectedSuffix, userMessage);
ThrowAssertFailed("Assert.DoesNotEndWith", finalMessage);
ReportAssertFailed("Assert.DoesNotEndWith", finalMessage);
}
}
}
2 changes: 1 addition & 1 deletion src/TestFramework/TestFramework/Assertions/Assert.Fail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ public sealed partial class Assert
/// </exception>
[DoesNotReturn]
public static void Fail(string message = "")
=> ThrowAssertFailed("Assert.Fail", BuildUserMessage(message));
=> ReportAssertFailed("Assert.Fail", BuildUserMessage(message), forceThrow: true);
}
14 changes: 7 additions & 7 deletions src/TestFramework/TestFramework/Assertions/Assert.IComparable.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down Expand Up @@ -307,7 +307,7 @@ private static void ThrowAssertIsGreaterThanFailed<T>(T lowerBound, T value, str
userMessage,
ReplaceNulls(lowerBound),
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsGreaterThan", finalMessage);
ReportAssertFailed("Assert.IsGreaterThan", finalMessage);
}

[DoesNotReturn]
Expand All @@ -319,7 +319,7 @@ private static void ThrowAssertIsGreaterThanOrEqualToFailed<T>(T lowerBound, T v
userMessage,
ReplaceNulls(lowerBound),
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsGreaterThanOrEqualTo", finalMessage);
ReportAssertFailed("Assert.IsGreaterThanOrEqualTo", finalMessage);
}

[DoesNotReturn]
Expand All @@ -331,7 +331,7 @@ private static void ThrowAssertIsLessThanFailed<T>(T upperBound, T value, string
userMessage,
ReplaceNulls(upperBound),
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsLessThan", finalMessage);
ReportAssertFailed("Assert.IsLessThan", finalMessage);
}

[DoesNotReturn]
Expand All @@ -343,7 +343,7 @@ private static void ThrowAssertIsLessThanOrEqualToFailed<T>(T upperBound, T valu
userMessage,
ReplaceNulls(upperBound),
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsLessThanOrEqualTo", finalMessage);
ReportAssertFailed("Assert.IsLessThanOrEqualTo", finalMessage);
}

[DoesNotReturn]
Expand All @@ -354,7 +354,7 @@ private static void ThrowAssertIsPositiveFailed<T>(T value, string userMessage)
FrameworkMessages.IsPositiveFailMsg,
userMessage,
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsPositive", finalMessage);
ReportAssertFailed("Assert.IsPositive", finalMessage);
}

[DoesNotReturn]
Expand All @@ -365,6 +365,6 @@ private static void ThrowAssertIsNegativeFailed<T>(T value, string userMessage)
FrameworkMessages.IsNegativeFailMsg,
userMessage,
ReplaceNulls(value));
ThrowAssertFailed("Assert.IsNegative", finalMessage);
ReportAssertFailed("Assert.IsNegative", finalMessage);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestTools.UnitTesting;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ public static void IsExactInstanceOfType([NotNull] object? value, [NotNull] Type
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
public static void IsExactInstanceOfType([NotNull] object? value, [NotNull] Type? expectedType, [InterpolatedStringHandlerArgument(nameof(value), nameof(expectedType))] ref AssertIsExactInstanceOfTypeInterpolatedStringHandler message, [CallerArgumentExpression(nameof(value))] string valueExpression = "")
#pragma warning restore IDE0060 // Remove unused parameter
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Not sure how to express the semantics to the compiler, but the implementation guarantees that.
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Deliberately keeping [NotNull] annotation while using soft assertions. Within an AssertScope, the postcondition is not enforced (same as all other assertion postconditions in scoped mode).
=> message.ComputeAssertion(valueExpression);
#pragma warning restore CS8777 // Parameter must have a non-null value when exiting.

Expand All @@ -318,7 +318,7 @@ public static T IsExactInstanceOfType<T>([NotNull] object? value, string? messag
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
public static T IsExactInstanceOfType<T>([NotNull] object? value, [InterpolatedStringHandlerArgument(nameof(value))] ref AssertGenericIsExactInstanceOfTypeInterpolatedStringHandler<T> message, [CallerArgumentExpression(nameof(value))] string valueExpression = "")
#pragma warning restore IDE0060 // Remove unused parameter
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Not sure how to express the semantics to the compiler, but the implementation guarantees that.
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Deliberately keeping [NotNull] annotation while using soft assertions. Within an AssertScope, the postcondition is not enforced (same as all other assertion postconditions in scoped mode).
{
message.ComputeAssertion(valueExpression);
return (T)value!;
Expand All @@ -342,7 +342,7 @@ private static void ThrowAssertIsExactInstanceOfTypeFailed(object? value, Type?
value.GetType().ToString());
}

ThrowAssertFailed("Assert.IsExactInstanceOfType", finalMessage);
ReportAssertFailed("Assert.IsExactInstanceOfType", finalMessage);
}

/// <summary>
Expand Down Expand Up @@ -418,6 +418,6 @@ private static void ThrowAssertIsNotExactInstanceOfTypeFailed(object? value, Typ
value!.GetType().ToString());
}

ThrowAssertFailed("Assert.IsNotExactInstanceOfType", finalMessage);
ReportAssertFailed("Assert.IsNotExactInstanceOfType", finalMessage);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ public static void IsInstanceOfType([NotNull] object? value, [NotNull] Type? exp
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
public static void IsInstanceOfType([NotNull] object? value, [NotNull] Type? expectedType, [InterpolatedStringHandlerArgument(nameof(value), nameof(expectedType))] ref AssertIsInstanceOfTypeInterpolatedStringHandler message, [CallerArgumentExpression(nameof(value))] string valueExpression = "")
#pragma warning restore IDE0060 // Remove unused parameter
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Not sure how to express the semantics to the compiler, but the implementation guarantees that.
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Deliberately keeping [NotNull] annotation while using soft assertions. Within an AssertScope, the postcondition is not enforced (same as all other assertion postconditions in scoped mode).
=> message.ComputeAssertion(valueExpression);
#pragma warning restore CS8777 // Parameter must have a non-null value when exiting.

Expand All @@ -320,7 +320,7 @@ public static T IsInstanceOfType<T>([NotNull] object? value, string? message = "
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
public static T IsInstanceOfType<T>([NotNull] object? value, [InterpolatedStringHandlerArgument(nameof(value))] ref AssertGenericIsInstanceOfTypeInterpolatedStringHandler<T> message, [CallerArgumentExpression(nameof(value))] string valueExpression = "")
#pragma warning restore IDE0060 // Remove unused parameter
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Not sure how to express the semantics to the compiler, but the implementation guarantees that.
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Deliberately keeping [NotNull] annotation while using soft assertions. Within an AssertScope, the postcondition is not enforced (same as all other assertion postconditions in scoped mode).
{
message.ComputeAssertion(valueExpression);
return (T)value!;
Expand All @@ -344,7 +344,7 @@ private static void ThrowAssertIsInstanceOfTypeFailed(object? value, Type? expec
value.GetType().ToString());
}

ThrowAssertFailed("Assert.IsInstanceOfType", finalMessage);
ReportAssertFailed("Assert.IsInstanceOfType", finalMessage);
}

/// <summary>
Expand Down Expand Up @@ -422,6 +422,6 @@ private static void ThrowAssertIsNotInstanceOfTypeFailed(object? value, Type? wr
value!.GetType().ToString());
}

ThrowAssertFailed("Assert.IsNotInstanceOfType", finalMessage);
ReportAssertFailed("Assert.IsNotInstanceOfType", finalMessage);
}
}
6 changes: 3 additions & 3 deletions src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,13 @@ public static void IsNull(object? value, string? message = "", [CallerArgumentEx
private static bool IsNullFailing(object? value) => value is not null;

private static void ThrowAssertIsNullFailed(string? message)
=> ThrowAssertFailed("Assert.IsNull", message);
=> ReportAssertFailed("Assert.IsNull", message);

/// <inheritdoc cref="IsNull(object?, string, string)" />
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
public static void IsNotNull([NotNull] object? value, [InterpolatedStringHandlerArgument(nameof(value))] ref AssertIsNotNullInterpolatedStringHandler message, [CallerArgumentExpression(nameof(value))] string valueExpression = "")
#pragma warning restore IDE0060 // Remove unused parameter
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Not sure how to express the semantics to the compiler, but the implementation guarantees that.
#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - Deliberately keeping [NotNull] annotation while using soft assertions. Within an AssertScope, the postcondition is not enforced (same as all other assertion postconditions in scoped mode).
=> message.ComputeAssertion(valueExpression);
#pragma warning restore CS8777 // Parameter must have a non-null value when exiting.

Expand Down Expand Up @@ -199,5 +199,5 @@ public static void IsNotNull([NotNull] object? value, string? message = "", [Cal

[DoesNotReturn]
private static void ThrowAssertIsNotNullFailed(string? message)
=> ThrowAssertFailed("Assert.IsNotNull", message);
=> ReportAssertFailed("Assert.IsNotNull", message);
}
Loading
Loading