diff --git a/src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs b/src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs index 5cd7fe9939..d513d6b6d9 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs @@ -48,8 +48,7 @@ internal void ComputeAssertion(string expectedExpression, string actualExpressio { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "expected", expectedExpression, "actual", actualExpression) + " "); - ThrowAssertAreEqualFailed(_expected, _actual, _builder.ToString()); + ThrowAssertAreEqualFailed(_expected, _actual, _builder.ToString(), expectedExpression, actualExpression); } } @@ -115,8 +114,7 @@ internal void ComputeAssertion(string notExpectedExpression, string actualExpres { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "notExpected", notExpectedExpression, "actual", actualExpression) + " "); - ThrowAssertAreNotEqualFailed(_notExpected, _actual, _builder.ToString()); + ThrowAssertAreNotEqualFailed(_notExpected, _actual, _builder.ToString(), notExpectedExpression, actualExpression); } } @@ -159,7 +157,7 @@ internal void ComputeAssertion(string notExpectedExpression, string actualExpres public readonly struct AssertNonGenericAreEqualInterpolatedStringHandler { private readonly StringBuilder? _builder; - private readonly Action? _failAction; + private readonly Action? _failAction; public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int formattedCount, float expected, float actual, float delta, out bool shouldAppend) { @@ -167,7 +165,7 @@ public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + _failAction = (userMessage, expectedExpr, actualExpr) => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage, expectedExpr, actualExpr); } } @@ -177,7 +175,7 @@ public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + _failAction = (userMessage, expectedExpr, actualExpr) => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage, expectedExpr, actualExpr); } } @@ -187,7 +185,7 @@ public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + _failAction = (userMessage, expectedExpr, actualExpr) => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage, expectedExpr, actualExpr); } } @@ -197,7 +195,7 @@ public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + _failAction = (userMessage, expectedExpr, actualExpr) => ThrowAssertAreEqualFailed(expected, actual, delta, userMessage, expectedExpr, actualExpr); } } @@ -213,18 +211,12 @@ public AssertNonGenericAreEqualInterpolatedStringHandler(int literalLength, int if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreEqualFailed(expected, actual, ignoreCase, culture, userMessage); + _failAction = (userMessage, expectedExpr, actualExpr) => ThrowAssertAreEqualFailed(expected, actual, ignoreCase, culture, userMessage, expectedExpr, actualExpr); } } internal void ComputeAssertion(string expectedExpression, string actualExpression) - { - if (_failAction is not null) - { - _builder!.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "expected", expectedExpression, "actual", actualExpression) + " "); - _failAction.Invoke(_builder!.ToString()); - } - } + => _failAction?.Invoke(_builder!.ToString(), expectedExpression, actualExpression); public void AppendLiteral(string value) => _builder!.Append(value); @@ -265,7 +257,7 @@ internal void ComputeAssertion(string expectedExpression, string actualExpressio public readonly struct AssertNonGenericAreNotEqualInterpolatedStringHandler { private readonly StringBuilder? _builder; - private readonly Action? _failAction; + private readonly Action? _failAction; public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, int formattedCount, float notExpected, float actual, float delta, out bool shouldAppend) { @@ -273,7 +265,7 @@ public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, i if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + _failAction = (userMessage, notExpectedExpr, actualExpr) => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage, notExpectedExpr, actualExpr); } } @@ -283,7 +275,7 @@ public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, i if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + _failAction = (userMessage, notExpectedExpr, actualExpr) => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage, notExpectedExpr, actualExpr); } } @@ -293,7 +285,7 @@ public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, i if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + _failAction = (userMessage, notExpectedExpr, actualExpr) => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage, notExpectedExpr, actualExpr); } } @@ -303,7 +295,7 @@ public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, i if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + _failAction = (userMessage, notExpectedExpr, actualExpr) => ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage, notExpectedExpr, actualExpr); } } @@ -319,18 +311,12 @@ public AssertNonGenericAreNotEqualInterpolatedStringHandler(int literalLength, i if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); - _failAction = userMessage => ThrowAssertAreNotEqualFailed(notExpected, actual, userMessage); + _failAction = (userMessage, notExpectedExpr, actualExpr) => ThrowAssertAreNotEqualFailed(notExpected, actual, userMessage, notExpectedExpr, actualExpr); } } internal void ComputeAssertion(string notExpectedExpression, string actualExpression) - { - if (_failAction is not null) - { - _builder!.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "notExpected", notExpectedExpression, "actual", actualExpression) + " "); - _failAction.Invoke(_builder!.ToString()); - } - } + => _failAction?.Invoke(_builder!.ToString(), notExpectedExpression, actualExpression); public void AppendLiteral(string value) => _builder!.Append(value); @@ -488,8 +474,7 @@ public static void AreEqual(T? expected, T? actual, IEqualityComparer comp return; } - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, userMessage); + ThrowAssertAreEqualFailed(expected, actual, message, expectedExpression, actualExpression); } private static bool AreEqualFailing(T? expected, T? actual, IEqualityComparer? comparer) @@ -547,24 +532,14 @@ private static bool AreEqualFailing(long expected, long actual, long delta) private static string FormatStringComparisonMessage(string? expected, string? actual, string userMessage) { // Handle null cases - if (expected is null && actual is null) - { - return string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualFailMsg, - userMessage, - ReplaceNulls(expected), - ReplaceNulls(actual)); - } - if (expected is null || actual is null) { - return string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualFailMsg, - userMessage, - ReplaceNulls(expected), - ReplaceNulls(actual)); + string message = FrameworkMessages.AreEqualFailNew; + message += FormatAlignedParameters( + (nameof(expected), FormatValue(expected)), + (nameof(actual), FormatValue(actual))); + + return message; } // Find the first difference @@ -609,98 +584,95 @@ private static string FormatStringDifferenceMessage(string expected, string actu string actualPreview = tuple.Item2; int caretPosition = tuple.Item3; - // Get localized prefixes - string expectedPrefix = FrameworkMessages.AreEqualStringDiffExpectedPrefix; - string actualPrefix = FrameworkMessages.AreEqualStringDiffActualPrefix; + // Fixed prefixes - expressions are now shown on the first line + string expectedPrefix = " expected: "; + string actualPrefix = " actual: "; - // Calculate the maximum prefix length to align the caret properly - int maxPrefixLength = Math.Max(expectedPrefix.Length, actualPrefix.Length); - - // Pad shorter prefix to match the longer one for proper alignment - string paddedExpectedPrefix = expectedPrefix.PadRight(maxPrefixLength); - string paddedActualPrefix = actualPrefix.PadRight(maxPrefixLength); + int maxPrefixLength = expectedPrefix.Length; // " expected: " is always the longest // Build the formatted lines with proper alignment - string expectedLine = paddedExpectedPrefix + $"\"{expectedPreview}\""; - string actualLine = paddedActualPrefix + $"\"{actualPreview}\""; + string expectedLine = expectedPrefix + $"\"{expectedPreview}\""; + string actualLine = actualPrefix + $"\"{actualPreview}\""; // The caret should align under the difference in the string content - // For localized prefixes with different lengths, we need to account for the longer prefix - // to ensure proper alignment. But the caret position is relative to the string content. int adjustedCaretPosition = maxPrefixLength + 1 + caretPosition; // +1 for the opening quote - // Format user message properly - add leading space if not empty, otherwise no extra formatting - string formattedUserMessage = string.IsNullOrEmpty(userMessage) ? string.Empty : $" {userMessage}"; - - return string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualStringDiffFailMsg, - lengthInfo, - formattedUserMessage, - expectedLine, - actualLine, - new string('-', adjustedCaretPosition) + "^"); + string formattedUserMessage = string.IsNullOrEmpty(userMessage) ? string.Empty : userMessage; + + string result = lengthInfo + Environment.NewLine + expectedLine + Environment.NewLine + actualLine + Environment.NewLine + " " + new string('-', adjustedCaretPosition - 2) + "^"; + return string.IsNullOrEmpty(formattedUserMessage) ? result : formattedUserMessage + Environment.NewLine + result; } [DoesNotReturn] - private static void ThrowAssertAreEqualFailed(object? expected, object? actual, string userMessage) + private static void ThrowAssertAreEqualFailed(object? expected, object? actual, string? userMessage, string expectedExpression, string actualExpression) { - string finalMessage = actual != null && expected != null && !actual.GetType().Equals(expected.GetType()) - ? string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualDifferentTypesFailMsg, - userMessage, - ReplaceNulls(expected), - expected.GetType().FullName, - ReplaceNulls(actual), - actual.GetType().FullName) - : expected is string expectedString && actual is string actualString - ? FormatStringComparisonMessage(expectedString, actualString, userMessage) - : string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualFailMsg, - userMessage, - ReplaceNulls(expected), - ReplaceNulls(actual)); - ThrowAssertFailed("Assert.AreEqual", finalMessage); + string callSite = FormatCallSite("Assert.AreEqual", (nameof(expected), expectedExpression), (nameof(actual), actualExpression)); + string message; + + if (actual is not null && expected is not null && !actual.GetType().Equals(expected.GetType())) + { + message = FrameworkMessages.AreEqualFailNew; + message += FormatAlignedParameters( + (nameof(expected), FormatValueWithType(expected)), + (nameof(actual), FormatValueWithType(actual))); + } + else if (expected is string expectedString && actual is string actualString) + { + message = FormatStringComparisonMessage(expectedString, actualString, string.Empty); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + return; + } + else + { + message = FrameworkMessages.AreEqualFailNew; + message += FormatAlignedParameters( + (nameof(expected), FormatValue(expected)), + (nameof(actual), FormatValue(actual))); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertAreEqualFailed(T expected, T actual, T delta, string userMessage) + private static void ThrowAssertAreEqualFailed(T expected, T actual, T delta, string? userMessage, string expectedExpression, string actualExpression) where T : struct, IConvertible { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualDeltaFailMsg, - userMessage, - expected.ToString(CultureInfo.CurrentCulture.NumberFormat), - actual.ToString(CultureInfo.CurrentCulture.NumberFormat), - delta.ToString(CultureInfo.CurrentCulture.NumberFormat)); - ThrowAssertFailed("Assert.AreEqual", finalMessage); + string callSite = FormatCallSite("Assert.AreEqual", (nameof(expected), expectedExpression), (nameof(actual), actualExpression), ("...", "...")); + string message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AreEqualDeltaNoGreaterThanFailMsg, delta.ToString(CultureInfo.CurrentCulture.NumberFormat)); + message += FormatAlignedParameters( + (nameof(expected), FormatValue(expected)), + (nameof(actual), FormatValue(actual)), + (nameof(delta), FormatValue(delta))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertAreEqualFailed(string? expected, string? actual, bool ignoreCase, CultureInfo culture, string userMessage) + private static void ThrowAssertAreEqualFailed(string? expected, string? actual, bool ignoreCase, CultureInfo culture, string? userMessage, string expectedExpression, string actualExpression) { - string finalMessage; + string callSite = FormatCallSite("Assert.AreEqual", (nameof(expected), expectedExpression), (nameof(actual), actualExpression), ("...", "...")); + string message; // If the user requested to match case, and the difference between expected/actual is casing only, then we use a different message. if (!ignoreCase && CompareInternal(expected, actual, ignoreCase: true, culture) == 0) { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreEqualCaseFailMsg, - userMessage, - ReplaceNulls(expected), - ReplaceNulls(actual)); + message = FrameworkMessages.AreEqualCaseDiffersMsg; + message += FormatAlignedParameters( + (nameof(expected), FormatValue(expected)), + (nameof(actual), FormatValue(actual)), + ("ignore case", ignoreCase.ToString()), + (nameof(culture), culture.Name)); } else { // Use enhanced string comparison for string-specific failures - finalMessage = FormatStringComparisonMessage(expected, actual, userMessage); + message = FormatStringComparisonMessage(expected, actual, string.Empty); } - ThrowAssertFailed("Assert.AreEqual", finalMessage); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } /// @@ -791,8 +763,7 @@ public static void AreNotEqual(T? notExpected, T? actual, IEqualityComparer @@ -837,8 +808,7 @@ public static void AreEqual(float expected, float actual, float delta, string? m { if (AreEqualFailing(expected, actual, delta)) { - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + ThrowAssertAreEqualFailed(expected, actual, delta, message, expectedExpression, actualExpression); } } @@ -884,8 +854,7 @@ public static void AreNotEqual(float notExpected, float actual, float delta, str { if (AreNotEqualFailing(notExpected, actual, delta)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression); - ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + ThrowAssertAreNotEqualFailed(notExpected, actual, delta, message, notExpectedExpression, actualExpression); } } @@ -952,8 +921,7 @@ public static void AreEqual(decimal expected, decimal actual, decimal delta, str { if (AreEqualFailing(expected, actual, delta)) { - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + ThrowAssertAreEqualFailed(expected, actual, delta, message, expectedExpression, actualExpression); } } @@ -999,8 +967,7 @@ public static void AreNotEqual(decimal notExpected, decimal actual, decimal delt { if (AreNotEqualFailing(notExpected, actual, delta)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression); - ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + ThrowAssertAreNotEqualFailed(notExpected, actual, delta, message, notExpectedExpression, actualExpression); } } @@ -1049,8 +1016,7 @@ public static void AreEqual(long expected, long actual, long delta, string? mess { if (AreEqualFailing(expected, actual, delta)) { - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + ThrowAssertAreEqualFailed(expected, actual, delta, message, expectedExpression, actualExpression); } } @@ -1096,8 +1062,7 @@ public static void AreNotEqual(long notExpected, long actual, long delta, string { if (AreNotEqualFailing(notExpected, actual, delta)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression); - ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + ThrowAssertAreNotEqualFailed(notExpected, actual, delta, message, notExpectedExpression, actualExpression); } } @@ -1145,8 +1110,7 @@ public static void AreEqual(double expected, double actual, double delta, string { if (AreEqualFailing(expected, actual, delta)) { - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, delta, userMessage); + ThrowAssertAreEqualFailed(expected, actual, delta, message, expectedExpression, actualExpression); } } @@ -1192,8 +1156,7 @@ public static void AreNotEqual(double notExpected, double actual, double delta, { if (AreNotEqualFailing(notExpected, actual, delta)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression); - ThrowAssertAreNotEqualFailed(notExpected, actual, delta, userMessage); + ThrowAssertAreNotEqualFailed(notExpected, actual, delta, message, notExpectedExpression, actualExpression); } } @@ -1219,17 +1182,17 @@ private static bool AreNotEqualFailing(double notExpected, double actual, double } [DoesNotReturn] - private static void ThrowAssertAreNotEqualFailed(T notExpected, T actual, T delta, string userMessage) + private static void ThrowAssertAreNotEqualFailed(T notExpected, T actual, T delta, string? userMessage, string notExpectedExpression, string actualExpression) where T : struct, IConvertible { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreNotEqualDeltaFailMsg, - userMessage, - notExpected.ToString(CultureInfo.CurrentCulture.NumberFormat), - actual.ToString(CultureInfo.CurrentCulture.NumberFormat), - delta.ToString(CultureInfo.CurrentCulture.NumberFormat)); - ThrowAssertFailed("Assert.AreNotEqual", finalMessage); + string callSite = FormatCallSite("Assert.AreNotEqual", (nameof(notExpected), notExpectedExpression), (nameof(actual), actualExpression), ("...", "...")); + string message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AreNotEqualDeltaGreaterThanFailMsg, delta.ToString(CultureInfo.CurrentCulture.NumberFormat)); + message += FormatAlignedParameters( + ("not expected", FormatValue(notExpected)), + (nameof(actual), FormatValue(actual)), + (nameof(delta), FormatValue(delta))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } /// @@ -1322,8 +1285,7 @@ public static void AreEqual(string? expected, string? actual, bool ignoreCase, C return; } - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreEqualFailed(expected, actual, ignoreCase, culture, userMessage); + ThrowAssertAreEqualFailed(expected, actual, ignoreCase, culture, message, expectedExpression, actualExpression); } /// @@ -1418,8 +1380,7 @@ public static void AreNotEqual(string? notExpected, string? actual, bool ignoreC return; } - string userMessage = BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression); - ThrowAssertAreNotEqualFailed(notExpected, actual, userMessage); + ThrowAssertAreNotEqualFailed(notExpected, actual, message, notExpectedExpression, actualExpression); } private static bool AreNotEqualFailing(string? notExpected, string? actual, bool ignoreCase, CultureInfo culture) @@ -1429,15 +1390,15 @@ private static bool AreNotEqualFailing(T? notExpected, T? actual, IEqualityCo => (comparer ?? EqualityComparer.Default).Equals(notExpected!, actual!); [DoesNotReturn] - private static void ThrowAssertAreNotEqualFailed(object? notExpected, object? actual, string userMessage) + private static void ThrowAssertAreNotEqualFailed(object? notExpected, object? actual, string? userMessage, string notExpectedExpression, string actualExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreNotEqualFailMsg, - userMessage, - ReplaceNulls(notExpected), - ReplaceNulls(actual)); - ThrowAssertFailed("Assert.AreNotEqual", finalMessage); + string callSite = FormatCallSite("Assert.AreNotEqual", (nameof(notExpected), notExpectedExpression), (nameof(actual), actualExpression)); + string message = FrameworkMessages.AreNotEqualFailNew; + message += FormatAlignedParameters( + ("not expected", FormatValue(notExpected)), + (nameof(actual), FormatValue(actual))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs b/src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs index 93be91c7fd..a25ba3d650 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs @@ -38,8 +38,7 @@ internal void ComputeAssertion(string expectedExpression, string actualExpressio { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "expected", expectedExpression, "actual", actualExpression) + " "); - ThrowAssertAreSameFailed(_expected, _actual, _builder.ToString()); + ThrowAssertAreSameFailed(_expected, _actual, _builder.ToString(), expectedExpression, actualExpression); } } @@ -80,9 +79,13 @@ internal void ComputeAssertion(string expectedExpression, string actualExpressio public readonly struct AssertAreNotSameInterpolatedStringHandler { private readonly StringBuilder? _builder; + private readonly TArgument? _notExpected; + private readonly TArgument? _actual; public AssertAreNotSameInterpolatedStringHandler(int literalLength, int formattedCount, TArgument? notExpected, TArgument? actual, out bool shouldAppend) { + _notExpected = notExpected; + _actual = actual; shouldAppend = IsAreNotSameFailing(notExpected, actual); if (shouldAppend) { @@ -94,8 +97,7 @@ internal void ComputeAssertion(string notExpectedExpression, string actualExpres { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "notExpected", notExpectedExpression, "actual", actualExpression) + " "); - ThrowAssertAreNotSameFailed(_builder.ToString()); + ThrowAssertAreNotSameFailed(_notExpected, _actual, _builder.ToString(), notExpectedExpression, actualExpression); } } @@ -177,26 +179,63 @@ public static void AreSame(T? expected, T? actual, string? message = "", [Cal return; } - string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression); - ThrowAssertAreSameFailed(expected, actual, userMessage); + ThrowAssertAreSameFailed(expected, actual, message, expectedExpression, actualExpression); } private static bool IsAreSameFailing(T? expected, T? actual) => !object.ReferenceEquals(expected, actual); [DoesNotReturn] - private static void ThrowAssertAreSameFailed(T? expected, T? actual, string userMessage) + private static void ThrowAssertAreSameFailed(T? expected, T? actual, string? userMessage, string expectedExpression, string actualExpression) { - string finalMessage = userMessage; + string callSite = FormatCallSite("Assert.AreSame", (nameof(expected), expectedExpression), (nameof(actual), actualExpression)); + + // When both values have the same string representation, include hash codes + // to help the user understand they are different object instances. + string expectedFormatted = FormatValue(expected); + string actualFormatted = FormatValue(actual); + bool sameToString = expected is not null && actual is not null && expectedFormatted == actualFormatted; + string expectedValue = sameToString + ? expectedFormatted + $" (Hash={RuntimeHelpers.GetHashCode(expected!)})" + : expectedFormatted; + string actualValue = sameToString + ? actualFormatted + $" (Hash={RuntimeHelpers.GetHashCode(actual!)})" + : actualFormatted; + + string message; + // If value types, add diagnostic hint before parameter details if (expected is ValueType && actual is ValueType) { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AreSameGivenValues, - userMessage); + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AreSameGivenValues, string.Empty).TrimEnd(); + } + else + { + // Check equality to give a diagnostic hint about whether the objects are equal + // even though they are different references. + string equalityHint = string.Empty; + if (expected is not null && actual is not null) + { + try + { + equalityHint = expected.Equals(actual) + ? " Objects are equal." + : " Objects are not equal."; + } + catch (Exception) + { + // If Equals throws, skip the hint. + } + } + + message = FrameworkMessages.AreSameFailNew + equalityHint; } - ThrowAssertFailed("Assert.AreSame", finalMessage); + message += FormatAlignedParameters( + (nameof(expected), expectedValue), + (nameof(actual), actualValue)); + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } /// @@ -240,7 +279,7 @@ public static void AreNotSame(T? notExpected, T? actual, string? message = "" { if (IsAreNotSameFailing(notExpected, actual)) { - ThrowAssertAreNotSameFailed(BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression)); + ThrowAssertAreNotSameFailed(notExpected, actual, message, notExpectedExpression, actualExpression); } } @@ -248,6 +287,26 @@ private static bool IsAreNotSameFailing(T? notExpected, T? actual) => object.ReferenceEquals(notExpected, actual); [DoesNotReturn] - private static void ThrowAssertAreNotSameFailed(string userMessage) - => ThrowAssertFailed("Assert.AreNotSame", userMessage); + private static void ThrowAssertAreNotSameFailed(T? notExpected, T? actual, string? userMessage, string notExpectedExpression, string actualExpression) + { + string callSite = FormatCallSite("Assert.AreNotSame", (nameof(notExpected), notExpectedExpression), (nameof(actual), actualExpression)); + string message = FrameworkMessages.AreNotSameFailNew; + + string notExpectedFormatted = FormatValue(notExpected); + string actualFormatted = FormatValue(actual); + + // Since AreNotSame failed, both references point to the same object. + // Show the hash to confirm it's one instance. + if (notExpected is not null) + { + notExpectedFormatted += $" (Hash={RuntimeHelpers.GetHashCode(notExpected!)})"; + actualFormatted += $" (Hash={RuntimeHelpers.GetHashCode(actual!)})"; + } + + message += FormatAlignedParameters( + ("not expected", notExpectedFormatted), + (nameof(actual), actualFormatted)); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Contains.cs b/src/TestFramework/TestFramework/Assertions/Assert.Contains.cs index 19fb68e0a6..9ab35793ed 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.Contains.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.Contains.cs @@ -39,8 +39,7 @@ internal TItem ComputeAssertion(string collectionExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "collection", collectionExpression) + " "); - ThrowAssertContainsSingleFailed(_actualCount, _builder.ToString()); + ThrowAssertContainsSingleFailed(_actualCount, _builder.ToString(), collectionExpression); } return _item!; @@ -179,13 +178,11 @@ public static T ContainsSingle(Func predicate, IEnumerable collec if (string.IsNullOrEmpty(predicateExpression)) { - string userMessage = BuildUserMessageForCollectionExpression(message, collectionExpression); - ThrowAssertContainsSingleFailed(matchCount, userMessage); + ThrowAssertContainsSingleFailed(matchCount, message, collectionExpression, collection); } else { - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertSingleMatchFailed(matchCount, userMessage); + ThrowAssertSingleMatchFailed(matchCount, message, predicateExpression, collectionExpression, collection); } // Unreachable code but compiler cannot work it out @@ -240,13 +237,11 @@ public static T ContainsSingle(Func predicate, IEnumerable collec if (string.IsNullOrEmpty(predicateExpression)) { - string userMessage = BuildUserMessageForCollectionExpression(message, collectionExpression); - ThrowAssertContainsSingleFailed(matchCount, userMessage); + ThrowAssertContainsSingleFailed(matchCount, message, collectionExpression, collection); } else { - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertSingleMatchFailed(matchCount, userMessage); + ThrowAssertSingleMatchFailed(matchCount, message, predicateExpression, collectionExpression, collection); } return default; @@ -273,10 +268,12 @@ public static T ContainsSingle(Func predicate, IEnumerable collec /// public static void Contains(T expected, IEnumerable collection, string? message = "", [CallerArgumentExpression(nameof(expected))] string expectedExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (!collection.Contains(expected)) + // Materialize non-ICollection enumerables to prevent multiple enumeration + // that could yield different results or fail on second pass. + ICollection snapshot = collection as ICollection ?? new List(collection); + if (!snapshot.Contains(expected)) { - string userMessage = BuildUserMessageForExpectedExpressionAndCollectionExpression(message, expectedExpression, collectionExpression); - ThrowAssertContainsItemFailed(userMessage); + ThrowAssertContainsItemFailed(message, expectedExpression, collectionExpression, snapshot); } } @@ -298,7 +295,10 @@ public static void Contains(object? expected, IEnumerable collection, string? me { CheckParameterNotNull(collection, "Assert.Contains", "collection"); - foreach (object? item in collection) + // Materialize non-ICollection enumerables to prevent multiple enumeration. + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (object.Equals(item, expected)) { @@ -306,8 +306,7 @@ public static void Contains(object? expected, IEnumerable collection, string? me } } - string userMessage = BuildUserMessageForExpectedExpressionAndCollectionExpression(message, expectedExpression, collectionExpression); - ThrowAssertContainsItemFailed(userMessage); + ThrowAssertContainsItemFailed(message, expectedExpression, collectionExpression, snapshot); } /// @@ -328,10 +327,10 @@ public static void Contains(object? expected, IEnumerable collection, string? me /// public static void Contains(T expected, IEnumerable collection, IEqualityComparer comparer, string? message = "", [CallerArgumentExpression(nameof(expected))] string expectedExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (!collection.Contains(expected, comparer)) + ICollection snapshot = collection as ICollection ?? new List(collection); + if (!snapshot.Contains(expected, comparer)) { - string userMessage = BuildUserMessageForExpectedExpressionAndCollectionExpression(message, expectedExpression, collectionExpression); - ThrowAssertContainsItemFailed(userMessage); + ThrowAssertContainsItemFailed(message, expectedExpression, collectionExpression, snapshot); } } @@ -355,7 +354,9 @@ public static void Contains(object? expected, IEnumerable collection, IEqualityC CheckParameterNotNull(collection, "Assert.Contains", "collection"); CheckParameterNotNull(comparer, "Assert.Contains", "comparer"); - foreach (object? item in collection) + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (comparer.Equals(item, expected)) { @@ -363,8 +364,7 @@ public static void Contains(object? expected, IEnumerable collection, IEqualityC } } - string userMessage = BuildUserMessageForExpectedExpressionAndCollectionExpression(message, expectedExpression, collectionExpression); - ThrowAssertContainsItemFailed(userMessage); + ThrowAssertContainsItemFailed(message, expectedExpression, collectionExpression, snapshot); } /// @@ -384,10 +384,10 @@ public static void Contains(object? expected, IEnumerable collection, IEqualityC /// public static void Contains(Func predicate, IEnumerable collection, string? message = "", [CallerArgumentExpression(nameof(predicate))] string predicateExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (!collection.Any(predicate)) + ICollection snapshot = collection as ICollection ?? new List(collection); + if (!snapshot.Any(predicate)) { - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertContainsPredicateFailed(userMessage); + ThrowAssertContainsPredicateFailed(message, predicateExpression, collectionExpression, snapshot); } } @@ -410,7 +410,9 @@ public static void Contains(Func predicate, IEnumerable collectio CheckParameterNotNull(collection, "Assert.Contains", "collection"); CheckParameterNotNull(predicate, "Assert.Contains", "predicate"); - foreach (object? item in collection) + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (predicate(item)) { @@ -418,8 +420,7 @@ public static void Contains(Func predicate, IEnumerable collectio } } - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertContainsPredicateFailed(userMessage); + ThrowAssertContainsPredicateFailed(message, predicateExpression, collectionExpression, snapshot); } /// @@ -491,9 +492,7 @@ public static void Contains(string substring, string value, StringComparison com if (!value.Contains(substring, comparisonType)) { - string userMessage = BuildUserMessageForSubstringExpressionAndValueExpression(message, substringExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.ContainsFail, value, substring, userMessage); - ThrowAssertFailed("Assert.Contains", finalMessage); + ThrowAssertStringContainsFailed(value, substring, message, substringExpression, valueExpression); } } @@ -518,10 +517,10 @@ public static void Contains(string substring, string value, StringComparison com /// public static void DoesNotContain(T notExpected, IEnumerable collection, string? message = "", [CallerArgumentExpression(nameof(notExpected))] string notExpectedExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (collection.Contains(notExpected)) + ICollection snapshot = collection as ICollection ?? new List(collection); + if (snapshot.Contains(notExpected)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndCollectionExpression(message, notExpectedExpression, collectionExpression); - ThrowAssertDoesNotContainItemFailed(userMessage); + ThrowAssertDoesNotContainItemFailed(message, notExpectedExpression, collectionExpression, snapshot); } } @@ -543,12 +542,13 @@ public static void DoesNotContain(object? notExpected, IEnumerable collection, s { CheckParameterNotNull(collection, "Assert.DoesNotContain", "collection"); - foreach (object? item in collection) + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (object.Equals(notExpected, item)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndCollectionExpression(message, notExpectedExpression, collectionExpression); - ThrowAssertDoesNotContainItemFailed(userMessage); + ThrowAssertDoesNotContainItemFailed(message, notExpectedExpression, collectionExpression, snapshot); } } } @@ -571,10 +571,10 @@ public static void DoesNotContain(object? notExpected, IEnumerable collection, s /// public static void DoesNotContain(T notExpected, IEnumerable collection, IEqualityComparer comparer, string? message = "", [CallerArgumentExpression(nameof(notExpected))] string notExpectedExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (collection.Contains(notExpected, comparer)) + ICollection snapshot = collection as ICollection ?? new List(collection); + if (snapshot.Contains(notExpected, comparer)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndCollectionExpression(message, notExpectedExpression, collectionExpression); - ThrowAssertDoesNotContainItemFailed(userMessage); + ThrowAssertDoesNotContainItemFailed(message, notExpectedExpression, collectionExpression, snapshot); } } @@ -598,12 +598,13 @@ public static void DoesNotContain(object? notExpected, IEnumerable collection, I CheckParameterNotNull(collection, "Assert.DoesNotContain", "collection"); CheckParameterNotNull(comparer, "Assert.DoesNotContain", "comparer"); - foreach (object? item in collection) + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (comparer.Equals(item, notExpected)) { - string userMessage = BuildUserMessageForNotExpectedExpressionAndCollectionExpression(message, notExpectedExpression, collectionExpression); - ThrowAssertDoesNotContainItemFailed(userMessage); + ThrowAssertDoesNotContainItemFailed(message, notExpectedExpression, collectionExpression, snapshot); } } } @@ -625,10 +626,10 @@ public static void DoesNotContain(object? notExpected, IEnumerable collection, I /// public static void DoesNotContain(Func predicate, IEnumerable collection, string? message = "", [CallerArgumentExpression(nameof(predicate))] string predicateExpression = "", [CallerArgumentExpression(nameof(collection))] string collectionExpression = "") { - if (collection.Any(predicate)) + ICollection snapshot = collection as ICollection ?? new List(collection); + if (snapshot.Any(predicate)) { - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertDoesNotContainPredicateFailed(userMessage); + ThrowAssertDoesNotContainPredicateFailed(message, predicateExpression, collectionExpression, snapshot); } } @@ -651,12 +652,13 @@ public static void DoesNotContain(Func predicate, IEnumerable col CheckParameterNotNull(collection, "Assert.DoesNotContain", "collection"); CheckParameterNotNull(predicate, "Assert.DoesNotContain", "predicate"); - foreach (object? item in collection) + ICollection snapshot = collection as ICollection ?? collection.Cast().ToList(); + + foreach (object? item in snapshot) { if (predicate(item)) { - string userMessage = BuildUserMessageForPredicateExpressionAndCollectionExpression(message, predicateExpression, collectionExpression); - ThrowAssertDoesNotContainPredicateFailed(userMessage); + ThrowAssertDoesNotContainPredicateFailed(message, predicateExpression, collectionExpression, snapshot); } } } @@ -730,9 +732,7 @@ public static void DoesNotContain(string substring, string value, StringComparis if (value.Contains(substring, comparisonType)) { - string userMessage = BuildUserMessageForSubstringExpressionAndValueExpression(message, substringExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DoesNotContainFail, value, substring, userMessage); - ThrowAssertFailed("Assert.DoesNotContain", finalMessage); + ThrowAssertStringDoesNotContainFailed(value, substring, message, substringExpression, valueExpression); } } @@ -771,73 +771,129 @@ public static void IsInRange(T minValue, T maxValue, T value, string? message if (value.CompareTo(minValue) < 0 || value.CompareTo(maxValue) > 0) { - string userMessage = BuildUserMessageForMinValueExpressionAndMaxValueExpressionAndValueExpression(message, minValueExpression, maxValueExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsInRangeFail, value, minValue, maxValue, userMessage); - ThrowAssertFailed("IsInRange", finalMessage); + ThrowAssertIsInRangeFailed(value, minValue, maxValue, message, minValueExpression, maxValueExpression, valueExpression); } } #endregion // IsInRange [DoesNotReturn] - private static void ThrowAssertSingleMatchFailed(int actualCount, string userMessage) + private static void ThrowAssertSingleMatchFailed(int actualCount, string? userMessage, string predicateExpression, string collectionExpression, IEnumerable? collectionValue = null) + { + string callSite = FormatCallSite("Assert.ContainsSingle", ("predicate", predicateExpression), ("collection", collectionExpression)); + string message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.ContainsSingleMatchFailNew, actualCount); + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } + + [DoesNotReturn] + private static void ThrowAssertContainsSingleFailed(int actualCount, string? userMessage, string collectionExpression, IEnumerable? collectionValue = null) + { + string callSite = FormatCallSite("Assert.ContainsSingle", ("collection", collectionExpression)); + string message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.ContainsSingleFailNew, actualCount); + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } + + [DoesNotReturn] + private static void ThrowAssertContainsItemFailed(string? userMessage, string expectedExpression, string collectionExpression, IEnumerable? collectionValue = null) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ContainsSingleMatchFailMsg, - userMessage, - actualCount); - ThrowAssertFailed("Assert.ContainsSingle", finalMessage); + string callSite = FormatCallSite("Assert.Contains", ("expected", expectedExpression), ("collection", collectionExpression)); + string message = FrameworkMessages.ContainsItemFailNew; + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertContainsSingleFailed(int actualCount, string userMessage) + private static void ThrowAssertContainsPredicateFailed(string? userMessage, string predicateExpression, string collectionExpression, IEnumerable? collectionValue = null) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ContainsSingleFailMsg, - userMessage, - actualCount); - ThrowAssertFailed("Assert.ContainsSingle", finalMessage); + string callSite = FormatCallSite("Assert.Contains", ("predicate", predicateExpression), ("collection", collectionExpression)); + string message = FrameworkMessages.ContainsPredicateFailNew; + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertContainsItemFailed(string userMessage) + private static void ThrowAssertDoesNotContainItemFailed(string? userMessage, string notExpectedExpression, string collectionExpression, IEnumerable? collectionValue = null) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ContainsItemFailMsg, - userMessage); - ThrowAssertFailed("Assert.Contains", finalMessage); + string callSite = FormatCallSite("Assert.DoesNotContain", ("notExpected", notExpectedExpression), ("collection", collectionExpression)); + string message = FrameworkMessages.DoesNotContainItemFailNew; + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } + + [DoesNotReturn] + private static void ThrowAssertDoesNotContainPredicateFailed(string? userMessage, string predicateExpression, string collectionExpression, IEnumerable? collectionValue = null) + { + string callSite = FormatCallSite("Assert.DoesNotContain", ("predicate", predicateExpression), ("collection", collectionExpression)); + string message = FrameworkMessages.DoesNotContainPredicateFailNew; + if (collectionValue is not null) + { + message += FormatCollectionParameter(collectionExpression, collectionValue); + } + + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertContainsPredicateFailed(string userMessage) + private static void ThrowAssertStringContainsFailed(string value, string substring, string? userMessage, string substringExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ContainsPredicateFailMsg, - userMessage); - ThrowAssertFailed("Assert.Contains", finalMessage); + string callSite = FormatCallSite("Assert.Contains", (nameof(substring), substringExpression), (nameof(value), valueExpression)); + string message = FrameworkMessages.ContainsStringFailNew; + message += FormatAlignedParameters( + (nameof(substring), FormatValue(substring)), + (nameof(value), FormatValue(value))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertDoesNotContainItemFailed(string userMessage) + private static void ThrowAssertStringDoesNotContainFailed(string value, string substring, string? userMessage, string substringExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.DoesNotContainItemFailMsg, - userMessage); - ThrowAssertFailed("Assert.DoesNotContain", finalMessage); + string callSite = FormatCallSite("Assert.DoesNotContain", (nameof(substring), substringExpression), (nameof(value), valueExpression)); + string message = FrameworkMessages.DoesNotContainStringFailNew; + message += FormatAlignedParameters( + (nameof(substring), FormatValue(substring)), + (nameof(value), FormatValue(value))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } [DoesNotReturn] - private static void ThrowAssertDoesNotContainPredicateFailed(string userMessage) + private static void ThrowAssertIsInRangeFailed(T value, T minValue, T maxValue, string? userMessage, string minValueExpression, string maxValueExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.DoesNotContainPredicateFailMsg, - userMessage); - ThrowAssertFailed("Assert.DoesNotContain", finalMessage); + string callSite = FormatCallSite("Assert.IsInRange", (nameof(value), valueExpression)); + string message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsInRangeFailNew, FormatValue(value), FormatValue(minValue), FormatValue(maxValue)); + message += FormatAlignedParameters( + ("range", $"[{FormatValue(minValue)}, {FormatValue(maxValue)}]"), + (nameof(value), FormatValue(value))); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Count.cs b/src/TestFramework/TestFramework/Assertions/Assert.Count.cs index 555d341686..47cf7483ea 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.Count.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.Count.cs @@ -20,6 +20,7 @@ public readonly struct AssertCountInterpolatedStringHandler private readonly StringBuilder? _builder; private readonly int _expectedCount; private readonly int _actualCount; + private readonly IEnumerable? _collection; public AssertCountInterpolatedStringHandler(int literalLength, int formattedCount, int count, IEnumerable collection, out bool shouldAppend) { @@ -29,6 +30,7 @@ public AssertCountInterpolatedStringHandler(int literalLength, int formattedCoun if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); + _collection = collection; } } @@ -40,6 +42,7 @@ public AssertCountInterpolatedStringHandler(int literalLength, int formattedCoun if (shouldAppend) { _builder = new StringBuilder(literalLength + formattedCount); + _collection = collection; } } @@ -47,8 +50,7 @@ internal void ComputeAssertion(string assertionName, string collectionExpression { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "collection", collectionExpression) + " "); - ThrowAssertCountFailed(assertionName, _expectedCount, _actualCount, _builder.ToString()); + ThrowAssertCountFailed(assertionName, _expectedCount, _actualCount, _collection!, _builder.ToString(), collectionExpression); } } @@ -115,8 +117,7 @@ internal void ComputeAssertion(string collectionExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "collection", collectionExpression) + " "); - ThrowAssertIsNotEmptyFailed(_builder.ToString()); + ThrowAssertIsNotEmptyFailed(_builder.ToString(), collectionExpression); } } @@ -202,8 +203,7 @@ public static void IsNotEmpty(IEnumerable collection, string? message = "" return; } - string userMessage = BuildUserMessageForCollectionExpression(message, collectionExpression); - ThrowAssertIsNotEmptyFailed(userMessage); + ThrowAssertIsNotEmptyFailed(message, collectionExpression); } /// @@ -222,8 +222,7 @@ public static void IsNotEmpty(IEnumerable collection, string? message = "", [Cal return; } - string userMessage = BuildUserMessageForCollectionExpression(message, collectionExpression); - ThrowAssertIsNotEmptyFailed(userMessage); + ThrowAssertIsNotEmptyFailed(message, collectionExpression); } #endregion // IsNotEmpty @@ -320,38 +319,39 @@ public static void IsEmpty(IEnumerable collection, string? message = "", [Caller private static void HasCount(string assertionName, int expected, IEnumerable collection, string? message, string collectionExpression) { - int actualCount = collection.Count(); - if (actualCount == expected) + // Materialize non-ICollection enumerables to prevent multiple enumeration + // that could yield different results or fail on second pass. + ICollection snapshot = collection as ICollection ?? new List(collection); + if (snapshot.Count == expected) { return; } - string userMessage = BuildUserMessageForCollectionExpression(message, collectionExpression); - ThrowAssertCountFailed(assertionName, expected, actualCount, userMessage); + ThrowAssertCountFailed(assertionName, expected, snapshot.Count, snapshot, message, collectionExpression); } private static void HasCount(string assertionName, int expected, IEnumerable collection, string? message, string collectionExpression) => HasCount(assertionName, expected, collection.Cast(), message, collectionExpression); [DoesNotReturn] - private static void ThrowAssertCountFailed(string assertionName, int expectedCount, int actualCount, string userMessage) + private static void ThrowAssertCountFailed(string assertionName, int expectedCount, int actualCount, IEnumerable collection, string? userMessage, string collectionExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.HasCountFailMsg, - userMessage, - expectedCount, - actualCount); - ThrowAssertFailed($"Assert.{assertionName}", finalMessage); + string callSite = FormatCallSite($"Assert.{assertionName}", ("collection", collectionExpression)); + string msg = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.HasCountFailNew, expectedCount, actualCount); + msg += FormatCollectionParameter(collectionExpression, collection); + msg += FormatAlignedParameters( + ("expected count", expectedCount.ToString(CultureInfo.InvariantCulture)), + ("actual count", actualCount.ToString(CultureInfo.InvariantCulture))); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsNotEmptyFailed(string userMessage) + private static void ThrowAssertIsNotEmptyFailed(string? userMessage, string collectionExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsNotEmptyFailMsg, - userMessage); - ThrowAssertFailed("Assert.IsNotEmpty", finalMessage); + string callSite = FormatCallSite("Assert.IsNotEmpty", ("collection", collectionExpression)); + string msg = FrameworkMessages.IsNotEmptyFailNew; + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.EndsWith.cs b/src/TestFramework/TestFramework/Assertions/Assert.EndsWith.cs index 772c1d1e48..5aec763303 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.EndsWith.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.EndsWith.cs @@ -76,9 +76,13 @@ public static void EndsWith([NotNull] string? expectedSuffix, [NotNull] string? CheckParameterNotNull(expectedSuffix, "Assert.EndsWith", "expectedSuffix"); if (!value.EndsWith(expectedSuffix, comparisonType)) { - string userMessage = BuildUserMessageForExpectedSuffixExpressionAndValueExpression(message, expectedSuffixExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.EndsWithFail, value, expectedSuffix, userMessage); - ThrowAssertFailed("Assert.EndsWith", finalMessage); + string callSite = FormatCallSite("Assert.EndsWith", (nameof(expectedSuffix), expectedSuffixExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.EndsWithFailNew; + msg += FormatAlignedParameters( + ("expected suffix", FormatValue(expectedSuffix)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } @@ -150,9 +154,13 @@ public static void DoesNotEndWith([NotNull] string? notExpectedSuffix, [NotNull] CheckParameterNotNull(notExpectedSuffix, "Assert.DoesNotEndWith", "notExpectedSuffix"); if (value.EndsWith(notExpectedSuffix, comparisonType)) { - string userMessage = BuildUserMessageForNotExpectedSuffixExpressionAndValueExpression(message, notExpectedSuffixExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DoesNotEndWithFail, value, notExpectedSuffix, userMessage); - ThrowAssertFailed("Assert.DoesNotEndWith", finalMessage); + string callSite = FormatCallSite("Assert.DoesNotEndWith", (nameof(notExpectedSuffix), notExpectedSuffixExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.DoesNotEndWithFailNew; + msg += FormatAlignedParameters( + ("unwanted suffix", FormatValue(notExpectedSuffix)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs b/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs index 3a3a4ebd24..80df01ea55 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.Fail.cs @@ -22,5 +22,5 @@ public sealed partial class Assert /// [DoesNotReturn] public static void Fail(string message = "") - => ThrowAssertFailed("Assert.Fail", BuildUserMessage(message)); + => ThrowAssertFailed("Assert.Fail", string.IsNullOrEmpty(message) ? null : message); } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IComparable.cs b/src/TestFramework/TestFramework/Assertions/Assert.IComparable.cs index a953f5cd33..8154f57ace 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IComparable.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IComparable.cs @@ -49,8 +49,7 @@ public static void IsGreaterThan(T lowerBound, T value, string? message = "", return; } - string userMessage = BuildUserMessageForLowerBoundExpressionAndValueExpression(message, lowerBoundExpression, valueExpression); - ThrowAssertIsGreaterThanFailed(lowerBound, value, userMessage); + ThrowAssertIsGreaterThanFailed(lowerBound, value, message, lowerBoundExpression, valueExpression); } #endregion // IsGreaterThan @@ -94,8 +93,7 @@ public static void IsGreaterThanOrEqualTo(T lowerBound, T value, string? mess return; } - string userMessage = BuildUserMessageForLowerBoundExpressionAndValueExpression(message, lowerBoundExpression, valueExpression); - ThrowAssertIsGreaterThanOrEqualToFailed(lowerBound, value, userMessage); + ThrowAssertIsGreaterThanOrEqualToFailed(lowerBound, value, message, lowerBoundExpression, valueExpression); } #endregion // IsGreaterThanOrEqualTo @@ -139,8 +137,7 @@ public static void IsLessThan(T upperBound, T value, string? message = "", [C return; } - string userMessage = BuildUserMessageForUpperBoundExpressionAndValueExpression(message, upperBoundExpression, valueExpression); - ThrowAssertIsLessThanFailed(upperBound, value, userMessage); + ThrowAssertIsLessThanFailed(upperBound, value, message, upperBoundExpression, valueExpression); } #endregion // IsLessThan @@ -184,8 +181,7 @@ public static void IsLessThanOrEqualTo(T upperBound, T value, string? message return; } - string userMessage = BuildUserMessageForUpperBoundExpressionAndValueExpression(message, upperBoundExpression, valueExpression); - ThrowAssertIsLessThanOrEqualToFailed(upperBound, value, userMessage); + ThrowAssertIsLessThanOrEqualToFailed(upperBound, value, message, upperBoundExpression, valueExpression); } #endregion // IsLessThanOrEqualTo @@ -221,15 +217,13 @@ public static void IsPositive(T value, string? message = "", [CallerArgumentE // Handle special case for floating point NaN values if (value is float.NaN) { - string userMessage = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsPositiveFailed(value, userMessage); + ThrowAssertIsPositiveFailed(value, message, valueExpression); return; } if (value is double.NaN) { - string userMessage = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsPositiveFailed(value, userMessage); + ThrowAssertIsPositiveFailed(value, message, valueExpression); return; } @@ -238,8 +232,7 @@ public static void IsPositive(T value, string? message = "", [CallerArgumentE return; } - string userMessage2 = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsPositiveFailed(value, userMessage2); + ThrowAssertIsPositiveFailed(value, message, valueExpression); } #endregion // IsPositive @@ -275,15 +268,13 @@ public static void IsNegative(T value, string? message = "", [CallerArgumentE // Handle special case for floating point NaN values if (value is float.NaN) { - string userMessage = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsNegativeFailed(value, userMessage); + ThrowAssertIsNegativeFailed(value, message, valueExpression); return; } if (value is double.NaN) { - string userMessage = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsNegativeFailed(value, userMessage); + ThrowAssertIsNegativeFailed(value, message, valueExpression); return; } @@ -292,79 +283,76 @@ public static void IsNegative(T value, string? message = "", [CallerArgumentE return; } - string userMessage2 = BuildUserMessageForValueExpression(message, valueExpression); - ThrowAssertIsNegativeFailed(value, userMessage2); + ThrowAssertIsNegativeFailed(value, message, valueExpression); } #endregion // IsNegative [DoesNotReturn] - private static void ThrowAssertIsGreaterThanFailed(T lowerBound, T value, string userMessage) + private static void ThrowAssertIsGreaterThanFailed(T lowerBound, T value, string? userMessage, string lowerBoundExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsGreaterThanFailMsg, - userMessage, - ReplaceNulls(lowerBound), - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsGreaterThan", finalMessage); + string callSite = FormatCallSite("Assert.IsGreaterThan", (nameof(lowerBound), lowerBoundExpression), (nameof(value), valueExpression)); + string msg = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsGreaterThanFailNew, FormatValue(value), FormatValue(lowerBound)); + msg += FormatAlignedParameters( + ("lower bound", FormatValue(lowerBound)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsGreaterThanOrEqualToFailed(T lowerBound, T value, string userMessage) + private static void ThrowAssertIsGreaterThanOrEqualToFailed(T lowerBound, T value, string? userMessage, string lowerBoundExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsGreaterThanOrEqualToFailMsg, - userMessage, - ReplaceNulls(lowerBound), - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsGreaterThanOrEqualTo", finalMessage); + string callSite = FormatCallSite("Assert.IsGreaterThanOrEqualTo", (nameof(lowerBound), lowerBoundExpression), (nameof(value), valueExpression)); + string msg = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsGreaterThanOrEqualToFailNew, FormatValue(value), FormatValue(lowerBound)); + msg += FormatAlignedParameters( + ("lower bound", FormatValue(lowerBound)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsLessThanFailed(T upperBound, T value, string userMessage) + private static void ThrowAssertIsLessThanFailed(T upperBound, T value, string? userMessage, string upperBoundExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsLessThanFailMsg, - userMessage, - ReplaceNulls(upperBound), - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsLessThan", finalMessage); + string callSite = FormatCallSite("Assert.IsLessThan", (nameof(upperBound), upperBoundExpression), (nameof(value), valueExpression)); + string msg = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsLessThanFailNew, FormatValue(value), FormatValue(upperBound)); + msg += FormatAlignedParameters( + ("upper bound", FormatValue(upperBound)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsLessThanOrEqualToFailed(T upperBound, T value, string userMessage) + private static void ThrowAssertIsLessThanOrEqualToFailed(T upperBound, T value, string? userMessage, string upperBoundExpression, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsLessThanOrEqualToFailMsg, - userMessage, - ReplaceNulls(upperBound), - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsLessThanOrEqualTo", finalMessage); + string callSite = FormatCallSite("Assert.IsLessThanOrEqualTo", (nameof(upperBound), upperBoundExpression), (nameof(value), valueExpression)); + string msg = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsLessThanOrEqualToFailNew, FormatValue(value), FormatValue(upperBound)); + msg += FormatAlignedParameters( + ("upper bound", FormatValue(upperBound)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsPositiveFailed(T value, string userMessage) + private static void ThrowAssertIsPositiveFailed(T value, string? userMessage, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsPositiveFailMsg, - userMessage, - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsPositive", finalMessage); + string callSite = FormatCallSite("Assert.IsPositive", (nameof(value), valueExpression)); + string msg = FrameworkMessages.IsPositiveFailNew; + msg += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } [DoesNotReturn] - private static void ThrowAssertIsNegativeFailed(T value, string userMessage) + private static void ThrowAssertIsNegativeFailed(T value, string? userMessage, string valueExpression) { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsNegativeFailMsg, - userMessage, - ReplaceNulls(value)); - ThrowAssertFailed("Assert.IsNegative", finalMessage); + string callSite = FormatCallSite("Assert.IsNegative", (nameof(value), valueExpression)); + string msg = FrameworkMessages.IsNegativeFailNew; + msg += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + msg = AppendUserMessage(msg, userMessage); + ThrowAssertFailed(callSite, msg); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsExactInstanceOfType.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsExactInstanceOfType.cs index 144f17cdbe..3b6f56aaaf 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsExactInstanceOfType.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IsExactInstanceOfType.cs @@ -38,8 +38,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsExactInstanceOfTypeFailed(_value, _expectedType, _builder.ToString()); + ThrowAssertIsExactInstanceOfTypeFailed(_value, _expectedType, _builder.ToString(), valueExpression); } } @@ -50,16 +49,11 @@ internal void ComputeAssertion(string valueExpression) #if NETCOREAPP3_1_OR_GREATER public void AppendFormatted(ReadOnlySpan value) => _builder!.Append(value); -#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads +#pragma warning disable RS0027 public void AppendFormatted(ReadOnlySpan value, int alignment = 0, string? format = null) => AppendFormatted(value.ToString(), alignment, format); -#pragma warning restore RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads +#pragma warning restore RS0027 #endif - // NOTE: All the overloads involving format and/or alignment are not super efficient. - // This code path is only for when an assert is failing, so that's not the common scenario - // and should be okay if not very optimized. - // A more efficient implementation that can be used for .NET 6 and later is to delegate the work to - // the BCL's StringBuilder.AppendInterpolatedStringHandler public void AppendFormatted(T value, string? format) => _builder!.AppendFormat(null, $"{{0:{format}}}", value); public void AppendFormatted(T value, int alignment) => _builder!.AppendFormat(null, $"{{0,{alignment}}}", value); @@ -68,13 +62,13 @@ internal void ComputeAssertion(string valueExpression) public void AppendFormatted(string? value) => _builder!.Append(value); -#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters -#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads +#pragma warning disable RS0026 +#pragma warning disable RS0027 public void AppendFormatted(string? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value); public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value); -#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters -#pragma warning restore RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads +#pragma warning restore RS0026 +#pragma warning restore RS0027 } [InterpolatedStringHandler] @@ -98,8 +92,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsExactInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString()); + ThrowAssertIsExactInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString(), valueExpression); } } @@ -160,8 +153,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNotExactInstanceOfTypeFailed(_value, _wrongType, _builder.ToString()); + ThrowAssertIsNotExactInstanceOfTypeFailed(_value, _wrongType, _builder.ToString(), valueExpression); } } @@ -220,8 +212,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNotExactInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString()); + ThrowAssertIsNotExactInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString(), valueExpression); } } @@ -291,7 +282,7 @@ public static void IsExactInstanceOfType([NotNull] object? value, [NotNull] Type { if (IsExactInstanceOfTypeFailing(value, expectedType)) { - ThrowAssertIsExactInstanceOfTypeFailed(value, expectedType, BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsExactInstanceOfTypeFailed(value, expectedType, message, valueExpression); } } @@ -329,20 +320,25 @@ private static bool IsExactInstanceOfTypeFailing([NotNullWhen(false)] object? va => expectedType is null || value is null || value.GetType() != expectedType; [DoesNotReturn] - private static void ThrowAssertIsExactInstanceOfTypeFailed(object? value, Type? expectedType, string userMessage) + private static void ThrowAssertIsExactInstanceOfTypeFailed(object? value, Type? expectedType, string? userMessage, string valueExpression) { - string finalMessage = userMessage; - if (expectedType is not null && value is not null) + string callSite = FormatCallSite("Assert.IsExactInstanceOfType", (nameof(value), valueExpression)); + string message; + + if (expectedType is null) + { + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsExactInstanceOfTypeFailNew, "null"); + message += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + message += Environment.NewLine + " expected type: null"; + } + else { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsExactInstanceOfFailMsg, - userMessage, - expectedType.ToString(), - value.GetType().ToString()); + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsExactInstanceOfTypeFailNew, FormatType(expectedType)); + message += Environment.NewLine + $" value: {(value is null ? "null" : FormatValueWithType(value))}"; } - ThrowAssertFailed("Assert.IsExactInstanceOfType", finalMessage); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } /// @@ -373,7 +369,7 @@ public static void IsNotExactInstanceOfType(object? value, [NotNull] Type? wrong { if (IsNotExactInstanceOfTypeFailing(value, wrongType)) { - ThrowAssertIsNotExactInstanceOfTypeFailed(value, wrongType, BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsNotExactInstanceOfTypeFailed(value, wrongType, message, valueExpression); } } @@ -405,19 +401,24 @@ private static bool IsNotExactInstanceOfTypeFailing(object? value, [NotNullWhen( (value is not null && value.GetType() == wrongType); [DoesNotReturn] - private static void ThrowAssertIsNotExactInstanceOfTypeFailed(object? value, Type? wrongType, string userMessage) + private static void ThrowAssertIsNotExactInstanceOfTypeFailed(object? value, Type? wrongType, string? userMessage, string valueExpression) { - string finalMessage = userMessage; - if (wrongType is not null) + string callSite = FormatCallSite("Assert.IsNotExactInstanceOfType", (nameof(value), valueExpression)); + string message; + + if (wrongType is null) + { + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotExactInstanceOfTypeFailNew, "null"); + message += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + message += Environment.NewLine + " wrong type: null"; + } + else { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsNotExactInstanceOfFailMsg, - userMessage, - wrongType.ToString(), - value!.GetType().ToString()); + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotExactInstanceOfTypeFailNew, FormatType(wrongType)); + message += Environment.NewLine + $" value: {FormatValueWithType(value!)}"; } - ThrowAssertFailed("Assert.IsNotExactInstanceOfType", finalMessage); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsInstanceOfType.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsInstanceOfType.cs index bdd68f1607..220ed86a54 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsInstanceOfType.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IsInstanceOfType.cs @@ -38,8 +38,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsInstanceOfTypeFailed(_value, _expectedType, _builder.ToString()); + ThrowAssertIsInstanceOfTypeFailed(_value, _expectedType, _builder.ToString(), valueExpression); } } @@ -98,8 +97,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString()); + ThrowAssertIsInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString(), valueExpression); } } @@ -160,8 +158,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNotInstanceOfTypeFailed(_value, _wrongType, _builder.ToString()); + ThrowAssertIsNotInstanceOfTypeFailed(_value, _wrongType, _builder.ToString(), valueExpression); } } @@ -220,8 +217,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNotInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString()); + ThrowAssertIsNotInstanceOfTypeFailed(_value, typeof(TArg), _builder.ToString(), valueExpression); } } @@ -292,7 +288,7 @@ public static void IsInstanceOfType([NotNull] object? value, [NotNull] Type? exp { if (IsInstanceOfTypeFailing(value, expectedType)) { - ThrowAssertIsInstanceOfTypeFailed(value, expectedType, BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsInstanceOfTypeFailed(value, expectedType, message, valueExpression); } } @@ -331,20 +327,25 @@ private static bool IsInstanceOfTypeFailing([NotNullWhen(false)] object? value, => expectedType == null || value == null || !expectedType.IsInstanceOfType(value); [DoesNotReturn] - private static void ThrowAssertIsInstanceOfTypeFailed(object? value, Type? expectedType, string userMessage) + private static void ThrowAssertIsInstanceOfTypeFailed(object? value, Type? expectedType, string? userMessage, string valueExpression) { - string finalMessage = userMessage; - if (expectedType is not null && value is not null) + string callSite = FormatCallSite("Assert.IsInstanceOfType", (nameof(value), valueExpression)); + string message; + + if (expectedType is null) + { + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsInstanceOfTypeFailNew, "null"); + message += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + message += Environment.NewLine + " expected type: null"; + } + else { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsInstanceOfFailMsg, - userMessage, - expectedType.ToString(), - value.GetType().ToString()); + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsInstanceOfTypeFailNew, FormatType(expectedType)); + message += Environment.NewLine + $" value: {(value is null ? "null" : FormatValueWithType(value))}"; } - ThrowAssertFailed("Assert.IsInstanceOfType", finalMessage); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } /// @@ -376,7 +377,7 @@ public static void IsNotInstanceOfType(object? value, [NotNull] Type? wrongType, { if (IsNotInstanceOfTypeFailing(value, wrongType)) { - ThrowAssertIsNotInstanceOfTypeFailed(value, wrongType, BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsNotInstanceOfTypeFailed(value, wrongType, message, valueExpression); } } @@ -409,19 +410,24 @@ private static bool IsNotInstanceOfTypeFailing(object? value, [NotNullWhen(false (value is not null && wrongType.IsInstanceOfType(value)); [DoesNotReturn] - private static void ThrowAssertIsNotInstanceOfTypeFailed(object? value, Type? wrongType, string userMessage) + private static void ThrowAssertIsNotInstanceOfTypeFailed(object? value, Type? wrongType, string? userMessage, string valueExpression) { - string finalMessage = userMessage; - if (wrongType is not null) + string callSite = FormatCallSite("Assert.IsNotInstanceOfType", (nameof(value), valueExpression)); + string message; + + if (wrongType is null) + { + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotInstanceOfTypeFailNew, "null"); + message += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + message += Environment.NewLine + " wrong type: null"; + } + else { - finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.IsNotInstanceOfFailMsg, - userMessage, - wrongType.ToString(), - value!.GetType().ToString()); + message = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotInstanceOfTypeFailNew, FormatType(wrongType)); + message += Environment.NewLine + $" value: {FormatValueWithType(value!)}"; } - ThrowAssertFailed("Assert.IsNotInstanceOfType", finalMessage); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs index fd6db5b3d4..3a8f0cbe7a 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs @@ -22,9 +22,11 @@ public sealed partial class Assert public readonly struct AssertIsNullInterpolatedStringHandler { private readonly StringBuilder? _builder; + private readonly object? _value; public AssertIsNullInterpolatedStringHandler(int literalLength, int formattedCount, object? value, out bool shouldAppend) { + _value = value; shouldAppend = IsNullFailing(value); if (shouldAppend) { @@ -36,8 +38,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNullFailed(_builder.ToString()); + ThrowAssertIsNullFailed(_value, _builder.ToString(), valueExpression); } } @@ -90,8 +91,7 @@ internal void ComputeAssertion(string valueExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "value", valueExpression) + " "); - ThrowAssertIsNotNullFailed(_builder.ToString()); + ThrowAssertIsNotNullFailed(_builder.ToString(), valueExpression); } } @@ -152,14 +152,21 @@ public static void IsNull(object? value, string? message = "", [CallerArgumentEx { if (IsNullFailing(value)) { - ThrowAssertIsNullFailed(BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsNullFailed(value, message, valueExpression); } } private static bool IsNullFailing(object? value) => value is not null; - private static void ThrowAssertIsNullFailed(string? message) - => ThrowAssertFailed("Assert.IsNull", message); + [DoesNotReturn] + private static void ThrowAssertIsNullFailed(object? value, string? userMessage, string valueExpression) + { + string callSite = FormatCallSite("Assert.IsNull", (nameof(value), valueExpression)); + string message = FrameworkMessages.IsNullFailNew; + message += Environment.NewLine + FormatParameter(nameof(value), valueExpression, value); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } /// #pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578 @@ -191,13 +198,18 @@ public static void IsNotNull([NotNull] object? value, string? message = "", [Cal { if (IsNotNullFailing(value)) { - ThrowAssertIsNotNullFailed(BuildUserMessageForValueExpression(message, valueExpression)); + ThrowAssertIsNotNullFailed(message, valueExpression); } } private static bool IsNotNullFailing([NotNullWhen(false)] object? value) => value is null; [DoesNotReturn] - private static void ThrowAssertIsNotNullFailed(string? message) - => ThrowAssertFailed("Assert.IsNotNull", message); + private static void ThrowAssertIsNotNullFailed(string? userMessage, string valueExpression) + { + string callSite = FormatCallSite("Assert.IsNotNull", ("value", valueExpression)); + string message = FrameworkMessages.IsNotNullFailNew; + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs index 1c31f3add1..18ba993561 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs @@ -22,9 +22,11 @@ public sealed partial class Assert public readonly struct AssertIsTrueInterpolatedStringHandler { private readonly StringBuilder? _builder; + private readonly bool? _condition; public AssertIsTrueInterpolatedStringHandler(int literalLength, int formattedCount, bool? condition, out bool shouldAppend) { + _condition = condition; shouldAppend = IsTrueFailing(condition); if (shouldAppend) { @@ -36,8 +38,7 @@ internal void ComputeAssertion(string conditionExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "condition", conditionExpression) + " "); - ThrowAssertIsTrueFailed(_builder.ToString()); + ThrowAssertIsTrueFailed(_condition, _builder.ToString(), conditionExpression); } } @@ -74,9 +75,11 @@ internal void ComputeAssertion(string conditionExpression) public readonly struct AssertIsFalseInterpolatedStringHandler { private readonly StringBuilder? _builder; + private readonly bool? _condition; public AssertIsFalseInterpolatedStringHandler(int literalLength, int formattedCount, bool? condition, out bool shouldAppend) { + _condition = condition; shouldAppend = IsFalseFailing(condition); if (shouldAppend) { @@ -88,8 +91,7 @@ internal void ComputeAssertion(string conditionExpression) { if (_builder is not null) { - _builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "condition", conditionExpression) + " "); - ThrowAssertIsFalseFailed(_builder.ToString()); + ThrowAssertIsFalseFailed(_condition, _builder.ToString(), conditionExpression); } } @@ -150,15 +152,22 @@ public static void IsTrue([DoesNotReturnIf(false)] bool? condition, string? mess { if (IsTrueFailing(condition)) { - ThrowAssertIsTrueFailed(BuildUserMessageForConditionExpression(message, conditionExpression)); + ThrowAssertIsTrueFailed(condition, message, conditionExpression); } } private static bool IsTrueFailing(bool? condition) => condition is false or null; - private static void ThrowAssertIsTrueFailed(string? message) - => ThrowAssertFailed("Assert.IsTrue", message); + [DoesNotReturn] + private static void ThrowAssertIsTrueFailed(bool? condition, string? userMessage, string conditionExpression) + { + string callSite = FormatCallSite("Assert.IsTrue", (nameof(condition), conditionExpression)); + string message = FrameworkMessages.IsTrueFailNew; + message += Environment.NewLine + FormatParameter(nameof(condition), conditionExpression, condition); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } /// #pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578 @@ -188,7 +197,7 @@ public static void IsFalse([DoesNotReturnIf(true)] bool? condition, string? mess { if (IsFalseFailing(condition)) { - ThrowAssertIsFalseFailed(BuildUserMessageForConditionExpression(message, conditionExpression)); + ThrowAssertIsFalseFailed(condition, message, conditionExpression); } } @@ -196,6 +205,12 @@ private static bool IsFalseFailing(bool? condition) => condition is true or null; [DoesNotReturn] - private static void ThrowAssertIsFalseFailed(string userMessage) - => ThrowAssertFailed("Assert.IsFalse", userMessage); + private static void ThrowAssertIsFalseFailed(bool? condition, string? userMessage, string conditionExpression) + { + string callSite = FormatCallSite("Assert.IsFalse", (nameof(condition), conditionExpression)); + string message = FrameworkMessages.IsFalseFailNew; + message += Environment.NewLine + FormatParameter(nameof(condition), conditionExpression, condition); + message = AppendUserMessage(message, userMessage); + ThrowAssertFailed(callSite, message); + } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.Matches.cs b/src/TestFramework/TestFramework/Assertions/Assert.Matches.cs index b204970b6d..f2eff640ef 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.Matches.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.Matches.cs @@ -44,9 +44,13 @@ public static void MatchesRegex([NotNull] Regex? pattern, [NotNull] string? valu if (!pattern.IsMatch(value)) { - string userMessage = BuildUserMessageForPatternExpressionAndValueExpression(message, patternExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsMatchFail, value, pattern, userMessage); - ThrowAssertFailed("Assert.MatchesRegex", finalMessage); + string callSite = FormatCallSite("Assert.MatchesRegex", (nameof(pattern), patternExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.MatchesRegexFailNew; + msg += FormatAlignedParameters( + (nameof(pattern), FormatValue(pattern)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } @@ -120,9 +124,13 @@ public static void DoesNotMatchRegex([NotNull] Regex? pattern, [NotNull] string? if (pattern.IsMatch(value)) { - string userMessage = BuildUserMessageForPatternExpressionAndValueExpression(message, patternExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotMatchFail, value, pattern, userMessage); - ThrowAssertFailed("Assert.DoesNotMatchRegex", finalMessage); + string callSite = FormatCallSite("Assert.DoesNotMatchRegex", (nameof(pattern), patternExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.DoesNotMatchRegexFailNew; + msg += FormatAlignedParameters( + (nameof(pattern), FormatValue(pattern)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.StartsWith.cs b/src/TestFramework/TestFramework/Assertions/Assert.StartsWith.cs index 6f5c728535..2695d15ae1 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.StartsWith.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.StartsWith.cs @@ -76,9 +76,13 @@ public static void StartsWith([NotNull] string? expectedPrefix, [NotNull] string CheckParameterNotNull(expectedPrefix, "Assert.StartsWith", "expectedPrefix"); if (!value.StartsWith(expectedPrefix, comparisonType)) { - string userMessage = BuildUserMessageForExpectedPrefixExpressionAndValueExpression(message, expectedPrefixExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.StartsWithFail, value, expectedPrefix, userMessage); - ThrowAssertFailed("Assert.StartsWith", finalMessage); + string callSite = FormatCallSite("Assert.StartsWith", (nameof(expectedPrefix), expectedPrefixExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.StartsWithFailNew; + msg += FormatAlignedParameters( + ("expected prefix", FormatValue(expectedPrefix)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } @@ -148,9 +152,13 @@ public static void DoesNotStartWith([NotNull] string? notExpectedPrefix, [NotNul CheckParameterNotNull(notExpectedPrefix, "Assert.DoesNotStartWith", "notExpectedPrefix"); if (value.StartsWith(notExpectedPrefix, comparisonType)) { - string userMessage = BuildUserMessageForNotExpectedPrefixExpressionAndValueExpression(message, notExpectedPrefixExpression, valueExpression); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.DoesNotStartWithFail, value, notExpectedPrefix, userMessage); - ThrowAssertFailed("Assert.DoesNotStartWith", finalMessage); + string callSite = FormatCallSite("Assert.DoesNotStartWith", (nameof(notExpectedPrefix), notExpectedPrefixExpression), (nameof(value), valueExpression)); + string msg = FrameworkMessages.DoesNotStartWithFailNew; + msg += FormatAlignedParameters( + ("unwanted prefix", FormatValue(notExpectedPrefix)), + (nameof(value), FormatValue(value))); + msg = AppendUserMessage(msg, message); + ThrowAssertFailed(callSite, msg); } } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.That.cs b/src/TestFramework/TestFramework/Assertions/Assert.That.cs index e13c803967..a7b8a072e7 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.That.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.That.cs @@ -36,23 +36,116 @@ public static void That(Expression> condition, string? message = null return; } - var sb = new StringBuilder(); string expressionText = conditionExpression ?? throw new ArgumentNullException(nameof(conditionExpression)); - sb.AppendLine(string.Format(CultureInfo.InvariantCulture, FrameworkMessages.AssertThatFailedFormat, expressionText)); - if (!string.IsNullOrWhiteSpace(message)) - { - sb.AppendLine(string.Format(CultureInfo.InvariantCulture, FrameworkMessages.AssertThatMessageFormat, message)); - } + + // Strip the lambda wrapper "() => " since CallerArgumentExpression captures + // the full argument including the lambda syntax, but the user only cares about + // the condition expression itself. + string displayExpression = expressionText.StartsWith("() => ", StringComparison.Ordinal) + ? expressionText.Substring(6) + : expressionText; + + string callSite = $"Assert.That({Assert.TruncateExpression(displayExpression)})"; + string msg = BuildExpressionAwareMessage(condition.Body); string details = ExtractDetails(condition.Body); if (!string.IsNullOrWhiteSpace(details)) { - sb.AppendLine(FrameworkMessages.AssertThatDetailsPrefix); - sb.AppendLine(details); + msg += Environment.NewLine + details.TrimEnd(); } - throw new AssertFailedException(sb.ToString().TrimEnd()); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed(callSite, msg); + } + } + + private static string BuildExpressionAwareMessage(Expression body) + { + switch (body) + { + // Binary comparisons: x == y, x != y, x > y, etc. + case BinaryExpression binary when body.NodeType + is ExpressionType.Equal + or ExpressionType.NotEqual + or ExpressionType.GreaterThan + or ExpressionType.GreaterThanOrEqual + or ExpressionType.LessThan + or ExpressionType.LessThanOrEqual: + return BuildComparisonMessage(binary); + + // Negation: !flag, !condition + case UnaryExpression unary when body.NodeType == ExpressionType.Not + && unary.Operand is not MethodCallExpression: + string innerName = GetCleanMemberName(unary.Operand); + return $"Expected {innerName} to be false."; + + // Method calls: text.StartsWith("x"), list.Contains(item), etc. + case MethodCallExpression methodCall: + return BuildMethodCallMessage(methodCall); + + // Bool member access: user.IsActive, flag + case MemberExpression: + string memberName = GetCleanMemberName(body); + return $"Expected {memberName} to be true."; + + default: + return FrameworkMessages.IsTrueFailNew; + } + } + + private static string BuildComparisonMessage(BinaryExpression binary) + { + string leftValue = TryEvaluateFormatted(binary.Left); + string rightValue = TryEvaluateFormatted(binary.Right); + + return binary.NodeType switch + { + ExpressionType.Equal => $"Expected {leftValue} to equal {rightValue}.", + ExpressionType.NotEqual => $"Expected {leftValue} to not equal {rightValue}.", + ExpressionType.GreaterThan => $"Expected {leftValue} to be greater than {rightValue}.", + ExpressionType.GreaterThanOrEqual => $"Expected {leftValue} to be greater than or equal to {rightValue}.", + ExpressionType.LessThan => $"Expected {leftValue} to be less than {rightValue}.", + ExpressionType.LessThanOrEqual => $"Expected {leftValue} to be less than or equal to {rightValue}.", + _ => FrameworkMessages.IsTrueFailNew, + }; + } + + private static string BuildMethodCallMessage(MethodCallExpression methodCall) + { + string methodName = methodCall.Method.Name; + + // String-specific methods + if (methodCall.Object is not null && methodCall.Object.Type == typeof(string)) + { + return methodName switch + { + "StartsWith" => FrameworkMessages.StartsWithFailNew, + "EndsWith" => FrameworkMessages.EndsWithFailNew, + nameof(string.Contains) => FrameworkMessages.ContainsStringFailNew, + _ => FrameworkMessages.IsTrueFailNew, + }; + } + + return methodName switch + { + nameof(string.Contains) => FrameworkMessages.ContainsItemFailNew, + "All" => FrameworkMessages.AllMatchPredicateFailNew, + "Any" => FrameworkMessages.ContainsPredicateFailNew, + _ => FrameworkMessages.IsTrueFailNew, + }; + } + + private static string TryEvaluateFormatted(Expression expr) + { + try + { + object? value = Expression.Lambda(expr).Compile().DynamicInvoke(); + return FormatValue(value); + } + catch (Exception) + { + return GetCleanMemberName(expr); } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs b/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs index b5478a28a6..e4b2151484 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.ThrowsException.cs @@ -42,8 +42,7 @@ internal TException ComputeAssertion(string actionExpression) { if (_state.FailAction is not null) { - _builder!.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "action", actionExpression) + " "); - _state.FailAction(_builder!.ToString()); + _state.FailAction(_builder!.ToString(), actionExpression); } else { @@ -113,8 +112,7 @@ internal TException ComputeAssertion(string actionExpression) { if (_state.FailAction is not null) { - _builder!.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, "action", actionExpression) + " "); - _state.FailAction(_builder!.ToString()); + _state.FailAction(_builder!.ToString(), actionExpression); } else { @@ -327,7 +325,7 @@ private static TException ThrowsException(Action action, bool isStri ThrowsExceptionState state = IsThrowsFailing(action, isStrictType, assertMethodName); if (state.FailAction is not null) { - state.FailAction(BuildUserMessageForActionExpression(message, actionExpression)); + state.FailAction(message ?? string.Empty, actionExpression); } else { @@ -347,7 +345,7 @@ private static TException ThrowsException(Action action, bool isStri ThrowsExceptionState state = IsThrowsFailing(action, isStrictType, assertMethodName); if (state.FailAction is not null) { - state.FailAction(BuildUserMessageForActionExpression(messageBuilder(state.ExceptionThrown), actionExpression)); + state.FailAction(messageBuilder(state.ExceptionThrown), actionExpression); } else { @@ -483,7 +481,7 @@ private static async Task ThrowsExceptionAsync(Func(action, isStrictType, assertMethodName).ConfigureAwait(false); if (state.FailAction is not null) { - state.FailAction(BuildUserMessageForActionExpression(message, actionExpression)); + state.FailAction(message ?? string.Empty, actionExpression); } else { @@ -503,7 +501,7 @@ private static async Task ThrowsExceptionAsync(Func(action, isStrictType, assertMethodName).ConfigureAwait(false); if (state.FailAction is not null) { - state.FailAction(BuildUserMessageForActionExpression(messageBuilder(state.ExceptionThrown), actionExpression)); + state.FailAction(messageBuilder(state.ExceptionThrown), actionExpression); } else { @@ -530,27 +528,25 @@ private static async Task IsThrowsAsyncFailingAsync + (userMessage, actionExpr) => { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.WrongExceptionThrown, - userMessage, - typeof(TException), - ex.GetType()); - ThrowAssertFailed("Assert." + assertMethodName, finalMessage); + string msg = FrameworkMessages.WrongExceptionThrownNew; + msg += FormatExpressionParameter(nameof(action), actionExpr); + msg += Environment.NewLine + $" expected exception type: {FormatType(typeof(TException))}"; + msg += Environment.NewLine + $" actual exception type: {FormatType(ex.GetType())}"; + msg = AppendUserMessage(msg, string.IsNullOrEmpty(userMessage) ? null : userMessage); + ThrowAssertFailed("Assert." + assertMethodName, msg); }, ex); } return ThrowsExceptionState.CreateFailingState( - failAction: userMessage => + failAction: (userMessage, actionExpr) => { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.NoExceptionThrown, - userMessage, - typeof(TException)); - ThrowAssertFailed("Assert." + assertMethodName, finalMessage); + string msg = FrameworkMessages.NoExceptionThrownNew; + msg += FormatExpressionParameter(nameof(action), actionExpr); + msg += Environment.NewLine + $" expected exception type: {FormatType(typeof(TException))}"; + msg = AppendUserMessage(msg, string.IsNullOrEmpty(userMessage) ? null : userMessage); + ThrowAssertFailed("Assert." + assertMethodName, msg); }, null); } @@ -570,27 +566,25 @@ private static ThrowsExceptionState IsThrowsFailing(Action action, b return isExceptionOfType ? ThrowsExceptionState.CreateNotFailingState(ex) : ThrowsExceptionState.CreateFailingState( - userMessage => + (userMessage, actionExpr) => { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.WrongExceptionThrown, - userMessage, - typeof(TException), - ex.GetType()); - ThrowAssertFailed("Assert." + assertMethodName, finalMessage); + string msg = FrameworkMessages.WrongExceptionThrownNew; + msg += FormatExpressionParameter(nameof(action), actionExpr); + msg += Environment.NewLine + $" expected exception type: {FormatType(typeof(TException))}"; + msg += Environment.NewLine + $" actual exception type: {FormatType(ex.GetType())}"; + msg = AppendUserMessage(msg, string.IsNullOrEmpty(userMessage) ? null : userMessage); + ThrowAssertFailed("Assert." + assertMethodName, msg); }, ex); } return ThrowsExceptionState.CreateFailingState( - failAction: userMessage => + failAction: (userMessage, actionExpr) => { - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.NoExceptionThrown, - userMessage, - typeof(TException)); - ThrowAssertFailed("Assert." + assertMethodName, finalMessage); + string msg = FrameworkMessages.NoExceptionThrownNew; + msg += FormatExpressionParameter(nameof(action), actionExpr); + msg += Environment.NewLine + $" expected exception type: {FormatType(typeof(TException))}"; + msg = AppendUserMessage(msg, string.IsNullOrEmpty(userMessage) ? null : userMessage); + ThrowAssertFailed("Assert." + assertMethodName, msg); }, null); } @@ -598,9 +592,9 @@ private readonly struct ThrowsExceptionState { public Exception? ExceptionThrown { get; } - public Action? FailAction { get; } + public Action? FailAction { get; } - private ThrowsExceptionState(Exception? exceptionThrown, Action? failAction) + private ThrowsExceptionState(Exception? exceptionThrown, Action? failAction) { // If the assert is failing, failAction should be non-null, and exceptionWhenNotFailing may or may not be null. // If the assert is not failing, exceptionWhenNotFailing should be non-null, and failAction should be null. @@ -608,7 +602,7 @@ private ThrowsExceptionState(Exception? exceptionThrown, Action? failAct FailAction = failAction; } - public static ThrowsExceptionState CreateFailingState(Action failAction, Exception? exceptionThrown) + public static ThrowsExceptionState CreateFailingState(Action failAction, Exception? exceptionThrown) => new(exceptionThrown, failAction); public static ThrowsExceptionState CreateNotFailingState(Exception exception) diff --git a/src/TestFramework/TestFramework/Assertions/Assert.cs b/src/TestFramework/TestFramework/Assertions/Assert.cs index 4a832186af..6b2f8c42d3 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.cs @@ -50,8 +50,11 @@ internal static void ThrowAssertFailed(string assertionName, string? message) } } - throw new AssertFailedException( - string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AssertionFailed, assertionName, message)); + string formattedMessage = string.IsNullOrEmpty(message) + ? assertionName + : assertionName + Environment.NewLine + message; + + throw new AssertFailedException(formattedMessage); } private static bool ShouldLaunchDebugger() @@ -74,125 +77,441 @@ private static bool ShouldLaunchDebugger() internal static string BuildUserMessage(string? format) => format ?? string.Empty; - private static string BuildUserMessageForSingleExpression(string? format, string callerArgExpression, string parameterName) + /// + /// Checks the parameter for valid conditions. + /// + /// + /// The parameter. + /// + /// + /// The assertion Name. + /// + /// + /// parameter name. + /// + internal static void CheckParameterNotNull([NotNull] object? param, string assertionName, string parameterName) + { + if (param is null) + { + string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.NullParameterToAssert, parameterName); + ThrowAssertFailed(assertionName, finalMessage); + } + } + + internal static string ReplaceNulls(object? input) + => input?.ToString() ?? string.Empty; + + internal static string FormatValue(T? value, int maxLength = 256) { - string userMessage = BuildUserMessage(format); - if (string.IsNullOrEmpty(callerArgExpression)) + if (value is null) + { + return "null"; + } + + if (value is string s) + { + return EscapeNewlines(Truncate($"\"{s}\"", maxLength)); + } + + // For collections, show a preview with element values + if (value is IEnumerable enumerable) { - return userMessage; + return FormatCollectionPreview(enumerable); } - string callerArgMessagePart = string.Format(CultureInfo.InvariantCulture, FrameworkMessages.CallerArgumentExpressionSingleParameterMessage, parameterName, callerArgExpression); - return string.IsNullOrEmpty(userMessage) - ? callerArgMessagePart - : $"{callerArgMessagePart} {userMessage}"; + // Always use the runtime type for non-null values so that interface/base-class + // typed parameters still resolve the actual overridden ToString(). + Type type = value.GetType(); + + if (type.IsPrimitive || value is decimal or DateTime or DateTimeOffset + or TimeSpan or Guid or Enum) + { + string formatted = EscapeNewlines(Truncate(value.ToString() ?? string.Empty, maxLength)); + string suffix = GetNumericTypeSuffix(value); + return suffix.Length > 0 ? formatted + suffix : formatted; + } + + MethodInfo? toStringMethod = type.GetMethod(nameof(ToString), BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null); + if (toStringMethod is not null + && toStringMethod.DeclaringType != typeof(object) + && toStringMethod.DeclaringType != typeof(ValueType)) + { + try + { + return EscapeNewlines(Truncate(value.ToString() ?? string.Empty, maxLength)); + } + catch (Exception) + { + // Fall through to type name display if ToString throws + } + } + + // No useful ToString - just return the type name + return FormatType(type); + } + + /// + /// Returns the C# literal suffix for numeric types where the type + /// is not the default for its category (int for integers, double for + /// floating-point). Returns empty string for int, double, and + /// non-numeric types. + /// + private static string GetNumericTypeSuffix(T value) => value switch + { + long => "L", + ulong => "UL", + uint => "U", + float => "f", + decimal => "m", + _ => string.Empty, + }; + + internal static string FormatType(Type type) + { + string typeName = type.FullName ?? type.Name; + return $"<{typeName}>"; + } + + internal static string FormatValueWithType(object value) + { + string formattedValue = FormatValue(value); + string formattedType = FormatType(value.GetType()); + + // When FormatValue already returned the type name (e.g. ), + // don't repeat it. + return formattedValue == formattedType + ? formattedValue + : $"{formattedValue} ({formattedType})"; } - private static string BuildUserMessageForTwoExpressions(string? format, string callerArgExpression1, string parameterName1, string callerArgExpression2, string parameterName2) + internal static string TruncateExpression(string expression, int maxLength = 100) + => expression.Length <= maxLength + ? expression +#if NETCOREAPP3_1_OR_GREATER + : string.Concat(expression.AsSpan(0, maxLength), "..."); +#else + : expression.Substring(0, maxLength) + "..."; +#endif + + private static string Truncate(string value, int maxLength) + => value.Length <= maxLength + ? value +#if NETCOREAPP3_1_OR_GREATER + : string.Concat(value.AsSpan(0, maxLength), "... ", (value.Length - maxLength).ToString(CultureInfo.InvariantCulture), " more"); +#else + : value.Substring(0, maxLength) + $"... {value.Length - maxLength} more"; +#endif + + private static string EscapeNewlines(string value) + => value.Contains('\n') || value.Contains('\r') + ? value.Replace("\r\n", "\\r\\n").Replace("\n", "\\n").Replace("\r", "\\r") + : value; + + private static bool IsExpressionRedundant(string expression, string formattedValue) { - string userMessage = BuildUserMessage(format); - if (string.IsNullOrEmpty(callerArgExpression1) || string.IsNullOrEmpty(callerArgExpression2)) + if (string.IsNullOrEmpty(expression)) + { + return true; + } + + // Exact match: expression "5" == formattedValue "5" + if (expression == formattedValue) { - return userMessage; + return true; } - string callerArgMessagePart = string.Format(CultureInfo.InvariantCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, parameterName1, callerArgExpression1, parameterName2, callerArgExpression2); - return string.IsNullOrEmpty(userMessage) - ? callerArgMessagePart - : $"{callerArgMessagePart} {userMessage}"; + // Null literal: expression "null" vs formattedValue "null" + if (expression is "null" && formattedValue is "null") + { + return true; + } + + // Boolean/true/false: expression "true" vs formattedValue "True" + if (string.Equals(expression, formattedValue, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + // Numeric literal in different notation (e.g., "100E-2" vs "1") + if (double.TryParse(expression, NumberStyles.Any, CultureInfo.InvariantCulture, out double exprNum) + && double.TryParse(formattedValue, NumberStyles.Any, CultureInfo.InvariantCulture, out double fmtNum) + && exprNum == fmtNum) + { + return true; + } + + // C# string literal expression: @"\d+" or "\d+" vs formattedValue \d+ + // Strip the string literal syntax and compare the inner content + string? innerContent = TryExtractStringLiteralContent(expression); + return innerContent is not null && innerContent == formattedValue; } - private static string BuildUserMessageForThreeExpressions(string? format, string callerArgExpression1, string parameterName1, string callerArgExpression2, string parameterName2, string callerArgExpression3, string parameterName3) + /// + /// Tries to extract the string content from a C# string literal expression. + /// Returns the inner string value for @"..." and "..." literals, or null if not a string literal. + /// + private static string? TryExtractStringLiteralContent(string expression) { - string userMessage = BuildUserMessage(format); - if (string.IsNullOrEmpty(callerArgExpression1) || string.IsNullOrEmpty(callerArgExpression2) || string.IsNullOrEmpty(callerArgExpression3)) + // Verbatim string: @"content" + if (expression.Length >= 3 && expression[0] == '@' && expression[1] == '"' && expression[expression.Length - 1] == '"') { - return userMessage; + return expression.Substring(2, expression.Length - 3).Replace("\"\"", "\""); } - string callerArgMessagePart = string.Format(CultureInfo.InvariantCulture, FrameworkMessages.CallerArgumentExpressionThreeParametersMessage, parameterName1, callerArgExpression1, parameterName2, callerArgExpression2, parameterName3, callerArgExpression3); - return string.IsNullOrEmpty(userMessage) - ? callerArgMessagePart - : $"{callerArgMessagePart} {userMessage}"; + // Regular string: "content" + if (expression.Length >= 2 && expression[0] == '"' && expression[expression.Length - 1] == '"') + { + return expression.Substring(1, expression.Length - 2); + } + + // Not a string literal + return null; } - private static string BuildUserMessageForConditionExpression(string? format, string conditionExpression) - => BuildUserMessageForSingleExpression(format, conditionExpression, "condition"); + /// + /// Checks if the expression is a typed numeric literal (e.g., 1.0f, 1.1d, 0.001m, 2L) + /// or a well-known numeric constant (float.NaN, double.NaN) that is a more informative + /// representation than the plain ToString() value. + /// + private static bool IsExpressionMoreSpecificNumericLiteral(string expression, string formattedValue) + { + if (string.IsNullOrEmpty(expression) || expression.Length < 2) + { + return false; + } - private static string BuildUserMessageForValueExpression(string? format, string valueExpression) - => BuildUserMessageForSingleExpression(format, valueExpression, "value"); + // Well-known numeric constants: float.NaN, double.NaN, float.PositiveInfinity, etc. + if (expression.StartsWith("float.", StringComparison.Ordinal) || expression.StartsWith("double.", StringComparison.Ordinal)) + { + return true; + } - private static string BuildUserMessageForActionExpression(string? format, string actionExpression) - => BuildUserMessageForSingleExpression(format, actionExpression, "action"); + // Check if expression ends with a numeric type suffix + char lastChar = expression[expression.Length - 1]; + if (lastChar is not ('f' or 'F' or 'd' or 'D' or 'm' or 'M' or 'L' or 'l' or 'u' or 'U')) + { + return false; + } - private static string BuildUserMessageForCollectionExpression(string? format, string collectionExpression) - => BuildUserMessageForSingleExpression(format, collectionExpression, "collection"); + // The formatted value should be the numeric part without the suffix + // e.g., expression "1.0d" -> formattedValue "1" or "1.0" + string numericPart = expression.Substring(0, expression.Length - 1); - private static string BuildUserMessageForSubstringExpressionAndValueExpression(string? format, string substringExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, substringExpression, "substring", valueExpression, "value"); + // Handle UL/ul suffix (two chars) + if (numericPart.Length > 0 && numericPart[numericPart.Length - 1] is 'u' or 'U' or 'l' or 'L') + { + numericPart = numericPart.Substring(0, numericPart.Length - 1); + } - private static string BuildUserMessageForExpectedSuffixExpressionAndValueExpression(string? format, string expectedSuffixExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, expectedSuffixExpression, "expectedSuffix", valueExpression, "value"); + // Check if removing the suffix gives the formatted value, or if they represent the same number + return numericPart == formattedValue + || (double.TryParse(numericPart, NumberStyles.Any, CultureInfo.InvariantCulture, out double exprNum) + && double.TryParse(formattedValue, NumberStyles.Any, CultureInfo.InvariantCulture, out double valNum) + && exprNum == valNum); + } - private static string BuildUserMessageForNotExpectedSuffixExpressionAndValueExpression(string? format, string notExpectedSuffixExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, notExpectedSuffixExpression, "notExpectedSuffix", valueExpression, "value"); + internal static string FormatParameter(string paramName, string expression, T? value) + { + string formattedValue = FormatValue(value); - private static string BuildUserMessageForExpectedPrefixExpressionAndValueExpression(string? format, string expectedPrefixExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, expectedPrefixExpression, "expectedPrefix", valueExpression, "value"); + return $" {paramName}: {formattedValue}"; + } - private static string BuildUserMessageForNotExpectedPrefixExpressionAndValueExpression(string? format, string notExpectedPrefixExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, notExpectedPrefixExpression, "notExpectedPrefix", valueExpression, "value"); + /// + /// Prepends the user-provided message before the assertion explanation. + /// Returns the message unchanged if userMessage is null or empty. + /// + internal static string AppendUserMessage(string message, string? userMessage) + => string.IsNullOrEmpty(userMessage) + ? message + : userMessage + Environment.NewLine + message; - private static string BuildUserMessageForPatternExpressionAndValueExpression(string? format, string patternExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, patternExpression, "pattern", valueExpression, "value"); + /// + /// Formats a parameter line showing only the expression (no value). + /// Used for parameters like predicates and actions where the + /// runtime value's ToString() is not useful. + /// Returns empty string if the expression is empty or matches the parameter name. + /// + internal static string FormatExpressionParameter(string paramName, string expression) + => string.IsNullOrEmpty(expression) || expression == paramName + ? string.Empty + : Environment.NewLine + $" {paramName}: {TruncateExpression(expression)}"; - private static string BuildUserMessageForLowerBoundExpressionAndValueExpression(string? format, string lowerBoundExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, lowerBoundExpression, "lowerBound", valueExpression, "value"); + /// + /// Formats a collection parameter line showing a preview of the collection elements. + /// Callers must ensure the collection is safe to enumerate (e.g. materialized via + /// snapshot at the assertion boundary). Non-ICollection enumerables are shown as their + /// type name as a safety net. + /// + internal static string FormatCollectionParameter(string expression, IEnumerable collection) + { + // Safety net: callers should materialize non-ICollection enumerables before + // reaching here, but if they don't, fall back to the type name rather than + // risk re-enumerating a non-deterministic or exhausted enumerator. + if (collection is not ICollection) + { + return $"{Environment.NewLine} collection: {FormatType(collection.GetType())}"; + } - private static string BuildUserMessageForUpperBoundExpressionAndValueExpression(string? format, string upperBoundExpression, string valueExpression) - => BuildUserMessageForTwoExpressions(format, upperBoundExpression, "upperBound", valueExpression, "value"); + string preview = FormatCollectionPreview(collection); - private static string BuildUserMessageForExpectedExpressionAndCollectionExpression(string? format, string expectedExpression, string collectionExpression) - => BuildUserMessageForTwoExpressions(format, expectedExpression, "expected", collectionExpression, "collection"); + return $"{Environment.NewLine} collection: {preview}"; + } - private static string BuildUserMessageForNotExpectedExpressionAndCollectionExpression(string? format, string notExpectedExpression, string collectionExpression) - => BuildUserMessageForTwoExpressions(format, notExpectedExpression, "notExpected", collectionExpression, "collection"); + /// + /// Formats a preview string for a collection, showing element values up to characters. + /// + /// Performance: We avoid enumerating the entire collection when the display is truncated. + /// For ICollection, we read .Count directly (O(1)) to get the total without full enumeration. + /// For non-ICollection enumerables (e.g. LINQ queries, infinite sequences), we stop + /// enumeration as soon as the display budget is exhausted and report "N+ elements" since + /// the true count is unknown. This prevents hangs on lazy/infinite sequences and avoids + /// O(n) enumeration cost when only a prefix is displayed. + /// + /// + private static string FormatCollectionPreview(IEnumerable collection, int maxLength = 256) + { + // Perf: get count from ICollection (O(1)) to avoid full enumeration just for the count. + int? knownCount = collection is ICollection c ? c.Count : null; + + var elements = new List(); + int enumeratedCount = 0; + int currentLength = 0; + bool truncated = false; + + // Perf: wrap in try-catch so that faulting enumerators (e.g. collection modified during + // iteration, or user-defined iterators that throw) don't bubble up from assertion formatting. + try + { + foreach (object? item in collection) + { + enumeratedCount++; - private static string BuildUserMessageForPredicateExpressionAndCollectionExpression(string? format, string predicateExpression, string collectionExpression) - => BuildUserMessageForTwoExpressions(format, predicateExpression, "predicate", collectionExpression, "collection"); + string formatted = item is IEnumerable innerCollection and not string + ? FormatCollectionPreview(innerCollection, maxLength: 50) + : FormatValue(item, maxLength: 50); - private static string BuildUserMessageForExpectedExpressionAndActualExpression(string? format, string expectedExpression, string actualExpression) - => BuildUserMessageForTwoExpressions(format, expectedExpression, "expected", actualExpression, "actual"); + // Account for ", " separator between elements + int addedLength = elements.Count > 0 + ? formatted.Length + 2 + : formatted.Length; - private static string BuildUserMessageForNotExpectedExpressionAndActualExpression(string? format, string notExpectedExpression, string actualExpression) - => BuildUserMessageForTwoExpressions(format, notExpectedExpression, "notExpected", actualExpression, "actual"); + if (currentLength + addedLength > maxLength && elements.Count > 0) + { + truncated = true; - private static string BuildUserMessageForMinValueExpressionAndMaxValueExpressionAndValueExpression(string? format, string minValueExpression, string maxValueExpression, string valueExpression) - => BuildUserMessageForThreeExpressions(format, minValueExpression, "minValue", maxValueExpression, "maxValue", valueExpression, "value"); + // Perf: stop enumeration immediately once the display budget is exceeded. + // Without this break, we'd continue iterating potentially millions of + // elements (or hang on infinite sequences) just to compute totalCount. + break; + } + + elements.Add(formatted); + currentLength += addedLength; + } + } + catch (Exception) + { + // If enumeration fails, report what we've collected so far + truncated = elements.Count > 0; + } + + int totalCount = knownCount ?? enumeratedCount; + int displayedCount = elements.Count; + + string elementList = string.Join(", ", elements); + if (truncated) + { + int remaining = totalCount - displayedCount; + string remainingText = knownCount is null + ? $"{remaining}+" + : $"{remaining}"; + elementList += $", ... {remainingText} more"; + } + + return $"[{elementList}]"; + } + + internal static string FormatParameterWithValue(string paramName, string expression, string formattedValue) + => $" {paramName}: {formattedValue}"; /// - /// Checks the parameter for valid conditions. + /// Formats a parameter line, checking expression redundancy against a base value + /// while displaying a different (enriched) display value. /// - /// - /// The parameter. - /// - /// - /// The assertion Name. - /// - /// - /// parameter name. - /// - internal static void CheckParameterNotNull([NotNull] object? param, string assertionName, string parameterName) + internal static string FormatParameterWithExpressionCheck(string paramName, string expression, string baseValue, string displayValue) + => $" {paramName}: {displayValue}"; + + /// + /// Builds the "Assert.Method(expr1, expr2)" call site string for the first line. + /// Only the primary/semantic parameters are included (not message, culture, delta, etc.). + /// + internal static string FormatCallSite(string methodName, params (string ParamName, string Expression)[] args) { - if (param == null) + var sb = new StringBuilder(methodName); + sb.Append('('); + bool hasVisibleArgs = false; + for (int i = 0; i < args.Length; i++) { - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.NullParameterToAssert, parameterName); - ThrowAssertFailed(assertionName, finalMessage); + string expression = args[i].Expression; + string paramName = args[i].ParamName; + + // Sentinel "..." indicates additional parameters were omitted. + if (paramName == "...") + { + if (hasVisibleArgs) + { + sb.Append(", "); + } + + sb.Append("..."); + continue; + } + + if (hasVisibleArgs) + { + sb.Append(", "); + } + + sb.Append(string.IsNullOrEmpty(expression) || expression == paramName + ? paramName + : TruncateExpression(expression, 50)); + hasVisibleArgs = true; } + + sb.Append(')'); + + return sb.ToString(); } - internal static string ReplaceNulls(object? input) - => input?.ToString() ?? string.Empty; + /// + /// Formats multiple parameter lines with aligned values. + /// All labels are padded so that values start at the same column. + /// + internal static string FormatAlignedParameters(params (string Label, string Value)[] parameters) + { + int maxLabelLength = 0; + foreach ((string label, string _) in parameters) + { + if (label.Length > maxLabelLength) + { + maxLabelLength = label.Length; + } + } + + var sb = new StringBuilder(); + foreach ((string label, string value) in parameters) + { + sb.Append(Environment.NewLine); + sb.Append(" "); + sb.Append(label); + sb.Append(':'); + sb.Append(new string(' ', maxLabelLength - label.Length + 1)); + sb.Append(value); + } + + return sb.ToString(); + } private static int CompareInternal(string? expected, string? actual, bool ignoreCase, CultureInfo culture) #pragma warning disable CA1309 // Use ordinal string comparison diff --git a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs index c8f37e098b..c009cbc8ae 100644 --- a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs +++ b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs @@ -79,7 +79,9 @@ public static void Contains([NotNull] ICollection? collection, object? element, } } - Assert.ThrowAssertFailed("CollectionAssert.Contains", Assert.BuildUserMessage(message)); + string msg = FrameworkMessages.ContainsItemFailNew; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.Contains", msg); } /// @@ -126,7 +128,9 @@ public static void DoesNotContain([NotNull] ICollection? collection, object? ele { if (object.Equals(current, element)) { - Assert.ThrowAssertFailed("CollectionAssert.DoesNotContain", Assert.BuildUserMessage(message)); + string msg = FrameworkMessages.DoesNotContainItemFailNew; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.DoesNotContain", msg); } } } @@ -165,7 +169,9 @@ public static void AllItemsAreNotNull([NotNull] ICollection? collection, string? { if (current == null) { - Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreNotNull", Assert.BuildUserMessage(message)); + string msg = FrameworkMessages.IsNotNullFailNew; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreNotNull", msg); } } } @@ -204,8 +210,6 @@ public static void AllItemsAreUnique([NotNull] ICollection? collection, string? { Assert.CheckParameterNotNull(collection, "CollectionAssert.AllItemsAreUnique", "collection"); - message = Assert.ReplaceNulls(message); - bool foundNull = false; Dictionary table = []; foreach (object? current in collection) @@ -219,28 +223,22 @@ public static void AllItemsAreUnique([NotNull] ICollection? collection, string? else { // Found a second occurrence of null. - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AllItemsAreUniqueFailMsg, - userMessage, - FrameworkMessages.Common_NullInMessages); - - Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreUnique", finalMessage); + string msg = FrameworkMessages.AllItemsAreUniqueFailMsg; + msg += Assert.FormatAlignedParameters( + ("duplicate", FrameworkMessages.Common_NullInMessages)); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreUnique", msg); } } else { if (!table.TryAdd(current, true)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.AllItemsAreUniqueFailMsg, - userMessage, - Assert.ReplaceNulls(current)); - - Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreUnique", finalMessage); + string msg = FrameworkMessages.AllItemsAreUniqueFailMsg; + msg += Assert.FormatAlignedParameters( + ("duplicate", Assert.ReplaceNulls(current))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreUnique", msg); } } } @@ -297,18 +295,10 @@ public static void IsSubsetOf([NotNull] ICollection? subset, [NotNull] ICollecti Tuple> isSubsetValue = IsSubsetOfHelper(subset, superset); if (!isSubsetValue.Item1) { - string returnedSubsetValueMessage = string.Join(", ", isSubsetValue.Item2.Select(item => Convert.ToString(item, CultureInfo.InvariantCulture))); - - returnedSubsetValueMessage = string.Format(CultureInfo.InvariantCulture, FrameworkMessages.ReturnedSubsetValueMessage, returnedSubsetValueMessage); - string userMessage = Assert.BuildUserMessage(message); - if (string.IsNullOrEmpty(userMessage)) - { - Assert.ThrowAssertFailed("CollectionAssert.IsSubsetOf", returnedSubsetValueMessage); - } - else - { - Assert.ThrowAssertFailed("CollectionAssert.IsSubsetOf", $"{returnedSubsetValueMessage} {userMessage}"); - } + string missingElements = string.Join(", ", isSubsetValue.Item2.Select(item => Convert.ToString(item, CultureInfo.InvariantCulture))); + string msg = string.Format(CultureInfo.InvariantCulture, FrameworkMessages.ReturnedSubsetValueMessage, missingElements); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.IsSubsetOf", msg); } } @@ -357,7 +347,9 @@ public static void IsNotSubsetOf([NotNull] ICollection? subset, [NotNull] IColle Tuple> isSubsetValue = IsSubsetOfHelper(subset, superset); if (isSubsetValue.Item1) { - Assert.ThrowAssertFailed("CollectionAssert.IsNotSubsetOf", Assert.BuildUserMessage(message)); + string msg = FrameworkMessages.BothSameElements; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.IsNotSubsetOf", msg); } } @@ -476,7 +468,9 @@ public static void AreEquivalent( // Check whether one is null while the other is not. if (expected == null != (actual == null)) { - Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", Assert.BuildUserMessage(message)); + string msg = FrameworkMessages.AreEqualFailNew; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", msg); } // If the references are the same or both collections are null, they are equivalent. @@ -493,14 +487,12 @@ public static void AreEquivalent( // Check whether the element counts are different. if (expectedCollectionCount != actualCollectionCount) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ElementNumbersDontMatch, - userMessage, - expectedCollectionCount, - actualCollectionCount); - Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", finalMessage); + string msg = FrameworkMessages.ElementNumbersDontMatch; + msg += Assert.FormatAlignedParameters( + ("expected count", expectedCollectionCount.ToString(CultureInfo.CurrentCulture)), + ("actual count", actualCollectionCount.ToString(CultureInfo.CurrentCulture))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", msg); } // If both collections are empty, they are equivalent. @@ -512,15 +504,13 @@ public static void AreEquivalent( // Search for a mismatched element. if (FindMismatchedElement(expected, actual, comparer, out int expectedCount, out int actualCount, out object? mismatchedElement)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.ActualHasMismatchedElements, - userMessage, - expectedCount.ToString(CultureInfo.CurrentCulture.NumberFormat), - Assert.ReplaceNulls(mismatchedElement), - actualCount.ToString(CultureInfo.CurrentCulture.NumberFormat)); - Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", finalMessage); + string msg = FrameworkMessages.ActualHasMismatchedElements; + msg += Assert.FormatAlignedParameters( + ("element", Assert.ReplaceNulls(mismatchedElement)), + ("expected occurrences", expectedCount.ToString(CultureInfo.CurrentCulture)), + ("actual occurrences", actualCount.ToString(CultureInfo.CurrentCulture))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreEquivalent", msg); } // All the elements and counts matched. @@ -649,12 +639,9 @@ public static void AreNotEquivalent( // are equivalent. object.ReferenceEquals will handle case where both are null. if (object.ReferenceEquals(notExpected, actual)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.BothCollectionsSameReference, - userMessage); - Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", finalMessage); + string msg = FrameworkMessages.BothCollectionsSameReference; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", msg); } DebugEx.Assert(actual is not null, "actual is not null here"); @@ -671,23 +658,17 @@ public static void AreNotEquivalent( // If both collections are empty, they are equivalent. if (notExpectedCount == 0) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.BothCollectionsEmpty, - userMessage); - Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", finalMessage); + string msg = FrameworkMessages.BothCollectionsEmpty; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", msg); } // Search for a mismatched element. if (!FindMismatchedElement(notExpected, actual, comparer, out _, out _, out _)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( - CultureInfo.CurrentCulture, - FrameworkMessages.BothSameElements, - userMessage); - Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", finalMessage); + string msg = FrameworkMessages.BothSameElements; + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AreNotEquivalent", msg); } } @@ -748,15 +729,15 @@ public static void AllItemsAreInstancesOfType( if (element?.GetType() is { } elementType && !expectedType.IsAssignableFrom(elementType)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format( + string msg = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.ElementTypesAtIndexDontMatch, - userMessage, - i, - expectedType.ToString(), - element.GetType().ToString()); - Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreInstancesOfType", finalMessage); + i); + msg += Assert.FormatAlignedParameters( + ("expected type", Assert.FormatType(expectedType)), + ("actual type", Assert.FormatType(element.GetType()))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("CollectionAssert.AllItemsAreInstancesOfType", msg); } i++; @@ -1181,7 +1162,7 @@ private static bool AreCollectionsEqual(ICollection? expected, ICollection? actu Assert.CheckParameterNotNull(comparer, "Assert.AreCollectionsEqual", "comparer"); if (object.ReferenceEquals(expected, actual)) { - reason = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.BothCollectionsSameReference, string.Empty); + reason = FrameworkMessages.BothCollectionsSameReference; return true; } @@ -1229,9 +1210,10 @@ private static bool CompareIEnumerable(IEnumerable? expected, IEnumerable? actua reason = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.ElementsAtIndexDontMatch, - position, - Assert.ReplaceNulls(curExpected), - Assert.ReplaceNulls(curActual)); + position) + + Assert.FormatAlignedParameters( + ("expected", Assert.ReplaceNulls(curExpected)), + ("actual", Assert.ReplaceNulls(curActual))); return false; } } @@ -1250,12 +1232,7 @@ private static bool CompareIEnumerable(IEnumerable? expected, IEnumerable? actua private static string ConstructFinalMessage( string reason, string? message) - { - string userMessage = Assert.BuildUserMessage(message); - return userMessage.Length == 0 - ? reason - : string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); - } + => Assert.AppendUserMessage(reason, message); /// /// compares the objects using object.Equals. diff --git a/src/TestFramework/TestFramework/Assertions/StringAssert.cs b/src/TestFramework/TestFramework/Assertions/StringAssert.cs index b2e36625ec..21401abd64 100644 --- a/src/TestFramework/TestFramework/Assertions/StringAssert.cs +++ b/src/TestFramework/TestFramework/Assertions/StringAssert.cs @@ -120,9 +120,12 @@ public static void Contains([NotNull] string? value, [NotNull] string? substring Assert.CheckParameterNotNull(substring, "StringAssert.Contains", "substring"); if (value.IndexOf(substring, comparisonType) < 0) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.ContainsFail, value, substring, userMessage); - Assert.ThrowAssertFailed("StringAssert.Contains", finalMessage); + string msg = FrameworkMessages.ContainsStringFailNew; + msg += Assert.FormatAlignedParameters( + (nameof(substring), Assert.FormatValue(substring)), + (nameof(value), Assert.FormatValue(value))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("StringAssert.Contains", msg); } } @@ -217,9 +220,12 @@ public static void StartsWith([NotNull] string? value, [NotNull] string? substri Assert.CheckParameterNotNull(substring, "StringAssert.StartsWith", "substring"); if (!value.StartsWith(substring, comparisonType)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.StartsWithFail, value, substring, userMessage); - Assert.ThrowAssertFailed("StringAssert.StartsWith", finalMessage); + string msg = FrameworkMessages.StartsWithFailNew; + msg += Assert.FormatAlignedParameters( + ("expected prefix", Assert.FormatValue(substring)), + (nameof(value), Assert.FormatValue(value))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("StringAssert.StartsWith", msg); } } @@ -314,9 +320,12 @@ public static void EndsWith([NotNull] string? value, [NotNull] string? substring Assert.CheckParameterNotNull(substring, "StringAssert.EndsWith", "substring"); if (!value.EndsWith(substring, comparisonType)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.EndsWithFail, value, substring, userMessage); - Assert.ThrowAssertFailed("StringAssert.EndsWith", finalMessage); + string msg = FrameworkMessages.EndsWithFailNew; + msg += Assert.FormatAlignedParameters( + ("expected suffix", Assert.FormatValue(substring)), + (nameof(value), Assert.FormatValue(value))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("StringAssert.EndsWith", msg); } } @@ -369,9 +378,12 @@ public static void Matches([NotNull] string? value, [NotNull] Regex? pattern, st if (!pattern.IsMatch(value)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsMatchFail, value, pattern, userMessage); - Assert.ThrowAssertFailed("StringAssert.Matches", finalMessage); + string msg = FrameworkMessages.MatchesRegexFailNew; + msg += Assert.FormatAlignedParameters( + (nameof(pattern), Assert.FormatValue(pattern)), + (nameof(value), Assert.FormatValue(value))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("StringAssert.Matches", msg); } } @@ -420,9 +432,12 @@ public static void DoesNotMatch([NotNull] string? value, [NotNull] Regex? patter if (pattern.IsMatch(value)) { - string userMessage = Assert.BuildUserMessage(message); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.IsNotMatchFail, value, pattern, userMessage); - Assert.ThrowAssertFailed("StringAssert.DoesNotMatch", finalMessage); + string msg = FrameworkMessages.DoesNotMatchRegexFailNew; + msg += Assert.FormatAlignedParameters( + (nameof(pattern), Assert.FormatValue(pattern)), + (nameof(value), Assert.FormatValue(value))); + msg = Assert.AppendUserMessage(msg, message); + Assert.ThrowAssertFailed("StringAssert.DoesNotMatch", msg); } } diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx index 537b9331a7..965947311d 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx @@ -121,34 +121,10 @@ Access string has invalid syntax. - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} + Expected collections to have matching element occurrences. - Duplicate item found:<{1}>. {0} - - - Expected:<{1}>. Actual:<{2}>. {0} - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - - - {0}{1} -{2} -{3} -{4} - - - Expected: - - - But was: + Expected all items to be unique. String lengths are both {0} but differ at index {1}. @@ -156,71 +132,33 @@ Expected string length {0} but was {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} - Both collections are empty. {0} + Both collections are empty. - Both collection contain same elements. + Both collections contain the same elements. - Both collection references point to the same collection object. {0} + Both collection references point to the same collection object. - Both collections contain the same elements. {0} - - - {0}. {1} - - - String '{0}' does not contain string '{1}'. {2}. - - - Value '{0}' is not within the expected range [{1}..{2}]. {3} + Both collections contain the same elements. - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} + Expected the same number of elements in the collections. - Element at index {0} do not match. -Expected: {1} -Actual: {2} + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - - - String '{0}' does not end with string '{1}'. {2} + Element at index {0} is not of the expected type. {0} failed. {1} - - {0} Expected type:<{1}>. Actual type:<{2}>. - - - String '{0}' does not match pattern '{1}'. {2} - - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - - - String '{0}' matches pattern '{1}'. {2} - The member specified ({0}) could not be found. You might need to regenerate your private accessor, @@ -241,9 +179,6 @@ Actual: {2} Different number of elements. - - String '{0}' does not start with string '{1}'. {2} - The property {0} has type {1}; expected type {2}. @@ -256,12 +191,6 @@ Actual: {2} (Failed to get the message for an exception of type {0} due to an exception.) - - Expected exception type:<{1}> but no exception was thrown. {0} - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - {0} ({1}) @@ -289,108 +218,157 @@ Actual: {2} The dynamic data source '{0}' in type '{1}' should exist and be a property, a method, or a field. - - Expected collection of size {1}. Actual: {2}. {0} + + Invalid GitHub ticket URL - - Expected exactly one item to match the predicate but found {1} item(s). {0} + + Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. - - Expected collection to contain exactly one element but found {1} element(s). {0} + + Assert.ReferenceEquals should not be used for Assertions. Please use Assert.AreSame & overloads instead. - - Expected collection to contain the specified item. {0} + + StringAssert.Equals should not be used for Assertions. Please use StringAssert methods or Assert.AreEqual & overloads instead. - - Expected at least one item to match the predicate. {0} + + StringAssert.ReferenceEquals should not be used for Assertions. Please use StringAssert methods or Assert.AreSame & overloads instead. - - Expected collection to not contain the specified item. {0} + + CollectionAssert.Equals should not be used for Assertions. Please use CollectionAssert.AreEqual & overloads instead. - - Expected no items to match the predicate. {0} + + CollectionAssert.ReferenceEquals should not be used for Assertions. Please use CollectionAssert methods or Assert.AreSame & overloads instead. - - Expected collection to contain any item but it is empty. {0} + + The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures. - - Invalid GitHub ticket URL + + Element(s) <{0}> is/are not present in the collection. - - String '{0}' does contain string '{1}'. {2}. + + The maximum value must be greater than or equal to the minimum value. - - Actual value <{2}> is not greater than expected value <{1}>. {0} + + Expected difference to be no greater than {0}. - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} + + Expected difference to be greater than {0}. - - Actual value <{2}> is not less than expected value <{1}>. {0} + + Case differs. - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} + + Expected string to start with the specified prefix. - - Expected value <{1}> to be positive. {0} + + Expected string to not start with the specified prefix. - - Expected value <{1}> to be negative. {0} + + Expected string to end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} + + Expected string to not end with the specified suffix. - - String '{0}' starts with string '{1}'. {2} + + Expected string to match the specified pattern. - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. + + Expected string to not match the specified pattern. - - Assert.ReferenceEquals should not be used for Assertions. Please use Assert.AreSame & overloads instead. + + Expected collection to contain the specified item. - - StringAssert.Equals should not be used for Assertions. Please use StringAssert methods or Assert.AreEqual & overloads instead. + + Expected at least one item to match the predicate. - - StringAssert.ReferenceEquals should not be used for Assertions. Please use StringAssert methods or Assert.AreSame & overloads instead. + + Expected collection to not contain the specified item. - - CollectionAssert.Equals should not be used for Assertions. Please use CollectionAssert.AreEqual & overloads instead. + + Expected no items to match the predicate. - - CollectionAssert.ReferenceEquals should not be used for Assertions. Please use CollectionAssert methods or Assert.AreSame & overloads instead. + + Expected all elements to match the predicate. - - The property 'TestContext.{0}' is related to current test is not available during assembly or class fixtures. + + Expected string to contain the specified substring. - - '{0}' expression: '{1}'. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. + + Expected string to not contain the specified substring. - - Assert.That({0}) failed. - {0} is the user code expression + + Expected exactly one item to match the predicate but found {0} item(s). - - Message: {0} - {0} user provided message + + Expected collection to contain exactly one item but found {0} item(s). - - Details: + + Expected collection to have {0} item(s) but found {1}. - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + + Expected collection to not be empty. - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + + Expected value {0} to be in range [{1}, {2}]. - - Element(s) <{0}> is/are not present in the collection. + + Expected the specified exception type to be thrown. - - The maximum value must be greater than or equal to the minimum value. + + Expected an exception to be thrown. + + + Expected values to be equal. + + + Expected values to not be equal. + + + Expected references to be the same. + + + Expected references to be different. + + + Expected condition to be true. + + + Expected condition to be false. + + + Expected value to be null. + + + Expected value to not be null. + + + Expected value to be an instance of {0}. + + + Expected value to not be an instance of {0}. + + + Expected value to be exactly {0}. + + + Expected value to not be exactly {0}. + + + Expected value {0} to be greater than {1}. + + + Expected value {0} to be greater than or equal to {1}. + + + Expected value {0} to be less than {1}. + + + Expected value {0} to be less than or equal to {1}. + + + Expected value to be positive. + + + Expected value to be negative. \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf index 02a8e5a3bc..9592489ea7 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Očekávaná kolekce obsahuje {1} výskyt(ů) <{2}>. Aktuální kolekce obsahuje {3} výskyt(ů). {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Byla nalezena duplicitní položka:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Očekáváno:<{1}>. Aktuálně:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Očekáván rozdíl, který není větší jak <{3}> mezi očekávanou hodnotou <{1}> a aktuální hodnotou <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Očekáváno:<{1}>. Případ je rozdílný pro aktuální hodnotu:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Očekáváno:<{1} ({2})>. Aktuálně:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Očekáváno: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Ale bylo: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Očekávaná délka řetězce je {0}, ale byla {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Nebyla očekávána žádná hodnota kromě:<{1}>. Aktuálně:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Očekáván rozdíl, který je větší jak <{3}> mezi očekávanou hodnotou <{1}> a aktuální hodnotou <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Nevkládejte hodnotu typů do AreSame(). Hodnoty převedené do typu Object už nebudou nikdy stejné. Zvažte použití AreEqual(). {0} - - Details: - Podrobnosti: - - - - Assert.That({0}) failed. - Assert.That({0}) se nezdařilo. - {0} is the user code expression - - - Message: {0} - Zpráva: {0} - {0} user provided message - - Both collections are empty. {0} - Obě kolekce jsou prázdné. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Obě kolekce obsahují stejné elementy. - + Both collections contain the same elements. + Obě kolekce obsahují stejné elementy. + - Both collection references point to the same collection object. {0} - Obě reference na kolekci odkazují na stejný objekt kolekce. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Obě kolekce obsahují stejné elementy. {0} - - - - '{0}' expression: '{1}'. - Výraz „{0}“: {1}. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Výraz „{0}“: {1}, výraz „{2}“: {3}, výraz „{4}“: {5}. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Výraz „{0}“: {1}, výraz „{2}“: {3}. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - Řetězec '{0}' neobsahuje řetězec '{1}'. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Očekávala se kolekce, která bude obsahovat zadanou položku. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Očekávala se alespoň jedna položka odpovídající predikátu. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Očekávalo se, že kolekce bude obsahovat přesně jeden prvek, ale našlo se tolik elementů: {1}. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Očekávala se přesně jedna položka odpovídající predikátu, ale našlo se tolik položek: {1}. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - Řetězec {0} obsahuje řetězec {1}. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Očekávalo se, že kolekce nebude obsahovat zadanou položku. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Očekávaly se žádné položky, které by odpovídaly predikátu. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - Řetězec „{0}“ končí řetězcem „{1}“. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - Řetězec „{0}“ začíná řetězcem „{1}“. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Počet elementů v kolekcích nesouhlasí. Očekáváno:<{1}>. Aktuálně:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - Element v indexu {0} nesouhlasí. -Očekáváno: {1} -Skutečnost: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - Element na indexu {1} není očekávaného typu. Očekávaný typ:<{2}>. Aktuální typ:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - Řetězec „{0}“ nekončí řetězcem „{1}“. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Skutečnost: {2} {0} selhalo. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Očekávala se kolekce {1} velikosti. Skutečnost: {2} {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Skutečnost: {2} Neplatná adresa URL lístku GitHubu - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Hodnota {0} není v očekávaném rozsahu [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Skutečnost: {2} Maximální hodnota musí být větší nebo rovna minimální hodnotě. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Očekávaný typ:<{1}>. Aktuální typ:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - Řetězec „{0}“ neodpovídá vzoru „{1}“. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Očekávalo se, že kolekce bude obsahovat libovolnou položku, ale je prázdná. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Špatný typ:<{1}>. Aktuální typ:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Očekávaný přesný typ:<{1}>. Skutečný typ:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Nesprávný přesný typ:<{1}>. Skutečný typ:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - Řetězec „{0}“ odpovídá vzoru „{1}“. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Skutečnost: {2} Elementy <{0}> se v kolekci nenachází. - - String '{0}' does not start with string '{1}'. {2} - Řetězec „{0}“ nezačíná řetězcem „{1}“. {2} - - The property {0} has type {1}; expected type {2}. Vlastnost {0} je typu {1}; očekávaný typ {2}. @@ -358,21 +358,16 @@ Skutečnost: {2} (objekt) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Z důvodu výjimky se nepodařilo získat zprávu o výjimce typu {0}.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Byl očekáván typ výjimky: <{1}>, ale nebyla vyvolána žádná výjimka. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Očekávaný typ výjimky: <{1}> Skutečný typ výjimky: <{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Skutečnost: {2} Vlastnost nebo metoda {0} ve třídě {1} vrací prázdné IEnumerable<object[]>. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Skutečná hodnota <{2}> není větší než očekávaná hodnota <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Skutečná hodnota <{2}> není větší nebo rovna očekávané hodnotě <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Skutečná hodnota <{2}> není menší než očekávaná hodnota <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Skutečná hodnota <{2}> není menší nebo rovna očekávané hodnotě <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Očekávaná hodnota <{1}> má být kladná. {0} - - - - Expected value <{1}> to be negative. {0} - Očekávaná hodnota <{1}> má být záporná. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals by neměla být pro kontrolní výrazy používána. Použijte prosím místo toho Assert.AreEqual a její přetížení. @@ -458,6 +423,11 @@ Skutečnost: {2} CollectionAssert.ReferenceEquals se nemá používat pro kontrolní výrazy. Místo toho použijte metody CollectionAssert nebo Assert.AreSame & overloads. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf index b240c09df6..445f8b28ca 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Die erwartete Sammlung enthält {1} Vorkommen von <{2}>. Die tatsächliche Sammlung enthält {3} Vorkommen. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Doppeltes Element gefunden: <{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Erwartet:<{1}>. Tatsächlich:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Es wurde eine Differenz nicht größer als <{3}> zwischen dem erwarteten Wert <{1}> und dem tatsächlichen Wert <{2}> erwartet. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Erwartet:<{1}>. Die Großschreibung des tatsächlichen Werts weicht davon ab:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Erwartet:<{1} ({2})>. Tatsächlich:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Erwartet: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - War aber: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Die erwartete Länge der Zeichenfolge ist {0}, war aber {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Es wurde ein beliebiger Wert erwartet außer:<{1}>. Tatsächlich:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Es wurde eine Differenz größer als <{3}> zwischen dem erwarteten Wert <{1}> und dem tatsächlichen Wert <{2}> erwartet. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Übergeben Sie keine Werttypen an AreSame(). In ein Objekt konvertierte Werte sind niemals identisch. Verwenden Sie stattdessen AreEqual(). {0} - - Details: - Details: - - - - Assert.That({0}) failed. - Assert.That({0}) fehlgeschlagen. - {0} is the user code expression - - - Message: {0} - Meldung: {0} - {0} user provided message - - Both collections are empty. {0} - Beide Sammlungen sind leer. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Beide Sammlungen enthalten dieselben Elemente. - + Both collections contain the same elements. + Beide Sammlungen enthalten dieselben Elemente. + - Both collection references point to the same collection object. {0} - Beide Sammlungsverweise zeigen auf dasselbe Sammlungsobjekt. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Beide Sammlungen enthalten dieselben Elemente. {0} - - - - '{0}' expression: '{1}'. - „{0}“ Ausdruck: „{1}“. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - „{0}“ Ausdruck: „{1}“, „{2}“ Ausdruck: „{3}“, „{4}“ Ausdruck: „{5}“. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - „{0}“ Ausdruck: „{1}“, „{2}“ Ausdruck: „{3}“. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - Die Zeichenfolge "{0}" enthält nicht die Zeichenfolge "{1}". {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Es wurde erwartet, dass die Sammlung das angegebene Element enthält. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Es wurde erwartet, dass mindestens ein Element mit dem Prädikat übereinstimmt. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Es wurde erwartet, dass die Sammlung genau ein Element enthält, es wurden jedoch {1} gefunden. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Es wurde erwartet, dass genau ein Element mit dem Prädikat übereinstimmt, es wurden jedoch {1} Element(e) gefunden. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - Die Zeichenfolge „{0}“ enthält die Zeichenfolge „{1}“. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Es wurde erwartet, dass die Sammlung das angegebene Element nicht enthält. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Es wurden erwartet, dass keine Elemente mit dem Prädikat übereinstimmen. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - Die Zeichenfolge „{0}“ endet mit der Zeichenfolge „{1}“. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - Die Zeichenfolge „{0}“ beginnt mit der Zeichenfolge „{1}“. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Die Anzahl der Elemente in den Sammlungen stimmt nicht überein. Erwartet: <{1}>. Tatsächlich: <{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - Das Element bei Index {0} stimmt nicht überein. -Erwartet: {1} -Tatsächlich: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - Das Element bei Index "{1}" weist nicht den erwarteten Typ auf. Erwarteter Typ:<{2}>. Tatsächlicher Typ:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - Die Zeichenfolge „{0}“ endet nicht auf die Zeichenfolge „{1}“. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Tatsächlich: {2} Fehler bei "{0}". {1} - - Expected collection of size {1}. Actual: {2}. {0} - Es wurde eine Sammlung mit einer Größe {1} erwartet. Tatsächlich: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Tatsächlich: {2} Ungültige GitHub-Ticket-URL. - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Der Wert „{0}“ liegt nicht im erwarteten Bereich [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Tatsächlich: {2} Der Höchstwert muss größer oder gleich dem Mindestwert sein. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0}Erwarteter Typ:<{1}>. Tatsächlicher Typ:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - Die Zeichenfolge „{0}“ stimmt nicht mit dem Muster „{1}“ überein. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Es wurde erwartet, dass die Sammlung ein beliebiges Element enthält, aber leer ist. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Falscher Typ:<{1}>. Tatsächlicher Typ:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Erwarteter genauer Typ:<{1}>. Tatsächlicher Typ:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Falscher genauer Typ:<{1}>. Tatsächlicher Typ:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - Die Zeichenfolge „{0}“ stimmt mit dem Muster „{1}“ überein. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Tatsächlich: {2} Element(e) <{0}> ist/sind in der Auflistung nicht vorhanden. - - String '{0}' does not start with string '{1}'. {2} - Die Zeichenfolge „{0}“ beginnt nicht mit der Zeichenfolge „{1}“. {2} - - The property {0} has type {1}; expected type {2}. Die {0}-Eigenschaft weist den Typ "{1}" auf; Typ "{2}" wird erwartet. @@ -358,21 +358,16 @@ Tatsächlich: {2} (Objekt) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Fehler beim Abrufen der Meldung für eine Ausnahme vom Typ "{0}" aufgrund einer Ausnahme.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Erwarteter Ausnahmetyp:<{1}>, aber es wurde keine Ausnahme ausgelöst. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Erwarteter Ausnahmetyp:<{1}>. Tatsächlicher Ausnahmetyp:<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Tatsächlich: {2} Eigenschaft oder Methode "{0}" in "{1}" gibt leeres IEnumerable<object[]> zurück. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Der tatsächliche Wert <{2}> ist nicht größer als der erwartete Wert <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Der tatsächliche Wert <{2}> ist nicht größer oder gleich dem erwarteten Wert <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Der tatsächliche Wert <{2}> ist nicht kleiner als der erwartete Wert <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Der tatsächliche Wert <{2}> ist nicht kleiner oder gleich dem erwarteten Wert <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Es wurde erwartet, dass der Wert <{1}> positiv ist. {0} - - - - Expected value <{1}> to be negative. {0} - Es wurde erwartet, dass der Wert <{1}> negativ ist. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals sollte nicht für Assertions verwendet werden. Verwenden Sie stattdessen Assert.AreEqual und Überladungen. @@ -458,6 +423,11 @@ Tatsächlich: {2} CollectionAssert.ReferenceEquals darf nicht für Assertions verwendet werden. Verwenden Sie stattdessen CollectionAssert-Methoden oder Assert.AreSame und Überladungen. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf index 427b030537..96b961aa92 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Apariciones que contiene la colección esperada: {1} de <{2}>. Apariciones que contiene la colección real: {3}. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Se encontró un elemento duplicado:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Se esperaba <{1}>, pero es <{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Se esperaba una diferencia no superior a <{3}> entre el valor esperado <{1}> y el valor actual <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Se esperaba:<{1}>. La caja es diferente para el valor actual:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Se esperaba:<{1} ({2})>, pero es:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Se esperaba: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Pero fue: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Se esperaba una longitud de cadena {0} pero fue {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Se esperaba cualquier valor excepto <{1}>, pero es <{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Se esperaba una diferencia mayor que <{3}> entre el valor esperado <{1}> y el valor actual <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} No pase tipos de valor a AreSame(). Los valores convertidos a Object no serán nunca iguales. Considere el uso de AreEqual(). {0} - - Details: - Detalles: - - - - Assert.That({0}) failed. - Error de Assert.That({0}). - {0} is the user code expression - - - Message: {0} - Mensaje: {0} - {0} user provided message - - Both collections are empty. {0} - Ambas colecciones están vacías. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Ambas colecciones tienen los mismos elementos. - + Both collections contain the same elements. + Ambas colecciones tienen los mismos elementos. + - Both collection references point to the same collection object. {0} - Las referencias de ambas colecciones apuntan al mismo objeto de colección. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Ambas colecciones tienen los mismos elementos. {0} - - - - '{0}' expression: '{1}'. - Expresión "{0}": "{1}". - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Expresión "{0}": "{1}", expresión "{2}": "{3}", expresión "{4}": "{5}". - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Expresión "{0}": "{1}", expresión "{2}": "{3}". - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - La cadena '{0}' no contiene la cadena '{1}'. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Se esperaba que la colección contuviera el elemento especificado. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Se esperaba al menos un elemento para que coincida con el predicado. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Se esperaba que la colección contuviera exactamente un elemento, pero se encontraron {1} elementos. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Se esperaba exactamente un elemento para que coincida con el predicado, pero se encontraron {1} elementos. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - La cadena '{0}' contiene la cadena '{1}'. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Se esperaba que la colección no contenga el elemento especificado. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - No se esperaba que ningún elemento coincidía con el predicado. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - La cadena "{0}" termina con la cadena "{1}". {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - La cadena "{0}" comienza con la cadena "{1}". {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - El número de elementos de las colecciones no coincide. Se esperaba:<{1}>, pero es:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - El elemento del índice {0} no coincide. -Esperado: {1} -Real: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - El elemento del índice {1} no es del tipo esperado. Tipo esperado:<{2}>, pero es el tipo:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - La cadena "{0}" no termina con la cadena "{1}". {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Real: {2} Error de {0}. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Se esperaba una colección de tamaño {1}. Real: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Real: {2} Dirección URL de vale de GitHub no válida - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - El valor "{0}" no está dentro del rango esperado [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Real: {2} El valor máximo debe ser igual o mayor que el valor mínimo. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Tipo esperado:<{1}>. Tipo real:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - La cadena "{0}" no coincide con el patrón "{1}". {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Se esperaba que la colección contenga cualquier elemento, pero está vacía. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Tipo incorrecto:<{1}>. Tipo actual:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Tipo exacto esperado: <{1}>. Tipo real:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Tipo exacto incorrecto: <{1}>. Tipo actual:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - La cadena "{0}" coincide con el patrón "{1}". {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Real: {2} Los elementos <{0}> no están presentes en la colección. - - String '{0}' does not start with string '{1}'. {2} - La cadena "{0}" no empieza con la cadena "{1}". {2} - - The property {0} has type {1}; expected type {2}. La propiedad {0} tiene el tipo {1}; se esperaba el tipo {2}. @@ -358,21 +358,16 @@ Real: {2} (objeto) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (No se pudo obtener el mensaje para una excepción del tipo {0} debido a una excepción.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Tipo de excepción esperada:<{1}> pero no se lanzó ninguna excepción. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Tipo de excepción esperada:<{1}>. Tipo de excepción actual: <{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Real: {2} La propiedad o el método {0} en {1} devuelve un elemento IEnumerable<object[]> vacío. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - El valor real <{2}> no es mayor que el valor esperado <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - El valor real <{2}> no es mayor o igual que el valor esperado <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - El valor real <{2}> no es menor que el valor esperado <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - El valor real <{2}> no es menor o igual que el valor esperado <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Se esperaba que el valor <{1}> ser positivo. {0} - - - - Expected value <{1}> to be negative. {0} - Se esperaba que el valor <{1}> ser negativo. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. No se debe usar Assert.Equals para aserciones. Use Assert.AreEqual y Overloads en su lugar. @@ -458,6 +423,11 @@ Real: {2} CollectionAssert.ReferenceEquals no se debe usar para las aserciones. Use los métodos CollectionAssert o las sobrecargas Assert.AreSame & en su lugar. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf index 0e46d1985a..70d0d6d83a 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - La collection attendue contient {1} occurrence(s) de <{2}>. La collection réelle contient {3} occurrence(s). {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Un élément dupliqué a été trouvé : <{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Attendu : <{1}>, Réel : <{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Différence attendue non supérieure à <{3}> comprise entre la valeur attendue <{1}> et la valeur réelle <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Attendu :<{1}>. La casse est différente pour la valeur réelle :<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Attendu : <{1} ({2})>, Réel : <{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Attendu : - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Mais c'était : - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ La longueur de chaîne attendue {0} mais était {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Toute valeur attendue sauf :<{1}>. Réel :<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Différence attendue supérieure à <{3}> comprise entre la valeur attendue <{1}> et la valeur réelle <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Ne passez pas de types valeur à AreSame(). Les valeurs converties en Object ne seront plus jamais les mêmes. Si possible, utilisez AreEqual(). {0} - - Details: - Détails : - - - - Assert.That({0}) failed. - Désolé, échec de Assert.That({0}). - {0} is the user code expression - - - Message: {0} - Message : {0} - {0} user provided message - - Both collections are empty. {0} - Les deux collections sont vides. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Les deux collections contiennent des éléments identiques. - + Both collections contain the same elements. + Les deux collections contiennent des éléments identiques. + - Both collection references point to the same collection object. {0} - Les deux collections Reference pointent vers le même objet Collection. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Les deux collections contiennent les mêmes éléments. {0} - - - - '{0}' expression: '{1}'. - « {0} » expression : « {1} ». - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - expression « {0} », « {1} », expression « {2} », « {3} », expression « {4} », « {5} ». - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - expression « {0} » : « {1} », expression « {2} » : « {3} ». - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - La chaîne '{0}' ne contient pas la chaîne '{1}'. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Collection attendue pour contenir l’élément spécifié. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Au moins un élément doit correspondre au prédicat. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Collection attendue pour contenir exactement un élément mais {1} élément(s) trouvé(s). {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Un seul élément était attendu pour correspondre au prédicat, mais {1} élément(s) trouvé(s). {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - La chaîne « {0} » contient la chaîne « {1} ». {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Collection attendue pour ne pas contenir l’élément spécifié. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Aucun élément ne doit correspondre au prédicat. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - La chaîne '{0}' se termine par la chaîne '{1}'. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - La chaîne '{0}' commence par la chaîne '{1}'. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Le nombre d'éléments dans les collections ne correspond pas. Attendu : <{1}>, Réel : <{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - L’élément au {0} d’index ne correspond pas. -Attendu : {1} -Réel : {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - L'élément à l'index {1} n'est pas du type attendu. Type attendu : <{2}>, Type réel : <{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - La chaîne '{0}' ne se termine pas par la chaîne '{1}'. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Réel : {2} Échec de {0}. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Collection de tailles attendue {1}. Réel : {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Réel : {2} URL de ticket GitHub non valide - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - La valeur « {0} » n'est pas dans la plage attendue [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Réel : {2} La valeur maximale doit être supérieure ou égale à la valeur minimale. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0}Type attendu :<{1}>. Type réel :<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - La chaîne '{0}' ne correspond pas au modèle '{1}'. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - La collection doit contenir n’importe quel élément, mais elle est vide. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Type incorrect : <{1}>, Type réel : <{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Type exact attendu :<{1}>. Type réel :<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Type exact incorrect :<{1}>. Type réel :<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - La chaîne '{0}' correspond au modèle '{1}'. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Réel : {2} L’élément ou les éléments <{0}> n’est ou ne sont pas présent(s) dans la collection. - - String '{0}' does not start with string '{1}'. {2} - La chaîne '{0}' ne commence pas par la chaîne '{1}'. {2} - - The property {0} has type {1}; expected type {2}. La propriété {0} possède le type {1} ; type attendu {2}. @@ -358,21 +358,16 @@ Réel : {2} (objet) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Échec de la réception du message pour une exception de type {0} en raison d'une exception.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Type d’exception attendu :<{1}> mais aucune exception n’a été levée. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Type d’exception attendu :<{1}>. Type d’exception réel :<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Réel : {2} La propriété ou la méthode {0} sur {1} retourne un IEnumerable<object[]> vide. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - La valeur réelle <{2}> n’est pas supérieure à la valeur attendue <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - La valeur réelle <{2}> n’est pas supérieure ou égale à la valeur attendue <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - La valeur réelle <{2}> n’est pas inférieure à la valeur attendue <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - La valeur réelle <{2}> n’est pas inférieure ou égale à la valeur attendue <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - La valeur attendue <{1}> doit être positive. {0} - - - - Expected value <{1}> to be negative. {0} - La valeur attendue <{1}> doit être négative. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals ne doit pas être utilisé pour les assertions. Utilisez Assert.AreEqual & overloads à la place. @@ -458,6 +423,11 @@ Réel : {2} CollectionAssert.ReferenceEquals ne doit pas être utilisé pour les assertions. Utilisez plutôt les méthodes CollectionAssert ou Assert.AreSame & overloads. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf index bfdc4c7ee6..4d258a5234 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - La raccolta prevista contiene {1} occorrenza/e di <{2}>. La raccolta effettiva contiene {3} occorrenza/e. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Rilevato elemento duplicato:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Previsto:<{1}>. Effettivo:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Prevista una differenza non maggiore di <{3}> tra il valore previsto <{1}> e il valore effettivo <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Previsto:<{1}>. La combinazione di maiuscole e minuscole è diversa per il valore effettivo:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Previsto:<{1} ({2})>. Effettivo:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Previsto: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Ma era: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ La lunghezza della stringa prevista è {0} ma era {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Previsto qualsiasi valore tranne:<{1}>. Effettivo:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Prevista una differenza maggiore di <{3}> tra il valore previsto <{1}> e il valore effettivo <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Non passare tipi valore a AreSame(). I valori convertiti in Object non saranno mai uguali. Usare AreEqual(). {0} - - Details: - Dettagli: - - - - Assert.That({0}) failed. - Assert.That({0}) non riuscito. - {0} is the user code expression - - - Message: {0} - Messaggio: {0} - {0} user provided message - - Both collections are empty. {0} - Le raccolte sono entrambe vuote. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Le raccolte contengono entrambe gli stessi elementi. - + Both collections contain the same elements. + Le raccolte contengono entrambe gli stessi elementi. + - Both collection references point to the same collection object. {0} - I riferimenti a raccolte puntano entrambi allo stesso oggetto Collection. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Le raccolte contengono entrambe gli stessi elementi. {0} - - - - '{0}' expression: '{1}'. - Espressione '{0}': '{1}'. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Espressione '{0}': '{1}', espressione '{2}': '{3}', espressione '{4}': '{5}'. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Espressione '{0}': '{1}', espressione '{2}': '{3}'. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - La stringa '{0}' non contiene la stringa '{1}'. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - La raccolta dovrebbe contenere l'elemento specificato. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Almeno un elemento dovrebbe corrispondere al predicato. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - La raccolta dovrebbe contenere un unico elemento, ma ne sono stati trovati {1}. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Un unico elemento dovrebbe corrispondere al predicato, ma ne sono stati trovati {1}. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - La stringa '{0}' contiene la stringa '{1}'. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - La raccolta non dovrebbe contenere l'elemento specificato. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Nessun elemento dovrebbe corrispondere al predicato. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - La stringa '{0}' termina con la stringa '{1}'. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - La stringa '{0}' inizia con la stringa '{1}'. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Il numero di elementi nelle raccolte non corrisponde. Previsto:<{1}>. Effettivo:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - L'elemento nell'indice {0} non corrisponde. -Previsto: {1} -Effettivo: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - L'elemento nell'indice {1} non è del tipo previsto. Tipo previsto:<{2}>. Tipo effettivo:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - La stringa '{0}' non termina con la stringa '{1}'. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Effettivo: {2} {0} non riuscita. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Prevista raccolta di dimensioni {1}. Effettivo: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Effettivo: {2} L'URL del ticket GitHub non è valido - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Il valore '{0}' non è compreso nell'intervallo previsto [{1}, {2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Effettivo: {2} Il valore massimo deve essere maggiore o uguale al valore minimo. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Tipo previsto:<{1}>. Tipo effettivo:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - La stringa '{0}' non corrisponde al criterio '{1}'. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - È previsto che la raccolta contenga qualsiasi elemento, ma è vuota. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Tipo errato:<{1}>. Tipo effettivo:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Tipo esatto previsto:<{1}>. Tipo effettivo:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Tipo esatto errato:<{1}>. Tipo effettivo:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - La stringa '{0}' corrisponde al criterio '{1}'. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Effettivo: {2} Gli elementi <{0}> non sono presenti nella raccolta. - - String '{0}' does not start with string '{1}'. {2} - La stringa '{0}' non inizia con la stringa '{1}'. {2} - - The property {0} has type {1}; expected type {2}. Il tipo della proprietà {0} è {1}, ma quello previsto è {2}. @@ -358,21 +358,16 @@ Effettivo: {2} (oggetto) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) Non è stato possibile ottenere il messaggio per un'eccezione di tipo {0} a causa di un'eccezione. - - Expected exception type:<{1}> but no exception was thrown. {0} - È previsto il tipo di eccezione: <{1}> ma non è stata generata alcuna eccezione. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Tipo di eccezione previsto:<{1}>. Tipo di eccezione effettivo: <{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Effettivo: {2} La proprietà o il metodo {0} nella classe {1} restituisce un elemento IEnumerable<object[]> vuoto. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Il valore effettivo <{2}> non è maggiore del valore previsto <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Il valore effettivo <{2}> non è maggiore o uguale al valore previsto <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Il valore effettivo <{2}> non è minore del valore previsto <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Il valore effettivo <{2}> non è minore o uguale al valore previsto <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Il valore <{1}{0}> dovrebbe essere positivo. - - - - Expected value <{1}> to be negative. {0} - Il valore <{1}{0}> dovrebbe essere negativo. - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Non è possibile usare Assert.Equals per le asserzioni. Usare Assert.AreEqual e gli overload. @@ -458,6 +423,11 @@ Effettivo: {2} Non è possibile usare CollectionAssert.ReferenceEquals per le asserzioni. In alternativa, usare i metodi CollectionAssert o Assert.AreSame e gli overload. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf index bdced96434..d858e8b746 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - 予期されたコレクションでは、<{2}> が {1} 回発生します。実際のコレクションでは、{3} 回発生します。{0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - 重複する項目が見つかりました:<{1}>。{0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - <{1}> が必要ですが、<{2}> が指定されました。{0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 指定する値 <{1}> と実際の値 <{2}> との間には <{3}> 以内の差が必要です。{0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - <{1}> が必要です。実際の値: <{2}> では大文字と小文字が異なります。{0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - <{1} ({2})> が必要ですが、<{3} ({4})> が指定されました。{0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - 期待値: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - しかし、次でした: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ 期待される文字列の長さは {0} ですが、実際は {1} でした。 - - Expected any value except:<{1}>. Actual:<{2}>. {0} - <{1}> 以外の任意の値が必要ですが、<{2}> が指定されています。{0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 指定する値 <{1}> と実際の値 <{2}> との間には、<{3}> を超える差が必要です。{0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} AreSame() には値型を渡すことはできません。オブジェクトに変換された値が同じにはなりません。AreEqual() を使用することを検討してください。{0} - - Details: - 詳細: - - - - Assert.That({0}) failed. - Assert.That({0}) に失敗しました。 - {0} is the user code expression - - - Message: {0} - メッセージ: {0} - {0} user provided message - - Both collections are empty. {0} - 両方のコレクションが空です。{0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - 両方のコレクションが同じ要素を含んでいます。 - + Both collections contain the same elements. + 両方のコレクションが同じ要素を含んでいます。 + - Both collection references point to the same collection object. {0} - 両方のコレクションの参照が、同じコレクション オブジェクトにポイントしています。{0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - 両方のコレクションが同じ要素を含んでいます。{0} - - - - '{0}' expression: '{1}'. - '{0}' 式: '{1}'。 - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - '{0}' 式: '{1}'、'{2}' 式: '{3}'、'{4}' 式: '{5}'。 - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - '{0}' 式: '{1}'、'{2}' 式: '{3}'。 - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}。{1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - 文字列 '{0}' は文字列 '{1}' を含んでいません。{2}。 - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - 指定された項目を含むコレクションが必要です。{0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - 述語と一致する項目が少なくとも 1 つ必要です。{0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - コレクションには 1 つの要素だけを含める必要がありますが、{1} 要素が見つかりました。{0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - 述語と一致する項目が 1 つだけ必要ですが、{1} 項目が見つかりました。{0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - 文字列 '{0}' は文字列 '{1}' を含んでいます。{2}。 + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - 指定された項目を含まないコレクションが必要です。{0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - 述語に一致する項目が必要ありません。{0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - 文字列 '{0}' の末尾は文字列 '{1}' です。{2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - 文字列 '{0}' は文字列 '{1}' で始まります。 {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - コレクション内の要素数が一致しません。<{1}> が必要ですが <{2}> が指定されています。{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - インデックス {0} の要素が一致しません。 -予想: {1} -実際: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - インデックス {1} の要素は、必要な型ではありません。<{2}> が必要ですが、<{3}> が指定されています。{0} - - - - String '{0}' does not end with string '{1}'. {2} - 文字列 '{0}' は文字列 '{1}' で終わりません。{2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Actual: {2} {0} に失敗しました。{1} - - Expected collection of size {1}. Actual: {2}. {0} - サイズ {1} のコレクションが必要です。実際: {2}。{0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Actual: {2} GitHub チケット URL が無効です - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - 値 '{0}' は予期される範囲 [{1}..{2}] 内にありません。{3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Actual: {2} 最大値は、最小値以上である必要があります。 - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} には型 <{1}> が必要ですが、型 <{2}> が指定されました。 - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - 文字列 '{0}' はパターン '{1}' と一致しません。{2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - コレクションには項目が含まれている必要がありますが、空です。{0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - 正しくない型は <{1}> であり、実際の型は <{2}> です。{0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} 正確な型が必要です: <{1}>。実際の型: <{2}>。 - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - 間違った正確な型: <{1}>。実際の型: {2}。{0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - 文字列 '{0}' はパターン '{1}' と一致します。{2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Actual: {2} 要素 <{0}> がコレクション内に存在しません。 - - String '{0}' does not start with string '{1}'. {2} - 文字列 '{0}' は文字列 '{1}' で始まりません。{2} - - The property {0} has type {1}; expected type {2}. プロパティ {0} は型 {1} を含んでいますが、型 {2} が必要です。 @@ -358,21 +358,16 @@ Actual: {2} (オブジェクト) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (例外が発生したため、型 {0} の例外のメッセージを取得できませんでした。) - - Expected exception type:<{1}> but no exception was thrown. {0} - 例外の種類: <{1}> が予期されますが、例外はスローされませんでした。{0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - 予期される例外の種類: <{1}>。実際の例外の種類: <{2}>。{0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Actual: {2} {1} 上のプロパティまたはメソッド {0} は空の IEnumerable<object[]> を返します。 - - Actual value <{2}> is not greater than expected value <{1}>. {0} - 実際の値 <{2}> は、予期された値 <{1}> より大きくありません。{0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - 実際の値 <{2}> は、予期された値 <{1}> 以上ではありません。{0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - 実際の値 <{2}> は、予期された値 <{1}> より小さくありません。{0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - 実際の値 <{2}> は、予期された値 <{1}> 以下ではありません。{0} - - - - Expected value <{1}> to be positive. {0} - 正の値 <{1}> が必要です。{0} - - - - Expected value <{1}> to be negative. {0} - 負の値 <{1}> が必要です。{0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. アサーションには Assert.Equals を使用せずに、Assert.AreEqual とオーバーロードを使用してください。(& ) @@ -458,6 +423,11 @@ Actual: {2} アサーションには CollectionAssert.ReferenceEquals を使用しないでください。代わりに CollectionAssert メソッドまたは Assert.AreSame およびオーバーロードを使用してください。 + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf index 6d9292a56e..70ed44695f 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - 필요한 컬렉션에 <{2}>은(는) {1}개가 포함되어야 하는데 실제 컬렉션에는 {3}개가 포함되어 있습니다. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - 중복된 항목이 있습니다. <{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - 예상 값: <{1}>. 실제 값: <{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 예상 값 <{1}>과(와) 실제 값 <{2}>의 차이가 <{3}>보다 크지 않아야 합니다. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - 예상 값: <{1}>. 대/소문자가 다른 실제 값: <{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - 예상 값: <{1} ({2})>. 실제 값: <{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - 예상: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - 그러나 다음과 같습니다. - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ 문자열 길이 {0}(을)를 예상했지만 {1}입니다. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - 예상 값: <{1}>을(를) 제외한 모든 값. 실제 값: <{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 예상 값 <{1}>과(와) 실제 값 <{2}>의 차이가 <{3}>보다 커야 합니다. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} AreSame()에 값 형식을 전달하면 안 됩니다. Object로 변환된 값은 동일한 값으로 간주되지 않습니다. AreEqual()을 사용해 보세요. {0} - - Details: - 세부 정보: - - - - Assert.That({0}) failed. - Assert.That({0})이(가) 실패했습니다. - {0} is the user code expression - - - Message: {0} - 메시지: {0} - {0} user provided message - - Both collections are empty. {0} - 두 컬렉션이 모두 비어 있습니다. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - 두 컬렉션에 같은 요소가 포함되어 있습니다. - + Both collections contain the same elements. + 두 컬렉션에 같은 요소가 포함되어 있습니다. + - Both collection references point to the same collection object. {0} - 두 컬렉션 참조가 동일한 컬렉션 개체를 가리킵니다. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - 두 컬렉션에 같은 요소가 포함되어 있습니다. {0} - - - - '{0}' expression: '{1}'. - '{0}' 식: '{1}'. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - ' {0}' 식: '{1}', '{2}' 식: '{3}', '{4}' 식: '{5}'. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - '{0}' 식: '{1}', '{2}' 식: '{3}'. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - '{0}' 문자열이 '{1}' 문자열을 포함하지 않습니다. {2} - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - 지정한 항목을 포함할 컬렉션이 필요합니다. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - 조건자와 일치하는 항목이 하나 이상 필요합니다. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - 정확히 하나의 요소를 포함할 컬렉션이 필요하지만 {1}개 요소가 발견되었습니다. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - 조건자에 일치하는 항목이 하나만 필요하지만 {1}개 항목이 발견되었습니다. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - '{0}' 문자열에 '{1}' 문자열이 포함되어 있습니다. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - 지정한 항목을 포함하지 않을 컬렉션이 필요합니다. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - 조건자와 일치하는 항목이 필요하지 않습니다. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - 문자열 '{0}'은 문자열 '{1}'(으)로 끝납니다. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - 문자열 '{0}'은 문자열 '{1}'(으)로 시작합니다. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - 컬렉션의 요소 수가 일치하지 않습니다. 예상 값: <{1}>. 실제 값: <{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - 인덱스 {0}에 있는 요소가 일치하지 않습니다. -예상: {1} -실제: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - 인덱스 {1}에 있는 요소가 필요한 형식이 아닙니다. 필요한 형식: <{2}>, 실제 형식: <{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - '{0}' 문자열이 '{1}' 문자열로 끝나지 않습니다. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Actual: {2} {0}이(가) 실패했습니다. {1} - - Expected collection of size {1}. Actual: {2}. {0} - {1} 크기 컬렉션이 필요합니다. 실제: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Actual: {2} 잘못된 GitHub 티켓 URL - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - '{0}' 값이 예상 범위 [{1}..{2}] 내에 있지 않습니다. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Actual: {2} 최댓값은 최솟값보다 크거나 같아야 합니다. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} 예상 형식: <{1}>, 실제 형식: <{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - '{0}' 문자열이 '{1}' 패턴과 일치하지 않습니다. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - 항목을 포함할 컬렉션이 필요한데 비어 있습니다. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - 잘못된 형식: <{1}>, 실제 형식: <{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} 예상되는 정확한 형식:<{1}>. 실제 형식: <{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - 잘못된 정확한 형식:<{1}>. 실제 형식: <{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - '{0}' 문자열이 '{1}' 패턴과 일치합니다. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Actual: {2} 컬렉션에 <{0}> 요소가 없습니다. - - String '{0}' does not start with string '{1}'. {2} - '{0}' 문자열이 '{1}' 문자열로 시작되지 않습니다. {2} - - The property {0} has type {1}; expected type {2}. {0} 속성의 형식은 {2}이어야 하는데 실제로는 {1}입니다. @@ -358,21 +358,16 @@ Actual: {2} (개체) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (예외로 인해 {0} 형식의 예외에 대한 메시지를 가져오지 못했습니다.) - - Expected exception type:<{1}> but no exception was thrown. {0} - 예상 예외 형식:<{1}> 하지만 예외가 발생하지 않음. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - 예상 예외 형식:<{1}>. 실제 예상 형식:<{2}>. {0} - - {0} ({1}) {0}({1}) @@ -398,36 +393,6 @@ Actual: {2} {1}의 속성 또는 메서드 {0}이(가) 빈 IEnumerable<object[]>를 반환합니다. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - 실제 값 <{2}>은(는)는 예상 값 <{1}>보다 크지 않습니다. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - 실제 값 <{2}>은(는)는 예상 값 <{1}>보다 크거나 같지 않습니다. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - 실제 값 <{2}>은(는)는 예상 값 <{1}>보다 작지 않습니다. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - 실제 값 <{2}>은(는)는 예상 값 <{1}>보다 작거나 같지 않습니다. {0} - - - - Expected value <{1}> to be positive. {0} - 예상 값 <{1}>은(는) 양수일 것으로 예상합니다. {0} - - - - Expected value <{1}> to be negative. {0} - 예상 값 <{1}>은(는) 음수일 것으로 예상합니다. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. 어설션에 Assert.Equals를 사용할 수 없습니다. 대신 Assert.AreEqual 및 오버로드를 사용하세요. @@ -458,6 +423,11 @@ Actual: {2} CollectionAssert.ReferenceEquals는 Assertions에 사용할 수 없습니다. 대신 CollectionAssert 메서드 또는 Assert.AreSame 및 오버로드를 사용하세요. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf index c50ff5897a..eaaf923f6f 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Oczekiwana kolekcja zawiera {1} wystąpień <{2}>. Bieżąca kolekcja zawiera {3} wystąpień. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Znaleziono duplikat:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Oczekiwana:<{1}>. Rzeczywista:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Oczekiwano różnicy nie większej niż <{3}> pomiędzy oczekiwaną wartością <{1}> a rzeczywistą wartością <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Oczekiwano:<{1}>. Przypadek różni się od rzeczywistej wartości:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Oczekiwana:<{1} ({2})>. Rzeczywista:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Oczekiwane: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Ale było: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Oczekiwano ciągu o długości {0}, ale miał wartość {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Oczekiwano dowolnej wartości za wyjątkiem:<{1}>. Rzeczywista:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Oczekiwano różnicy większej niż <{3}> pomiędzy oczekiwaną wartością <{1}> a rzeczywistą wartością <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Nie przekazuj typów wartości do metody AreSame(). Wartości przekonwertowane na typ Object nigdy nie będą takie same. Rozważ użycie metody AreEqual(). {0} - - Details: - Szczegóły: - - - - Assert.That({0}) failed. - Operacja Assert.That({0}) nie powiodła się. - {0} is the user code expression - - - Message: {0} - Komunikat: {0} - {0} user provided message - - Both collections are empty. {0} - Obie kolekcje są puste. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Obie kolekcje zawierają te same elementy. - + Both collections contain the same elements. + Obie kolekcje zawierają te same elementy. + - Both collection references point to the same collection object. {0} - Odwołania do obu kolekcji wskazują ten sam obiekt kolekcji. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Obie kolekcje zawierają te same elementy. {0} - - - - '{0}' expression: '{1}'. - Wyrażenie „{0}”: „{1}”. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Wyrażenie „{0}”: „{1}”, wyrażenie „{2}”: „{3}”, wyrażenie „{4}”: „{5}”. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Wyrażenie „{0}”: „{1}”, wyrażenie „{2}”: „{3}”. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - Ciąg „{0}” nie zawiera ciągu „{1}”. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Oczekiwano, że kolekcja będzie zawierać określony element. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Oczekiwano co najmniej jednego elementu zgodnego z predykatem. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Oczekiwano, że kolekcja będzie zawierać dokładnie jeden element, ale znaleziono {1} elementów. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Oczekiwano dokładnie jednego elementu zgodnego z predykatem, ale znaleziono {1} elementów. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - Ciąg „{0}” zawiera ciąg „{1}”. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Oczekiwano, że kolekcja nie będzie zawierać określonego elementu. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Nie oczekiwano elementów zgodnych z predykatem. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - Ciąg „{0}” kończy się ciągiem „{1}”. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - Ciąg „{0}” rozpoczyna się od ciągu „{1}”. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Nie zgadza się liczba elementów w kolekcji. Oczekiwana:<{1}>. Rzeczywista:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - Element w indeksie {0} nie jest zgodny. -Oczekiwano: {1} -Rzeczywiste: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - Element o indeksie {1} jest innego typu niż oczekiwano. Oczekiwany typ:<{2}>. Rzeczywisty typ:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - Ciąg „{0}” nie kończy się ciągiem „{1}”. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Rzeczywiste: {2} {0} — niepowodzenie. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Oczekiwano kolekcji rozmiaru {1}. Wartość rzeczywista: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Rzeczywiste: {2} Nieprawidłowy adres URL biletu usługi GitHub - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Wartość „{0}” nie mieści się w oczekiwanym zakresie [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Rzeczywiste: {2} Wartość maksymalna musi być większa niż wartość minimalna lub jej równa. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Oczekiwany typ:<{1}>. Rzeczywisty typ:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - Ciąg „{0}” nie jest zgodny ze wzorcem „{1}”. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Oczekiwano, że kolekcja będzie zawierać dowolny element, ale jest pusta. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Zły typ:<{1}>. Rzeczywisty typ:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Oczekiwano dokładnego typu:<{1}>. Rzeczywisty typ:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Nieprawidłowy dokładny typ:<{1}>. Rzeczywisty typ:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - Ciąg „{0}” jest zgodny ze wzorcem „{1}”. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Rzeczywiste: {2} Elementy <{0}> nie występują w kolekcji. - - String '{0}' does not start with string '{1}'. {2} - Ciąg „{0}” nie rozpoczyna się od ciągu „{1}”. {2} - - The property {0} has type {1}; expected type {2}. Właściwość {0} jest typu {1}; oczekiwano typu {2}. @@ -358,21 +358,16 @@ Rzeczywiste: {2} (obiekt) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Nie można pobrać komunikatu dotyczącego wyjątku typu {0} z powodu wyjątku). - - Expected exception type:<{1}> but no exception was thrown. {0} - Oczekiwano typu wyjątku:<{1}>, ale nie zgłoszono wyjątku. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Oczekiwano typu wyjątku:<{1}>. Rzeczywisty typ wyjątku:<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Rzeczywiste: {2} Właściwość lub metoda {0} w elemencie {1} zwraca pusty interfejs IEnumerable<object[]>. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Wartość rzeczywista <{2}> nie jest większa niż oczekiwana wartość <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Wartość rzeczywista <{2}> nie jest większa lub równa oczekiwanej wartości <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Wartość rzeczywista <{2}> nie jest mniejsza niż oczekiwana wartość <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Wartość rzeczywista <{2}> nie jest mniejsza lub równa oczekiwanej wartości <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Oczekiwana wartość <{1}> powinna być dodatnia. {0} - - - - Expected value <{1}> to be negative. {0} - Oczekiwana wartość <{1}> powinna być negatywna. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals nie powinno być używane do potwierdzania. Zamiast tego użyj Assert.AreEqual i przeciążeń. @@ -458,6 +423,11 @@ Rzeczywiste: {2} Element Assert.ReferenceEquals nie powinien być używany dla asercji. Zamiast tego użyj metod CollectionAssert lub Assert.AreSame oraz ich przeciążeń. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf index faf04cc886..18b55371e2 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - A coleção esperada contém {1} ocorrência(s) de <{2}>. A coleção real contém {3} ocorrência(s). {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Item duplicado encontrado:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Esperado:<{1}>. Real:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Esperada uma diferença não maior que <{3}> entre o valor esperado <{1}> e o valor real <{2}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Esperado:<{1}>. Capitalização é diferente para o valor real:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Esperado:<{1} ({2})>. Real:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Esperado: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Mas foi: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Comprimento esperado da cadeia de caracteres {0}, mas foi {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Esperado qualquer valor exceto:<{1}>. Real:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Esperada uma diferença maior que <{3}> entre o valor esperado <{1}> e o valor real <{2}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Não passe tipos de valores para AreSame(). Os valores convertidos para Object nunca serão os mesmos. Considere usar AreEqual(). {0} - - Details: - Detalhes: - - - - Assert.That({0}) failed. - Assert.That({0}) falhou. - {0} is the user code expression - - - Message: {0} - Mensagem: {0} - {0} user provided message - - Both collections are empty. {0} - Ambas as coleções estão vazias. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Ambas as coleções contêm os mesmos elementos. - + Both collections contain the same elements. + Ambas as coleções contêm os mesmos elementos. + - Both collection references point to the same collection object. {0} - Ambas as referências de coleção apontam para o mesmo objeto de coleção. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Ambas as coleções contêm os mesmos elementos. {0} - - - - '{0}' expression: '{1}'. - Expressão "{0}": "{1}". - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Expressão "{0}": "{1}", "{2}" expressão: "{3}", "{4}" expressão: "{5}". - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Expressão "{0}": "{1}", "{2}" expressão: "{3}". - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - A cadeia de caracteres '{0}' não contém a cadeia de caracteres '{1}'. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - A coleção esperada contém o item especificado. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Esperava-se que pelo menos um item correspondesse ao predicado. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - A coleção esperada contém exatamente um elemento, mas encontrou {1} elementos. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Esperava-se exatamente um item para corresponder ao predicado, mas encontrou {1} itens. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - A cadeia de caracteres "{0}" contém a cadeia de caracteres "{1}". {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - A coleção esperada não contém o item especificado. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Não era esperado nenhum item que corresponda ao predicado. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - A cadeia de caracteres “{0}” termina com cadeia de caracteres “{1}”. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - A cadeia de caracteres “{0}” começa com a cadeia de caracteres “{1}”. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - O número de elementos nas coleções não coincidem. Esperado:<{1}>. Real:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - O elemento no índice {0} não corresponde. -Esperado: {1} -Real: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - Elemento de índice {1} não é de tipo esperado. Tipo esperado:<{2}>. Tipo real:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - A cadeia de caracteres “{0}” não termina com a cadeia de caracteres “{1}”. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Real: {2} {0} falhou. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Coleção esperada de tamanho {1}. Real: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Real: {2} URL de tíquete do GitHub inválida - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - O valor '{0}' não está dentro do intervalo esperado [{1}.. {2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Real: {2} O valor máximo deve ser maior ou igual ao valor mínimo. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Tipo esperado:<{1}>. Tipo real:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - A cadeia de caracteres “{0}” não corresponde ao padrão “{1}”. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - A coleção esperada conter qualquer item, mas ela está vazia. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Tipo errado:<{1}>. Tipo real:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Tipo exato esperado:<{1}>. Tipo real:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Tipo exato errado:<{1}>. Tipo real:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - A cadeia de caracteres “{0}” corresponde ao padrão “{1}”. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Real: {2} O(s) elemento(s) <{0}> não está/estão presente(s) na coleção. - - String '{0}' does not start with string '{1}'. {2} - A cadeia de caracteres “{0}” não começa com a cadeia de caracteres “{1}”. {2} - - The property {0} has type {1}; expected type {2}. A propriedade {0} é do tipo {1}; o tipo esperado era {2}. @@ -358,21 +358,16 @@ Real: {2} (objeto) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Falha ao obter a mensagem para uma exceção do tipo {0} devido a uma exceção.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Tipo de exceção esperado:<{1}> mas nenhuma exceção foi lançada. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Tipo de exceção esperado:<{1}>. Tipo de exceção real:<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Real: {2} A propriedade ou o método {0} em {1} retorna um IEnumerable<object[]> vazio. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - O valor <{2}> real não é maior que o valor esperado <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - O valor <{2}> real não é maior ou igual ao valor esperado <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - O valor <{2}> real não é menor que o valor esperado <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - O valor <{2}> real não é menor ou igual ao valor esperado <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - O valor <{1}> esperado deve ser positivo. {0} - - - - Expected value <{1}> to be negative. {0} - O valor <{1}> esperado deve ser negativo. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals não deveria ser usado para Declarações. Use Assert.AreEqual e sobrecargas em seu lugar. @@ -458,6 +423,11 @@ Real: {2} CollectionAssert.ReferenceEquals não deve ser usado com as Declarações. Em vez disso, use os métodos CollectionAssert ou Assert.AreSame e as sobrecargas. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf index e39af70016..db55e28ead 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Ожидаемый набор содержит следующее число событий <{2}>: {1}. Фактический набор содержит число событий: {3}. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Обнаружен совпадающий элемент: <{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Ожидается: <{1}>. Фактически: <{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Между ожидаемым значением <{1}> и фактическим значением <{2}> требуется разница не более чем <{3}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Ожидается: <{1}>. Отличается на фактическое значение: <{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Ожидается: <{1} ({2})>. Фактически: <{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Ожидалось: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Было: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Ожидалась длина строки: {0}, фактическая длина строки: {1}. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Ожидается любое значение, кроме: <{1}>. Фактически: <{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Между ожидаемым значением <{1}> и фактическим значением <{2}> требуется разница более чем <{3}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} Не передавайте типы значений в функцию AreSame(). Значения, преобразованные в Object, никогда не будут одинаковыми. Попробуйте использовать AreEqual(). {0} - - Details: - Подробности: - - - - Assert.That({0}) failed. - Сбой Assert.That({0}). - {0} is the user code expression - - - Message: {0} - Сообщение: {0} - {0} user provided message - - Both collections are empty. {0} - Обе коллекции пусты. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Обе коллекции содержат одинаковые элементы. - + Both collections contain the same elements. + Обе коллекции содержат одинаковые элементы. + - Both collection references point to the same collection object. {0} - Ссылки в обоих коллекциях указывают на один и тот же объект коллекции. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Обе коллекции содержат одинаковые элементы. {0} - - - - '{0}' expression: '{1}'. - Выражение "{0}": "{1}". - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - Выражение "{0}": "{1}", выражение "{2}": "{3}", выражение "{4}": "{5}". - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - Выражение "{0}": "{1}", выражение "{2}": "{3}". - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - Строка "{0}" не содержит строку "{1}". {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Ожидалось, что коллекция будет содержать указанный элемент. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - Ожидался по крайней мере один элемент, соответствующий предикату. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Ожидалось, что коллекция будет содержать ровно один элемент, но найдено элементов: {1}. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Ожидался ровно один элемент, соответствующий предикату, но найдено элементов: {1}. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - Строка "{0}" не содержит строку "{1}". {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Ожидалось, что коллекция не будет содержать указанный элемент. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Ожидалось, что ни один элемент не будет соответствовать предикату. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - Строка "{0}" заканчивается строкой "{1}". {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - Строка "{0}" начинается со строки "{1}". {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Число элементов в наборе не соответствует ожидаемому. Ожидается: <{1}>. Фактически: <{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - Элемент по индексу {0} не совпадает. -Ожидается: {1} -Фактическое значение: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - Тип элемента по индексу {1} не соответствует ожидаемому. Ожидаемый тип: <{2}>. Фактический тип: <{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - Строка "{0}" не заканчивается строкой "{1}". {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Actual: {2} Сбой {0}. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Ожидается коллекция размеров {1}. Фактически: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Actual: {2} Недопустимый URL-адрес билета GitHub - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Значение "{0}" не находится в пределах ожидаемого диапазона [{1}..{2}]. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Actual: {2} Максимальное значение должно быть больше минимального значения или равно ему. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0}Ожидается тип: <{1}>. Фактический тип: <{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - Строка "{0}" не соответствует шаблону "{1}". {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Ожидается, что коллекция будет содержать любой элемент, но она пуста. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Неверный тип: <{1}>. Фактический тип: <{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Ожидается точный тип: <{1}>. Фактический тип: <{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Неверный точный тип: <{1}>. Фактический тип: <{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - Строка "{0}" соответствует шаблону "{1}". {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Actual: {2} Элементы <{0}> отсутствуют в коллекции. - - String '{0}' does not start with string '{1}'. {2} - Строка "{0}" не начинается со строки "{1}". {2} - - The property {0} has type {1}; expected type {2}. Свойство {0} имеет тип {1}. Ожидается тип {2}. @@ -358,21 +358,16 @@ Actual: {2} (объект) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Не удалось получить сообщение для исключения с типом {0} в связи с возникновением исключения.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Ожидаемый тип исключения:<{1}> но исключение не создано. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Ожидаемый тип исключения:<{1}>. Фактический тип исключения:<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Actual: {2} Свойство или метод {0} класса {1} возвращает пустой IEnumerable<object[]>. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Действительное значение <{2}> не больше ожидаемого значения <{1}>. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Действительное значение <{2}> не больше или не равно ожидаемому значению <{1}>. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Действительное значение <{2}> не меньше ожидаемого значения <{1}>. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Действительное значение <{2}> не меньше или не равно ожидаемому значению <{1}>. {0} - - - - Expected value <{1}> to be positive. {0} - Ожидалось, что значение <{1}> будет положительным. {0} - - - - Expected value <{1}> to be negative. {0} - Ожидалось, что значение <{1}> будет отрицательным. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Нельзя использовать Assert.Equals для Assertions. Вместо этого используйте Assert.AreEqual и перегрузки. @@ -458,6 +423,11 @@ Actual: {2} Нельзя использовать CollectionAssert.ReferenceEquals для Assertions. Вместо этого используйте методы CollectionAssert или Assert.AreSame и перегрузки. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf index 3a24012694..9e98081b26 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - Beklenen koleksiyon {1} <{2}> örneği içerir. Gerçek koleksiyon {3} örnek içerir. {0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - Yinelenen öğe bulundu:<{1}>. {0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - Beklenen:<{1}>. Gerçek:<{2}>. {0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Beklenen değer <{1}> ile gerçek değer <{2}> arasında, şundan büyük olmayan fark bekleniyor: <{3}>. {0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - Beklenen:<{1}>. Durum, gerçek değer için farklı:<{2}>. {0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - Beklenen:<{1} ({2})>. Gerçek:<{3} ({4})>. {0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - Beklenen: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - Ancak: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ Beklenen dize uzunluğu {0} idi, ancak dize uzunluğu {1} oldu. - - Expected any value except:<{1}>. Actual:<{2}>. {0} - Şunun dışında bir değer bekleniyor:<{1}>. Gerçek:<{2}>. {0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - Beklenen değer <{1}> ile gerçek değer <{2}> arasında, şundan büyük olan fark bekleniyor: <{3}>. {0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} AreSame()'e değer türleri geçirmeyin. Object olarak dönüştürülen değerler asla aynı olamayacak. AreEqual() kullanmayı düşün. {0} - - Details: - Ayrıntılar: - - - - Assert.That({0}) failed. - Assert.That({0}) başarısız oldu. - {0} is the user code expression - - - Message: {0} - İleti: {0} - {0} user provided message - - Both collections are empty. {0} - Koleksiyonların her ikisi de boş. {0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - Her iki koleksiyon da aynı öğeleri içeriyor. - + Both collections contain the same elements. + Her iki koleksiyon da aynı öğeleri içeriyor. + - Both collection references point to the same collection object. {0} - Her iki koleksiyon başvurusu da aynı koleksiyon nesnesine işaret ediyor. {0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - Her iki koleksiyon da aynı öğeleri içeriyor. {0} - - - - '{0}' expression: '{1}'. - '{0}' ifadesi: '{1}'. - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - '{0}' ifadesi: '{1}', '{2}' ifadesi: '{3}', '{4}' ifadesi: '{5}'. - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - '{0}' ifadesi: '{1}', '{2}' ifadesi: '{3}'. - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}. {1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - '{0}' dizesi, '{1}' dizesini içermiyor. {2}. - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - Koleksiyonun belirtilen öğeyi içermesi bekleniyordu. {0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - En az bir öğenin koşulla eşleşmesi bekleniyordu. {0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - Beklenen koleksiyonun tam olarak bir öğe içermesi beklenirken, {1} öğe bulundu. {0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - Özellikle bir öğenin koşulla eşleşmesi beklenirken {1} öğe bulundu. {0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - '{0}' dizesi, '{1}' dizesini içermiyor. {2}. + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - Koleksiyonun belirtilen öğeyi içermemesi bekleniyordu. {0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - Hiçbir öğenin koşulla eşleşmesi beklenmiyordu. {0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - '{0}' dizesi '{1}' dizesi ile bitiyor. {2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - '{0}' dizesi '{1}' dizesi ile başlıyor. {2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Koleksiyonlar içindeki öğe sayıları eşleşmiyor. Beklenen:<{1}>. Gerçek:<{2}>.{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - {0} dizinindeki öğe eşleşmiyor. -Beklenen: {1} -Gerçekte olan: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - {1} dizinindeki öğe, beklenen türde değil. Beklenen tür:<{2}>. Gerçek tür:<{3}>.{0} - - - - String '{0}' does not end with string '{1}'. {2} - '{0}' dizesi, '{1}' dizesi ile sonlanmıyor. {2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Gerçekte olan: {2} {0} başarısız. {1} - - Expected collection of size {1}. Actual: {2}. {0} - Beklenen boyut {1}. Gerçek: {2}. {0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Gerçekte olan: {2} Geçersiz GitHub anahtar URL'si - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - Değer '{0}' beklenen aralık [{1}..{2}] içinde değil. {3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Gerçekte olan: {2} En büyük değer en küçük değerden büyük veya buna eşit olmalıdır. - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} Beklenen tür:<{1}>. Gerçek tür:<{2}>. - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - '{0}' dizesi, '{1}' deseni ile eşleşmiyor. {2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - Koleksiyonun herhangi bir öğe içermesi bekleniyordu ancak boş. {0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - Yanlış Tür:<{1}>. Gerçek tür:<{2}>. {0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} Beklenen tam tür:<{1}>. Gerçek tür:<{2}>. - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - Yanlış tam tür:<{1}>. Gerçek tür:<{2}>. {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - '{0}' dizesi, '{1}' deseni ile eşleşiyor. {2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Gerçekte olan: {2} Öğe(ler) <{0}> koleksiyonda mevcut değildir. - - String '{0}' does not start with string '{1}'. {2} - '{0}' dizesi, '{1}' dizesi ile başlamıyor. {2} - - The property {0} has type {1}; expected type {2}. {0} özelliği, {1} türüne sahip; beklenen tür {2}. @@ -358,21 +358,16 @@ Gerçekte olan: {2} (nesne) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (Bir özel durum nedeniyle, {0} türündeki özel durum iletisi alınamadı.) - - Expected exception type:<{1}> but no exception was thrown. {0} - Beklenen özel durum türü:<{1}> ancak hiçbir özel durum oluşmadı. {0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - Beklenen özel durum türü:<{1}>. Gerçek özel durum türü:<{2}>. {0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Gerçekte olan: {2} {1} üzerindeki {0} özelliği veya metodu boş IEnumerable<object[]> döndürür. - - Actual value <{2}> is not greater than expected value <{1}>. {0} - Geçerli <{2}> değeri, beklenen <{1}> değerinden daha büyük değil. {0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - Geçerli <{2}> değeri, beklenen <{1}> değerinden büyük veya bu değere eşit değil. {0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - Geçerli <{2}> değeri, beklenen <{1}> değerinden daha küçük değil. {0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - Geçerli <{2}> değeri, beklenen <{1}> değerinden küçük veya bu değere eşit değil. {0} - - - - Expected value <{1}> to be positive. {0} - Beklenen <{1}> değeri pozitif olmalıdır. {0} - - - - Expected value <{1}> to be negative. {0} - Beklenen <{1}> değeri negatif olmalıdır. {0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals, Onaylama için kullanılmamalı. Lütfen yerine Assert.AreEqual & aşırı yüklemeleri kullanın. @@ -458,6 +423,11 @@ Gerçekte olan: {2} CollectionAssert.ReferenceEquals, Onaylama için kullanılmamalı. Lütfen bunun yerine CollectionAssert yöntemlerini veya Assert.AreSame & aşırı yüklemelerini kullanın. + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf index 94100054a3..861b921af1 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - 所需集合包含 <{2}> 的 {1} 个匹配项。实际集合包含 {3} 个匹配项。{0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - 找到了重复项: <{1}>。{0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - 应为: <{1}>,实际为: <{2}>。{0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 预期值 <{1}> 和实际值 <{2}> 之间的差不应大于 <{3}>。{0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - 应为: <{1}>。实际值的大小写有所不同: <{2}>。{0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - 应为: <{1} ({2})>,实际为: <{3} ({4})>。{0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - 应为: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - 但却是: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ 字符串长度应为 {0},但为 {1}。 - - Expected any value except:<{1}>. Actual:<{2}>. {0} - 应为: <{1}> 以外的任意值,实际为: <{2}>。{0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 预期值 <{1}> 和实际值 <{2}> 之间的差应大于 <{3}>。{0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} 不要向 AreSame() 传递值类型。转换为 Object 的值将永远不会相等。请考虑使用 AreEqual()。{0} - - Details: - 详细信息: - - - - Assert.That({0}) failed. - Assert.That({0}) 失败。 - {0} is the user code expression - - - Message: {0} - 消息: {0} - {0} user provided message - - Both collections are empty. {0} - 这两个集合都为空。{0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - 这两个集合包含相同的元素。 - + Both collections contain the same elements. + 这两个集合包含相同的元素。 + - Both collection references point to the same collection object. {0} - 这两个集合引用指向同一个集合对象。{0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - 这两个集合包含相同的元素。{0} - - - - '{0}' expression: '{1}'. - ‘{0}’表达式:‘{1}’。 - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - ‘{0}’表达式:‘{1}’,‘{2}’表达式:‘{3}’,‘{4}’表达式:‘{5}’。 - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - ‘{0}’表达式:‘{1}’,‘{2}’表达式:‘{3}’。 - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}。{1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - 字符串“{0}”不包含字符串“{1}”。{2}。 - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - 预期集合包含指定项。{0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - 应至少有一项与谓词匹配。{0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - 预期集合仅包含一个元素,但找到 {1} 个元素。{0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - 应恰好只有一项与谓词匹配,但找到 {1} 项。{0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - 字符串“{0}”确实包含字符串“{1}”。{2} + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - 预期集合不包含指定项。{0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - 预期没有与谓词匹配的项。{0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - 字符串 '{0}' 以字符串 '{1}'结尾。{2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - 字符串 '{0}' 以字符串 '{1}' 开头。{2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - 集合中元素的数量不匹配。应为: <{1}>,实际为: <{2}>。{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - 索引 {0} 处的元素不匹配。 -预计值: {1} -实际值: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - 索引 {1} 处的元素不是所需类型。所需类型为: <{2}>,实际类型为: <{3}>。{0} - - - - String '{0}' does not end with string '{1}'. {2} - 字符串 '{0}' 不以字符串 '{1}' 结尾。{2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Actual: {2} {0} 失败。{1} - - Expected collection of size {1}. Actual: {2}. {0} - 大小 {1} 的预期集合。实际: {2}。{0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Actual: {2} GitHub 票证 URL 无效 - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - 值 "{0}" 不在预期范围 [{1}..{2}] 内。{3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Actual: {2} 最大值必须大于或等于最小值。 - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} 类型应为: <{1}>。类型实为: <{2}>。 - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - 字符串 '{0}' 与模式 '{1}' 不匹配。{2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - 集合应包含任何项,但它为空。{0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - 错误类型为: <{1}>,实际类型为: <{2}>。{0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} 预期的确切类型: <{1}>。实际类型: <{2}>。 - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - 错误的确切类型: <{1}>。实际类型: <{2}>。{0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - 字符串 '{0}' 与模式 '{1}' 匹配。{2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Actual: {2} 集合中不存在元素 <{0}>。 - - String '{0}' does not start with string '{1}'. {2} - 字符串 '{0}' 不以字符串 '{1}' 开头。{2} - - The property {0} has type {1}; expected type {2}. 属性 {0} 的类型为 {1};类型应为 {2}。 @@ -358,21 +358,16 @@ Actual: {2} (对象) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (因异常而未能获取类型为 {0} 的异常的消息。) - - Expected exception type:<{1}> but no exception was thrown. {0} - 预期异常类型:<{1}>,但未引发异常。{0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - 预期异常类型:<{1}>。实际异常类型:<{2}>。{0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Actual: {2} {1} 上的属性或方法 {0} 返回空 IEnumerable<object[]>。 - - Actual value <{2}> is not greater than expected value <{1}>. {0} - 实际值 <{2}> 不大于预期值 <{1}>。{0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - 实际值 <{2}> 不大于或等于预期值 <{1}>。{0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - 实际值 <{2}> 不小于预期值 <{1}>。{0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - 实际值 <{2}> 不小于或等于预期值 <{1}>。{0} - - - - Expected value <{1}> to be positive. {0} - 预期值 <{1}> 为正值。{0} - - - - Expected value <{1}> to be negative. {0} - 预期值 <{1}> 为负值。{0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals 不应用于断言。请改用 Assert.AreEqual 和重载。 @@ -458,6 +423,11 @@ Actual: {2} CollectionAssert.ReferenceEquals 不应用于断言。请改用 CollectionAssert 方法或 Assert.AreSame 和重载。 + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf index 3d758f945a..8b42dde962 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf @@ -8,55 +8,34 @@ - The expected collection contains {1} occurrence(s) of <{2}>. The actual collection contains {3} occurrence(s). {0} - 預期在集合中包含 {1} 項 <{2}>,但實際的集合卻有 {3} 項。{0} - + Expected collections to have matching element occurrences. + Expected collections to have matching element occurrences. + - Duplicate item found:<{1}>. {0} - 找到重複的項目: <{1}>。{0} - - - - Expected:<{1}>. Actual:<{2}>. {0} - 預期: <{1}>。實際: <{2}>。{0} - - - - Expected a difference no greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 預期值 <{1}> 和實際值 <{2}> 之間的預期差異沒有大於 <{3}>。{0} - - - - Expected:<{1}>. Case is different for actual value:<{2}>. {0} - 預期: <{1}>。大小寫與下列實際值不同: <{2}>。{0} - + Expected all items to be unique. + Expected all items to be unique. + - - Expected:<{1} ({2})>. Actual:<{3} ({4})>. {0} - 預期: <{1} ({2})>。實際: <{3} ({4})>。{0} - + + Expected all elements to match the predicate. + Expected all elements to match the predicate. + - - {0}{1} -{2} -{3} -{4} - {0}{1} -{2} -{3} -{4} + + Case differs. + Case differs. - - Expected: - 預期為: - + + Expected difference to be no greater than {0}. + Expected difference to be no greater than {0}. + - - But was: - 但為: - + + Expected values to be equal. + Expected values to be equal. + String lengths are both {0} but differ at index {1}. @@ -68,124 +47,104 @@ 預期的字串長度為 {0},但為 {1}。 - - Expected any value except:<{1}>. Actual:<{2}>. {0} - 預期任何值 (<{1}> 除外)。實際: <{2}>。{0} - + + Expected difference to be greater than {0}. + Expected difference to be greater than {0}. + - - Expected a difference greater than <{3}> between expected value <{1}> and actual value <{2}>. {0} - 預期值 <{1}> 和實際值 <{2}> 之間的預期差異大於 <{3}>。{0} - + + Expected values to not be equal. + Expected values to not be equal. + + + + Expected references to be different. + Expected references to be different. + + + + Expected references to be the same. + Expected references to be the same. + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). {0} 不要將實值型別傳遞給 AreSame()。轉換成 Object 的值從此不再一樣。請考慮使用 AreEqual()。{0} - - Details: - 詳細資料: - - - - Assert.That({0}) failed. - Assert.That({0}) 失敗。 - {0} is the user code expression - - - Message: {0} - 訊息: {0} - {0} user provided message - - Both collections are empty. {0} - 兩個集合皆空白。{0} - + Both collections are empty. + Both collections are empty. + - Both collection contain same elements. - 兩個集合含有相同的項目。 - + Both collections contain the same elements. + 兩個集合含有相同的項目。 + - Both collection references point to the same collection object. {0} - 兩個集合參考都指向同一個集合物件。{0} - + Both collection references point to the same collection object. + Both collection references point to the same collection object. + - Both collections contain the same elements. {0} - 兩個集合含有相同的項目。{0} - - - - '{0}' expression: '{1}'. - '{0}' 運算式: '{1}'。 - Example: "'value' expression: 'new object()'", where 'value' is the parameter name of an assertion method, and 'new object()' is the expression the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}', '{4}' expression: '{5}'. - '{0}' 運算式: '{1}','{2}' 運算式: '{3}','{4}' 運算式: '{5}'。 - Example: "'substring' expression: 'userCode1', 'value' expression: 'userCode2'", where 'substring' and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. - - - '{0}' expression: '{1}', '{2}' expression: '{3}'. - '{0}' 運算式: '{1}','{2}' 運算式: '{3}'。 - Example: "'minValue' expression: 'userCode1', 'maxValue' expression: 'userCode2', 'value' expression: 'userCode3'", where 'minValue', 'maxValue', and 'value' are the parameter names of an assertion method, and 'userCode's are the expressions the user passed to the assert method. + Both collections contain the same elements. + Both collections contain the same elements. + - - {0}. {1} - {0}。{1} + + Expected collection to contain the specified item. + Expected collection to contain the specified item. - - String '{0}' does not contain string '{1}'. {2}. - 字串 '{0}' 未包含字串 '{1}'。{2}。 - + + Expected at least one item to match the predicate. + Expected at least one item to match the predicate. + - - Expected collection to contain the specified item. {0} - 預期集合包含指定的項目。{0} + + Expected collection to contain exactly one item but found {0} item(s). + Expected collection to contain exactly one item but found {0} item(s). - - Expected at least one item to match the predicate. {0} - 必須至少有一個項目符合述詞。{0} + + Expected exactly one item to match the predicate but found {0} item(s). + Expected exactly one item to match the predicate but found {0} item(s). - - Expected collection to contain exactly one element but found {1} element(s). {0} - 預期集合應僅包含一個元素,但發現 {1} 個元素。{0} + + Expected string to contain the specified substring. + Expected string to contain the specified substring. - - Expected exactly one item to match the predicate but found {1} item(s). {0} - 預期只有一個項目符合述詞,但找到 {1} 個項目。{0} + + Expected collection to not contain the specified item. + Expected collection to not contain the specified item. - - String '{0}' does contain string '{1}'. {2}. - 字串 '{0}' 有包含字串 '{1}'。{2}。 + + Expected no items to match the predicate. + Expected no items to match the predicate. - - Expected collection to not contain the specified item. {0} - 預期集合不包含指定的項目。{0} + + Expected string to not contain the specified substring. + Expected string to not contain the specified substring. - - Expected no items to match the predicate. {0} - 預期沒有任何項目符合述詞。{0} + + Expected string to not end with the specified suffix. + Expected string to not end with the specified suffix. - - String '{0}' ends with string '{1}'. {2} - 字串 '{0}' 以字串 '{1}' 結尾。{2} + + Expected string to not match the specified pattern. + Expected string to not match the specified pattern. - - String '{0}' starts with string '{1}'. {2} - 字串 '{0}' 以字串 '{1}' 開頭。{2} + + Expected string to not start with the specified prefix. + Expected string to not start with the specified prefix. @@ -209,27 +168,18 @@ - The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - 集合中的項目數目不符。預期: <{1}>。實際: <{2}>。{0} - + Expected the same number of elements in the collections. + Expected the same number of elements in the collections. + - Element at index {0} do not match. -Expected: {1} -Actual: {2} - 位於索引 {0} 的項目不符。 -預期為: {1} -實際為: {2} + Element at index {0} do not match. + Element at index {0} do not match. - Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} - 位於索引 {1} 的項目不是預期的類型。預期的類型: <{2}>。實際的類型: <{3}>。{0} - - - - String '{0}' does not end with string '{1}'. {2} - 字串 '{0}' 不是以字串 '{1}' 結尾。{2} + Element at index {0} is not of the expected type. + Element at index {0} is not of the expected type. @@ -237,9 +187,14 @@ Actual: {2} {0} 失敗。 {1} - - Expected collection of size {1}. Actual: {2}. {0} - 預期的大小集合 {1}。實際: {2}。{0} + + Expected string to end with the specified suffix. + Expected string to end with the specified suffix. + + + + Expected collection to have {0} item(s) but found {1}. + Expected collection to have {0} item(s) but found {1}. @@ -252,9 +207,29 @@ Actual: {2} 無效的 GitHub 票證 URL - - Value '{0}' is not within the expected range [{1}..{2}]. {3} - 值 '{0}' 不在預期的範圍 [{1}, {2}] 內。{3} + + Expected value to be exactly {0}. + Expected value to be exactly {0}. + + + + Expected condition to be false. + Expected condition to be false. + + + + Expected value {0} to be greater than {1}. + Expected value {0} to be greater than {1}. + + + + Expected value {0} to be greater than or equal to {1}. + Expected value {0} to be greater than or equal to {1}. + + + + Expected value {0} to be in range [{1}, {2}]. + Expected value {0} to be in range [{1}, {2}]. @@ -262,39 +237,69 @@ Actual: {2} 最大值必須大於或等於最小值。 - - {0} Expected type:<{1}>. Actual type:<{2}>. - {0} 預期的類型: <{1}>,實際的類型: <{2}>。 - + + Expected value to be an instance of {0}. + Expected value to be an instance of {0}. + - - String '{0}' does not match pattern '{1}'. {2} - 字串 '{0}' 與模式 '{1}' 不符。{2} + + Expected value {0} to be less than {1}. + Expected value {0} to be less than {1}. - - Expected collection to contain any item but it is empty. {0} - 預期集合包含任何專案,但卻是空的。{0} + + Expected value {0} to be less than or equal to {1}. + Expected value {0} to be less than or equal to {1}. - - Wrong Type:<{1}>. Actual type:<{2}>. {0} - 錯誤的類型: <{1}>。實際的類型: <{2}>。{0} - + + Expected value to be negative. + Expected value to be negative. + - - {0} Expected exact type:<{1}>. Actual type:<{2}>. - {0} 預期的精確類型:<{1}>。實際的類型: <{2}>。 - + + Expected collection to not be empty. + Expected collection to not be empty. + - - Wrong exact Type:<{1}>. Actual type:<{2}>. {0} - 錯誤的精確類型:<{1}>。實際的類型: <{2}>。 {0} - + + Expected value to not be exactly {0}. + Expected value to not be exactly {0}. + + + + Expected value to not be an instance of {0}. + Expected value to not be an instance of {0}. + + + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected value to be positive. + Expected value to be positive. + + + + Expected condition to be true. + Expected condition to be true. + - - String '{0}' matches pattern '{1}'. {2} - 字串 '{0}' 與模式 '{1}' 相符。{2} + + Expected string to match the specified pattern. + Expected string to match the specified pattern. + + + + Expected an exception to be thrown. + Expected an exception to be thrown. @@ -338,11 +343,6 @@ Actual: {2} 集合中不存在元素 <{0}>。 - - String '{0}' does not start with string '{1}'. {2} - 字串 '{0}' 不是以字串 '{1}' 開頭。{2} - - The property {0} has type {1}; expected type {2}. 屬性 {0} 具有類型 {1}; 預期為類型 {2}。 @@ -358,21 +358,16 @@ Actual: {2} (物件) + + Expected string to start with the specified prefix. + Expected string to start with the specified prefix. + + (Failed to get the message for an exception of type {0} due to an exception.) (因為發生例外狀況,所以無法取得類型 {0} 之例外狀況的訊息。) - - Expected exception type:<{1}> but no exception was thrown. {0} - 預期的例外狀況類型:<{1}>,但未擲回任何例外狀況。{0} - - - - Expected exception type:<{1}>. Actual exception type:<{2}>. {0} - 預期的例外狀況類型:<{1}>。實際的例外狀況類型:<{2}>。{0} - - {0} ({1}) {0} ({1}) @@ -398,36 +393,6 @@ Actual: {2} {1} 上的屬性或方法 {0} 傳回空的 IEnumerable<object[]>。 - - Actual value <{2}> is not greater than expected value <{1}>. {0} - 實際值 <{2}> 不大於預期值 <{1}>。{0} - - - - Actual value <{2}> is not greater than or equal to expected value <{1}>. {0} - 實際值 <{2}> 不大於或等於預期值 <{1}>。{0} - - - - Actual value <{2}> is not less than expected value <{1}>. {0} - 實際值 <{2}> 不小於預期值 <{1}>。{0} - - - - Actual value <{2}> is not less than or equal to expected value <{1}>. {0} - 實際值 <{2}> 不小於或等於預期值 <{1}>。{0} - - - - Expected value <{1}> to be positive. {0} - 預期值 <{1}> 為正數。{0} - - - - Expected value <{1}> to be negative. {0} - 預期值 <{1}> 為負數。{0} - - Assert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead. Assert.Equals 不應使用於判斷提示。請改用 Assert.AreEqual 及多載。 @@ -458,6 +423,11 @@ Actual: {2} CollectionAssert.ReferenceEquals 不應使用於判斷提示。請改用 CollectionAssert 方法或 Assert.AreSame 及其多載。 + + Expected the specified exception type to be thrown. + Expected the specified exception type to be thrown. + + \ No newline at end of file diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/OutputTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/OutputTests.cs index 0a2f3d678e..4f260239db 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/OutputTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/OutputTests.cs @@ -17,7 +17,12 @@ public async Task DetailedOutputIsAsExpected(string tfm) TestHostResult testHostResult = await testHost.ExecuteAsync("--output detailed", cancellationToken: TestContext.CancellationToken); // Assert - testHostResult.AssertOutputContains("Assert.AreEqual failed. Expected:<1>. Actual:<2>."); + testHostResult.AssertOutputContains(""" + Assert.AreEqual failed. + Expected values to be equal. + expected: 1 + actual: 2 + """); testHostResult.AssertOutputContains(""" Standard output Console message diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TrxReportTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TrxReportTests.cs index 2943f72d25..87f16e337b 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TrxReportTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/TrxReportTests.cs @@ -33,7 +33,15 @@ public async Task TrxReport_WhenTestFails_ContainsExceptionInfoInOutput(string t // Verify that exception message is present Assert.Contains(@"", trxContent, trxContent); - Assert.Contains("Assert.AreEqual failed. Expected:<1>. Actual:<2>.", trxContent, trxContent); + Assert.Contains( + """ + Assert.AreEqual failed. + Expected values to be equal. + expected: 1 + actual: 2 + """, + trxContent, + trxContent); // Verify that stack trace is present Assert.Contains(@"", trxContent, trxContent); diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs index 1ba1daaad9..103b9fff0f 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreEqualTests.cs @@ -19,7 +19,13 @@ public void AreNotEqualShouldFailWhenNotEqualTypeWithMessage() { Action action = () => Assert.AreNotEqual(1, 1, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(1, 1) + A Message + Expected values to not be equal. + not expected: 1 + actual: 1 + """); } public void AreNotEqualShouldFailWhenNotEqualString() @@ -32,7 +38,13 @@ public void AreNotEqualShouldFailWhenNotEqualStringWithMessage() { Action action = () => Assert.AreNotEqual("A", "A", "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual("A", "A") + A Message + Expected values to not be equal. + not expected: "A" + actual: "A" + """); } [SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Testing the API without the culture")] @@ -52,7 +64,13 @@ public void AreNotEqualShouldFailWhenNotEqualIntWithMessage() { Action action = () => Assert.AreNotEqual(1, 1, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(1, 1) + A Message + Expected values to not be equal. + not expected: 1 + actual: 1 + """); } public void AreNotEqualShouldFailWhenNotEqualLong() @@ -65,7 +83,13 @@ public void AreNotEqualShouldFailWhenNotEqualLongWithMessage() { Action action = () => Assert.AreNotEqual(1L, 1L, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(1L, 1L) + A Message + Expected values to not be equal. + not expected: 1L + actual: 1L + """); } public void AreNotEqualShouldFailWhenNotEqualLongWithDelta() @@ -84,7 +108,13 @@ public void AreNotEqualShouldFailWhenNotEqualDecimalWithMessage() { Action action = () => Assert.AreNotEqual(0.1M, 0.1M, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(0.1M, 0.1M) + A Message + Expected values to not be equal. + not expected: 0.1m + actual: 0.1m + """); } public void AreNotEqualShouldFailWhenNotEqualDecimalWithDelta() @@ -103,7 +133,13 @@ public void AreNotEqualShouldFailWhenNotEqualDoubleWithMessage() { Action action = () => Assert.AreNotEqual(0.1, 0.1, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(0.1, 0.1) + A Message + Expected values to not be equal. + not expected: 0.1 + actual: 0.1 + """); } public void AreNotEqualShouldFailWhenNotEqualDoubleWithDelta() @@ -122,7 +158,13 @@ public void AreNotEqualShouldFailWhenFloatDoubleWithMessage() { Action action = () => Assert.AreNotEqual(100E-2, 100E-2, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreNotEqual(100E-2, 100E-2) + A Message + Expected values to not be equal. + not expected: 1 + actual: 1 + """); } public void AreNotEqualShouldFailWhenNotEqualFloatWithDelta() @@ -141,7 +183,13 @@ public void AreEqualShouldFailWhenNotEqualTypeWithMessage() { Action action = () => Assert.AreEqual(null, "string", "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(null, "string") + A Message + Expected values to be equal. + expected: null + actual: "string" + """); } public void AreEqual_WithTurkishCultureAndIgnoreCase_Throws() @@ -174,7 +222,14 @@ public void AreEqual_WithEnglishCultureAndDoesNotIgnoreCase_Throws() // Won't ignore case. Action action = () => Assert.AreEqual(expected, actual, false, englishCulture); action.Should().Throw() - .WithMessage("Assert.AreEqual failed. Expected:. Case is different for actual value:. 'expected' expression: 'expected', 'actual' expression: 'actual'."); + .WithMessage("""" + Assert.AreEqual(expected, actual, ...) + Case differs. + expected: "i" + actual: "I" + ignore case: False + culture: en-EN + """"); } public void AreEqual_WithTurkishCultureAndDoesNotIgnoreCase_Throws() @@ -191,8 +246,7 @@ public void AreEqual_WithTurkishCultureAndDoesNotIgnoreCase_Throws() public void AreEqualShouldFailWhenNotEqualStringWithMessage() { Action action = () => Assert.AreEqual("A", "a", "A Message"); - action.Should().Throw() - .And.Message.Should().Contain("A Message"); + action.Should().Throw().And.Message.Should().Contain("A Message"); } [SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "Testing the API without the culture")] @@ -212,7 +266,13 @@ public void AreEqualShouldFailWhenNotEqualIntWithMessage() { Action action = () => Assert.AreEqual(1, 2, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(1, 2) + A Message + Expected values to be equal. + expected: 1 + actual: 2 + """); } public void AreEqualShouldFailWhenNotEqualLong() @@ -225,7 +285,13 @@ public void AreEqualShouldFailWhenNotEqualLongWithMessage() { Action action = () => Assert.AreEqual(1L, 2L, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(1L, 2L) + A Message + Expected values to be equal. + expected: 1L + actual: 2L + """); } public void AreEqualShouldFailWhenNotEqualLongWithDelta() @@ -244,7 +310,13 @@ public void AreEqualShouldFailWhenNotEqualDoubleWithMessage() { Action action = () => Assert.AreEqual(0.1, 0.2, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(0.1, 0.2) + A Message + Expected values to be equal. + expected: 0.1 + actual: 0.2 + """); } public void AreEqualShouldFailWhenNotEqualDoubleWithDelta() @@ -264,7 +336,13 @@ public void AreEqualShouldFailWhenNotEqualDecimalWithMessage() { Action action = () => Assert.AreEqual(0.1M, 0.2M, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(0.1M, 0.2M) + A Message + Expected values to be equal. + expected: 0.1m + actual: 0.2m + """); } public void AreEqualShouldFailWhenNotEqualDecimalWithDelta() @@ -283,7 +361,13 @@ public void AreEqualShouldFailWhenFloatDoubleWithMessage() { Action action = () => Assert.AreEqual(100E-2, 200E-2, "A Message"); action.Should().Throw() - .And.Message.Should().Contain("A Message"); + .WithMessage(""" + Assert.AreEqual(100E-2, 200E-2) + A Message + Expected values to be equal. + expected: 1 + actual: 2 + """); } public void AreEqualShouldFailWhenNotEqualFloatWithDelta() @@ -302,7 +386,12 @@ public void AreEqualTwoObjectsDifferentTypeShouldFail() { Action action = () => Assert.AreEqual(new object(), 1); action.Should().Throw() - .And.Message.Should().Contain("Assert.AreEqual failed. Expected:. Actual:<1 (System.Int32)>."); + .WithMessage(""" + Assert.AreEqual(new object(), 1) + Expected values to be equal. + expected: + actual: 1 () + """); } public void AreEqualWithTypeOverridingEqualsShouldWork() @@ -373,7 +462,13 @@ public async Task GenericAreEqual_InterpolatedString_DifferentValues_ShouldFail( DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreEqual(0, 1, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreEqual failed. Expected:<0>. Actual:<1>. 'expected' expression: '0', 'actual' expression: '1'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreEqual(0, 1) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected values to be equal. + expected: 0 + actual: 1 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -390,7 +485,13 @@ public async Task GenericAreNotEqual_InterpolatedString_SameValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotEqual(0, 0, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreNotEqual failed. Expected any value except:<0>. Actual:<0>. 'notExpected' expression: '0', 'actual' expression: '0'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreNotEqual(0, 0) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected values to not be equal. + not expected: 0 + actual: 0 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -407,7 +508,14 @@ public async Task FloatAreEqual_InterpolatedString_DifferentValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreEqual(1.0f, 1.1f, 0.001f, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreEqual failed. Expected a difference no greater than <0.001> between expected value <1> and actual value <1.1>. 'expected' expression: '1.0f', 'actual' expression: '1.1f'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreEqual(1.0f, 1.1f, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be no greater than 0.001. + expected: 1f + actual: 1.1f + delta: 0.001f + """); o.WasToStringCalled.Should().BeTrue(); } @@ -424,7 +532,14 @@ public async Task FloatAreNotEqual_InterpolatedString_SameValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotEqual(1.0f, 1.1f, 0.2f, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreNotEqual failed. Expected a difference greater than <0.2> between expected value <1> and actual value <1.1>. 'notExpected' expression: '1.0f', 'actual' expression: '1.1f'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreNotEqual(1.0f, 1.1f, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be greater than 0.2. + not expected: 1f + actual: 1.1f + delta: 0.2f + """); o.WasToStringCalled.Should().BeTrue(); } @@ -441,7 +556,14 @@ public async Task DecimalAreEqual_InterpolatedString_DifferentValues_ShouldFail( DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreEqual(1.0m, 1.1m, 0.001m, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreEqual failed. Expected a difference no greater than <0.001> between expected value <1.0> and actual value <1.1>. 'expected' expression: '1.0m', 'actual' expression: '1.1m'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreEqual(1.0m, 1.1m, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be no greater than 0.001. + expected: 1.0m + actual: 1.1m + delta: 0.001m + """); o.WasToStringCalled.Should().BeTrue(); } @@ -458,7 +580,14 @@ public async Task DecimalAreNotEqual_InterpolatedString_SameValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotEqual(1.0m, 1.1m, 0.2m, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreNotEqual failed. Expected a difference greater than <0.2> between expected value <1.0> and actual value <1.1>. 'notExpected' expression: '1.0m', 'actual' expression: '1.1m'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreNotEqual(1.0m, 1.1m, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be greater than 0.2. + not expected: 1.0m + actual: 1.1m + delta: 0.2m + """); o.WasToStringCalled.Should().BeTrue(); } @@ -475,7 +604,14 @@ public async Task LongAreEqual_InterpolatedString_DifferentValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreEqual(1L, 2L, 0L, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreEqual failed. Expected a difference no greater than <0> between expected value <1> and actual value <2>. 'expected' expression: '1L', 'actual' expression: '2L'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreEqual(1L, 2L, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be no greater than 0. + expected: 1L + actual: 2L + delta: 0L + """); o.WasToStringCalled.Should().BeTrue(); } @@ -492,7 +628,14 @@ public async Task LongAreNotEqual_InterpolatedString_SameValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotEqual(1L, 2L, 1L, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreNotEqual failed. Expected a difference greater than <1> between expected value <1> and actual value <2>. 'notExpected' expression: '1L', 'actual' expression: '2L'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreNotEqual(1L, 2L, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be greater than 1. + not expected: 1L + actual: 2L + delta: 1L + """); o.WasToStringCalled.Should().BeTrue(); } @@ -509,7 +652,14 @@ public async Task DoubleAreEqual_InterpolatedString_DifferentValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreEqual(1.0d, 1.1d, 0.001d, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreEqual failed. Expected a difference no greater than <0.001> between expected value <1> and actual value <1.1>. 'expected' expression: '1.0d', 'actual' expression: '1.1d'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreEqual(1.0d, 1.1d, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be no greater than 0.001. + expected: 1 + actual: 1.1 + delta: 0.001 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -526,7 +676,14 @@ public async Task DoubleAreNotEqual_InterpolatedString_SameValues_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotEqual(1.0d, 1.1d, 0.2d, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.AreNotEqual failed. Expected a difference greater than <0.2> between expected value <1> and actual value <1.1>. 'notExpected' expression: '1.0d', 'actual' expression: '1.1d'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.AreNotEqual(1.0d, 1.1d, ...) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected difference to be greater than 0.2. + not expected: 1 + actual: 1.1 + delta: 0.2 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -698,13 +855,25 @@ Specified argument was out of the range of valid values. public void FloatAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceGreaterThanDeltaPositive_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(5.0f, 2.0f, 2.0f); // difference is 3. Delta is 2 - action.Should().Throw().WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <5> and actual value <2>. 'expected' expression: '5.0f', 'actual' expression: '2.0f'."); + action.Should().Throw().WithMessage("""" + Assert.AreEqual(5.0f, 2.0f, ...) + Expected difference to be no greater than 2. + expected: 5f + actual: 2f + delta: 2f + """"); } public void FloatAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceGreaterThanDeltaNegative_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(2.0f, 5.0f, 2.0f); // difference is -3. Delta is 2 - action.Should().Throw().WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <2> and actual value <5>. 'expected' expression: '2.0f', 'actual' expression: '5.0f'."); + action.Should().Throw().WithMessage("""" + Assert.AreEqual(2.0f, 5.0f, ...) + Expected difference to be no greater than 2. + expected: 2f + actual: 5f + delta: 2f + """"); } public void FloatAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceLessThanDeltaPositive_DeltaIsNumeric_ShouldPass() @@ -716,13 +885,25 @@ public void FloatAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDif public void FloatAreEqual_ExpectedIsNumeric_ActualIsNaN_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(5.0f, float.NaN, 2.0f); - action.Should().Throw().WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <5> and actual value . 'expected' expression: '5.0f', 'actual' expression: 'float.NaN'."); + action.Should().Throw().WithMessage("""" + Assert.AreEqual(5.0f, float.NaN, ...) + Expected difference to be no greater than 2. + expected: 5f + actual: NaNf + delta: 2f + """"); } public void FloatAreEqual_ExpectedIsNaN_ActualIsNumeric_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(float.NaN, 5.0f, 2.0f); - action.Should().Throw().WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value and actual value <5>. 'expected' expression: 'float.NaN', 'actual' expression: '5.0f'."); + action.Should().Throw().WithMessage("""" + Assert.AreEqual(float.NaN, 5.0f, ...) + Expected difference to be no greater than 2. + expected: NaNf + actual: 5f + delta: 2f + """"); } public void FloatAreEqual_ExpectedIsNaN_ActualIsNaN_DeltaIsNumeric_ShouldPass() @@ -910,13 +1091,25 @@ public void FloatAreNotEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActual public void FloatAreNotEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceLessThanDeltaPositive_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreNotEqual(5.0f, 4.0f, 2.0f); // difference is 1. Delta is 2 - action.Should().Throw().WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value <5> and actual value <4>. 'notExpected' expression: '5.0f', 'actual' expression: '4.0f'."); + action.Should().Throw().WithMessage("""" + Assert.AreNotEqual(5.0f, 4.0f, ...) + Expected difference to be greater than 2. + not expected: 5f + actual: 4f + delta: 2f + """"); } public void FloatAreNotEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceLessThanDeltaNegative_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreNotEqual(4.0f, 5.0f, 2.0f); // difference is -1. Delta is 2 - action.Should().Throw().WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value <4> and actual value <5>. 'notExpected' expression: '4.0f', 'actual' expression: '5.0f'."); + action.Should().Throw().WithMessage("""" + Assert.AreNotEqual(4.0f, 5.0f, ...) + Expected difference to be greater than 2. + not expected: 4f + actual: 5f + delta: 2f + """"); } public void FloatAreNotEqual_ExpectedIsNumeric_ActualIsNaN_DeltaIsNumeric_ShouldPass() => Assert.AreNotEqual(5.0f, float.NaN, 2.0f); @@ -927,7 +1120,13 @@ public void FloatAreNotEqual_ExpectedIsNaN_ActualIsNumeric_DeltaIsNumeric_Should public void FloatAreNotEqual_ExpectedIsNaN_ActualIsNaN_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreNotEqual(float.NaN, float.NaN, 2.0f); - action.Should().Throw().WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value and actual value . 'notExpected' expression: 'float.NaN', 'actual' expression: 'float.NaN'."); + action.Should().Throw().WithMessage("""" + Assert.AreNotEqual(float.NaN, float.NaN, ...) + Expected difference to be greater than 2. + not expected: NaNf + actual: NaNf + delta: 2f + """"); } public void DoubleAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualNotEquals_DeltaIsNaN_ShouldFail() @@ -1111,14 +1310,26 @@ public void DoubleAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDi { Action action = () => Assert.AreEqual(5.0d, 2.0d, 2.0d); // difference is 3. Delta is 2 action.Should().Throw() - .WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <5> and actual value <2>. 'expected' expression: '5.0d', 'actual' expression: '2.0d'."); + .WithMessage("""" + Assert.AreEqual(5.0d, 2.0d, ...) + Expected difference to be no greater than 2. + expected: 5 + actual: 2 + delta: 2 + """"); } public void DoubleAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceGreaterThanDeltaNegative_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(2.0d, 5.0d, 2.0d); // difference is -3. Delta is 2 action.Should().Throw() - .WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <2> and actual value <5>. 'expected' expression: '2.0d', 'actual' expression: '5.0d'."); + .WithMessage("""" + Assert.AreEqual(2.0d, 5.0d, ...) + Expected difference to be no greater than 2. + expected: 2 + actual: 5 + delta: 2 + """"); } public void DoubleAreEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceLessThanDeltaPositive_DeltaIsNumeric_ShouldPass() @@ -1131,14 +1342,26 @@ public void DoubleAreEqual_ExpectedIsNumeric_ActualIsNaN_DeltaIsNumeric_ShouldFa { Action action = () => Assert.AreEqual(5.0d, double.NaN, 2.0d); action.Should().Throw() - .WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value <5> and actual value . 'expected' expression: '5.0d', 'actual' expression: 'double.NaN'."); + .WithMessage("""" + Assert.AreEqual(5.0d, double.NaN, ...) + Expected difference to be no greater than 2. + expected: 5 + actual: NaN + delta: 2 + """"); } public void DoubleAreEqual_ExpectedIsNaN_ActualIsNumeric_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreEqual(double.NaN, 5.0d, 2.0d); action.Should().Throw() - .WithMessage("Assert.AreEqual failed. Expected a difference no greater than <2> between expected value and actual value <5>. 'expected' expression: 'double.NaN', 'actual' expression: '5.0d'."); + .WithMessage("""" + Assert.AreEqual(double.NaN, 5.0d, ...) + Expected difference to be no greater than 2. + expected: NaN + actual: 5 + delta: 2 + """"); } public void DoubleAreEqual_ExpectedIsNaN_ActualIsNaN_DeltaIsNumeric_ShouldPass() @@ -1334,14 +1557,26 @@ public void DoubleAreNotEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActua { Action action = () => Assert.AreNotEqual(5.0d, 4.0d, 2.0d); // difference is 1. Delta is 2 action.Should().Throw() - .WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value <5> and actual value <4>. 'notExpected' expression: '5.0d', 'actual' expression: '4.0d'."); + .WithMessage("""" + Assert.AreNotEqual(5.0d, 4.0d, ...) + Expected difference to be greater than 2. + not expected: 5 + actual: 4 + delta: 2 + """"); } public void DoubleAreNotEqual_ExpectedIsNumeric_ActualIsNumeric_ExpectedAndActualDifferenceLessThanDeltaNegative_DeltaIsNumeric_ShouldFail() { Action action = () => Assert.AreNotEqual(4.0d, 5.0d, 2.0d); // difference is -1. Delta is 2 action.Should().Throw() - .WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value <4> and actual value <5>. 'notExpected' expression: '4.0d', 'actual' expression: '5.0d'."); + .WithMessage("""" + Assert.AreNotEqual(4.0d, 5.0d, ...) + Expected difference to be greater than 2. + not expected: 4 + actual: 5 + delta: 2 + """"); } public void DoubleAreNotEqual_ExpectedIsNumeric_ActualIsNaN_DeltaIsNumeric_ShouldPass() => Assert.AreNotEqual(5.0d, double.NaN, 2.0d); @@ -1353,7 +1588,13 @@ public void DoubleAreNotEqual_ExpectedIsNaN_ActualIsNaN_DeltaIsNumeric_ShouldFai { Action action = () => Assert.AreNotEqual(double.NaN, double.NaN, 2.0d); action.Should().Throw() - .WithMessage("Assert.AreNotEqual failed. Expected a difference greater than <2> between expected value and actual value . 'notExpected' expression: 'double.NaN', 'actual' expression: 'double.NaN'."); + .WithMessage("""" + Assert.AreNotEqual(double.NaN, double.NaN, ...) + Expected difference to be greater than 2. + not expected: NaN + actual: NaN + delta: 2 + """"); } private class TypeOverridesEquals @@ -1412,10 +1653,11 @@ public void AreEqualStringDifferenceAtBeginning() Action action = () => Assert.AreEqual("baaa", "aaaa"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 4 but differ at index 0. 'expected' expression: '"baaa"', 'actual' expression: '"aaaa"'. - Expected: "baaa" - But was: "aaaa" - -----------^ + Assert.AreEqual("baaa", "aaaa") + String lengths are both 4 but differ at index 0. + expected: "baaa" + actual: "aaaa" + -----------^ """); } @@ -1424,10 +1666,11 @@ public void AreEqualStringDifferenceAtEnd() Action action = () => Assert.AreEqual("aaaa", "aaab"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 4 but differ at index 3. 'expected' expression: '"aaaa"', 'actual' expression: '"aaab"'. - Expected: "aaaa" - But was: "aaab" - --------------^ + Assert.AreEqual("aaaa", "aaab") + String lengths are both 4 but differ at index 3. + expected: "aaaa" + actual: "aaab" + --------------^ """); } @@ -1436,10 +1679,11 @@ public void AreEqualStringWithSpecialCharactersShouldEscape() Action action = () => Assert.AreEqual("aa\ta", "aa a"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 4 but differ at index 2. 'expected' expression: '"aa\ta"', 'actual' expression: '"aa a"'. - Expected: "aa␉a" - But was: "aa a" - -------------^ + Assert.AreEqual("aa\ta", "aa a") + String lengths are both 4 but differ at index 2. + expected: "aa␉a" + actual: "aa a" + -------------^ """); } @@ -1451,10 +1695,11 @@ public void AreEqualLongStringsShouldTruncateAndShowContext() Action action = () => Assert.AreEqual(expected, actual); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 201 but differ at index 100. 'expected' expression: 'expected', 'actual' expression: 'actual'. - Expected: "...aaaaaaaaaaaaaaaaaabcccccccccccccccc..." - But was: "...aaaaaaaaaaaaaaaaaadcccccccccccccccc..." - --------------------------------^ + Assert.AreEqual(expected, actual) + String lengths are both 201 but differ at index 100. + expected: "...aaaaaaaaaaaaaaaaaabcccccccccccccccc..." + actual: "...aaaaaaaaaaaaaaaaaadcccccccccccccccc..." + --------------------------------^ """); } @@ -1463,10 +1708,11 @@ public void AreEqualStringWithCultureShouldUseEnhancedMessage() Action action = () => Assert.AreEqual("aaaa", "aaab", false, CultureInfo.InvariantCulture); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 4 but differ at index 3. 'expected' expression: '"aaaa"', 'actual' expression: '"aaab"'. - Expected: "aaaa" - But was: "aaab" - --------------^ + Assert.AreEqual("aaaa", "aaab") + String lengths are both 4 but differ at index 3. + expected: "aaaa" + actual: "aaab" + --------------^ """); } @@ -1475,10 +1721,11 @@ public void AreEqualStringWithDifferentLength() Action action = () => Assert.AreEqual("aaaa", "aaa"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. Expected string length 4 but was 3. 'expected' expression: '"aaaa"', 'actual' expression: '"aaa"'. - Expected: "aaaa" - But was: "aaa" - --------------^ + Assert.AreEqual("aaaa", "aaa") + Expected string length 4 but was 3. + expected: "aaaa" + actual: "aaa" + --------------^ """); } @@ -1487,10 +1734,11 @@ public void AreEqualShorterExpectedString() Action action = () => Assert.AreEqual("aaa", "aaab"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. Expected string length 3 but was 4. 'expected' expression: '"aaa"', 'actual' expression: '"aaab"'. - Expected: "aaa" - But was: "aaab" - --------------^ + Assert.AreEqual("aaa", "aaab") + Expected string length 3 but was 4. + expected: "aaa" + actual: "aaab" + --------------^ """); } @@ -1499,22 +1747,25 @@ public void AreEqualStringWithUserMessage() Action action = () => Assert.AreEqual("aaaa", "aaab", "My custom message"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. String lengths are both 4 but differ at index 3. 'expected' expression: '"aaaa"', 'actual' expression: '"aaab"'. My custom message - Expected: "aaaa" - But was: "aaab" - --------------^ + Assert.AreEqual("aaaa", "aaab") + My custom message + String lengths are both 4 but differ at index 3. + expected: "aaaa" + actual: "aaab" + --------------^ """); } public void AreEqualStringWithEmojis() { - Action action = () => Assert.AreEqual("🥰", "aaab"); + Action action = () => Assert.AreEqual("??", "aaab"); action.Should().Throw() .WithMessage(""" - Assert.AreEqual failed. Expected string length 2 but was 4. 'expected' expression: '"🥰"', 'actual' expression: '"aaab"'. - Expected: "🥰" - But was: "aaab" - -----------^ + Assert.AreEqual("??", "aaab") + Expected string length 2 but was 4. + expected: "??" + actual: "aaab" + -----------^ """); } @@ -1722,4 +1973,94 @@ private void StringPreviewsAreEqual(string expected, string actual) """); } } + + #region Truncation and newline escaping + + public void AreEqual_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 1; + + Action action = () => Assert.AreEqual(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 2); + action.Should().Throw() + .WithMessage(""" + Assert.AreEqual(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 2) + Expected values to be equal. + expected: 1 + actual: 2 + """); + } + + public void AreEqual_WithLongToStringValue_ShouldTruncateValue() + { + var expected = new ObjectWithLongToString(); + var actual = new ObjectWithLongToString(); + + Action action = () => Assert.AreEqual(expected, actual); + action.Should().Throw() + .WithMessage($""" + Assert.AreEqual(expected, actual) + Expected values to be equal. + expected: {new string('L', 256)}... 44 more + actual: {new string('L', 256)}... 44 more + """); + } + + public void AreEqual_WithNewlineInToString_ShouldEscapeNewlines() + { + var expected = new ObjectWithNewlineToString(); + var actual = new ObjectWithNewlineToString(); + + Action action = () => Assert.AreEqual(expected, actual); + action.Should().Throw() + .WithMessage(""" + Assert.AreEqual(expected, actual) + Expected values to be equal. + expected: line1\r\nline2\nline3 + actual: line1\r\nline2\nline3 + """); + } + + public void AreNotEqual_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 1; + + Action action = () => Assert.AreNotEqual(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 1); + action.Should().Throw() + .WithMessage(""" + Assert.AreNotEqual(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 1) + Expected values to not be equal. + not expected: 1 + actual: 1 + """); + } + + public void AreNotEqual_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.AreNotEqual(obj, obj); + action.Should().Throw() + .WithMessage($""" + Assert.AreNotEqual(obj, obj) + Expected values to not be equal. + not expected: {new string('L', 256)}... 44 more + actual: {new string('L', 256)}... 44 more + """); + } + + public void AreNotEqual_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.AreNotEqual(obj, obj); + action.Should().Throw() + .WithMessage(""" + Assert.AreNotEqual(obj, obj) + Expected values to not be equal. + not expected: line1\r\nline2\nline3 + actual: line1\r\nline2\nline3 + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreSame.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreSame.cs index bd97809016..b5c1bb5e2d 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreSame.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.AreSame.cs @@ -16,10 +16,12 @@ public void AreSame_PassSameObject_ShouldPass() public void AreSame_PassDifferentObject_ShouldFail() { Action action = () => Assert.AreSame(new object(), new object()); - action.Should().Throw().WithMessage("Assert.AreSame failed. 'expected' expression: 'new object()', 'actual' expression: 'new object()'."); - } - - public void AreSame_StringMessage_PassSameObject_ShouldPass() + action.Should().Throw().WithMessage(""" + Assert.AreSame(new object(), new object()) + Expected references to be the same. Objects are not equal. + expected: (Hash=*) + actual: (Hash=*) + """); { object o = new(); Assert.AreSame(o, o, "User-provided message"); @@ -28,10 +30,13 @@ public void AreSame_StringMessage_PassSameObject_ShouldPass() public void AreSame_StringMessage_PassDifferentObject_ShouldFail() { Action action = () => Assert.AreSame(new object(), new object(), "User-provided message"); - action.Should().Throw().WithMessage("Assert.AreSame failed. 'expected' expression: 'new object()', 'actual' expression: 'new object()'. User-provided message"); - } - - public void AreSame_InterpolatedString_PassSameObject_ShouldPass() + action.Should().Throw().WithMessage(""" + Assert.AreSame(new object(), new object()) + User-provided message + Expected references to be the same. Objects are not equal. + expected: (Hash=*) + actual: (Hash=*) + """); { DummyClassTrackingToStringCalls o = new(); Assert.AreSame(o, o, $"User-provided message: {o}"); @@ -43,7 +48,13 @@ public async Task AreSame_InterpolatedString_PassDifferentObject_ShouldFail() DummyClassTrackingToStringCalls o = new(); DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreSame(new object(), new object(), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); - (await action.Should().ThrowAsync()).WithMessage($"Assert.AreSame failed. 'expected' expression: 'new object()', 'actual' expression: 'new object()'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + (await action.Should().ThrowAsync()).WithMessage(""" + Assert.AreSame(new object(), new object()) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected references to be the same. Objects are not equal. + expected: (Hash=*) + actual: (Hash=*) + """); o.WasToStringCalled.Should().BeTrue(); } @@ -53,26 +64,48 @@ public void AreNotSame_PassDifferentObject_ShouldPass() public void AreSame_BothAreValueTypes_ShouldFailWithSpecializedMessage() { Action action = () => Assert.AreSame(1, 1); - action.Should().Throw().WithMessage("Assert.AreSame failed. Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). 'expected' expression: '1', 'actual' expression: '1'."); + action.Should().Throw().WithMessage(""" + Assert.AreSame(1, 1) + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). + expected: 1 (Hash=*) + actual: 1 (Hash=*) + """); } public void AreSame_StringMessage_BothAreValueTypes_ShouldFailWithSpecializedMessage() { Action action = () => Assert.AreSame(1, 1, "User-provided message"); - action.Should().Throw().WithMessage("Assert.AreSame failed. Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). 'expected' expression: '1', 'actual' expression: '1'. User-provided message"); + action.Should().Throw().WithMessage(""" + Assert.AreSame(1, 1) + User-provided message + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). + expected: 1 (Hash=*) + actual: 1 (Hash=*) + """); } public void AreSame_InterpolatedString_BothAreValueTypes_ShouldFailWithSpecializedMessage() { Action action = () => Assert.AreSame(1, 1, $"User-provided message {new object().GetType()}"); - action.Should().Throw().WithMessage("Assert.AreSame failed. Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). 'expected' expression: '1', 'actual' expression: '1'. User-provided message System.Object"); + action.Should().Throw().WithMessage(""" + Assert.AreSame(1, 1) + User-provided message System.Object + Do not pass value types to AreSame(). Values converted to Object will never be the same. Consider using AreEqual(). + expected: 1 (Hash=*) + actual: 1 (Hash=*) + """); } public void AreNotSame_PassSameObject_ShouldFail() { object o = new(); Action action = () => Assert.AreNotSame(o, o); - action.Should().Throw().WithMessage("Assert.AreNotSame failed. 'notExpected' expression: 'o', 'actual' expression: 'o'."); + action.Should().Throw().WithMessage(""" + Assert.AreNotSame(o, o) + Expected references to be different. + not expected: (Hash=*) + actual: (Hash=*) + """); } public void AreNotSame_StringMessage_PassDifferentObject_ShouldPass() @@ -82,7 +115,13 @@ public void AreNotSame_StringMessage_PassSameObject_ShouldFail() { object o = new(); Action action = () => Assert.AreNotSame(o, o, "User-provided message"); - action.Should().Throw().WithMessage("Assert.AreNotSame failed. 'notExpected' expression: 'o', 'actual' expression: 'o'. User-provided message"); + action.Should().Throw().WithMessage(""" + Assert.AreNotSame(o, o) + User-provided message + Expected references to be different. + not expected: (Hash=*) + actual: (Hash=*) + """); } public void AreNotSame_InterpolatedString_PassDifferentObject_ShouldPass() @@ -97,7 +136,97 @@ public async Task AreNotSame_InterpolatedString_PassSameObject_ShouldFail() DummyClassTrackingToStringCalls o = new(); DateTime dateTime = DateTime.Now; Func action = async () => Assert.AreNotSame(o, o, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); - (await action.Should().ThrowAsync()).WithMessage($"Assert.AreNotSame failed. 'notExpected' expression: 'o', 'actual' expression: 'o'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + (await action.Should().ThrowAsync()).WithMessage(""" + Assert.AreNotSame(o, o) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected references to be different. + not expected: DummyClassTrackingToStringCalls (Hash=*) + actual: DummyClassTrackingToStringCalls (Hash=*) + """); o.WasToStringCalled.Should().BeTrue(); } + + #region AreSame/AreNotSame truncation and newline escaping + + public void AreSame_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = new object(); + + Action action = () => Assert.AreSame(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, new object()); + action.Should().Throw() + .WithMessage(""" + Assert.AreSame(aVeryLongVariableNameThatExceedsOneHundredCharacte..., new object()) + Expected references to be the same. Objects are not equal. + expected: (Hash=*) + actual: (Hash=*) + """); + } + + public void AreSame_WithLongToStringValue_ShouldTruncateValue() + { + Action action = () => Assert.AreSame(new ObjectWithLongToString(), new ObjectWithLongToString()); + action.Should().Throw() + .WithMessage($""" + Assert.AreSame(new ObjectWithLongToString(), new ObjectWithLongToString()) + Expected references to be the same. Objects are not equal. + expected: {new string('L', 256)}... 44 more (Hash=*) + actual: {new string('L', 256)}... 44 more (Hash=*) + """); + } + + public void AreSame_WithNewlineInToString_ShouldEscapeNewlines() + { + Action action = () => Assert.AreSame(new ObjectWithNewlineToString(), new ObjectWithNewlineToString()); + action.Should().Throw() + .WithMessage(""" + Assert.AreSame(new ObjectWithNewlineToString(), new ObjectWithNewlineToString()) + Expected references to be the same. Objects are not equal. + expected: line1\r\nline2\nline3 (Hash=*) + actual: line1\r\nline2\nline3 (Hash=*) + """); + } + + public void AreNotSame_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = new object(); + + Action action = () => Assert.AreNotSame(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.AreNotSame(aVeryLongVariableNameThatExceedsOneHundredCharacte..., aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected references to be different. + not expected: (Hash=*) + actual: (Hash=*) + """); + } + + public void AreNotSame_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.AreNotSame(obj, obj); + action.Should().Throw() + .WithMessage($""" + Assert.AreNotSame(obj, obj) + Expected references to be different. + not expected: {new string('L', 256)}... 44 more (Hash=*) + actual: {new string('L', 256)}... 44 more (Hash=*) + """); + } + + public void AreNotSame_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.AreNotSame(obj, obj); + action.Should().Throw() + .WithMessage(""" + Assert.AreNotSame(obj, obj) + Expected references to be different. + not expected: line1\r\nline2\nline3 (Hash=*) + actual: line1\r\nline2\nline3 (Hash=*) + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Contains.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Contains.cs index 74d12c523a..ea66b41186 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Contains.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Contains.cs @@ -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 AwesomeAssertions; @@ -338,7 +338,10 @@ public void ContainsSingle_InterpolatedHandler_WithMultipleElements_ThrowsExcept Action action = () => Assert.ContainsSingle(collection, ref handler); // Assert - action.Should().Throw().WithMessage("Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 3 element(s). 'collection' expression: 'collection'. "); + action.Should().Throw().WithMessage(""" + Assert.ContainsSingle(collection) + Expected collection to contain exactly one item but found 3 item(s). + """); } /// @@ -368,7 +371,11 @@ public void ContainsSingle_InNonGenericCollection_NoMessage_WithEmptyCollection_ Action action = () => Assert.ContainsSingle(collection); // Assert - action.Should().Throw().WithMessage("Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 0 element(s). 'collection' expression: 'collection'."); + action.Should().Throw().WithMessage(""" + Assert.ContainsSingle(collection) + Expected collection to contain exactly one item but found 0 item(s). + collection: [] + """); } /// @@ -383,7 +390,12 @@ public void ContainsSingle_InNonGenericCollection_AssertCustomMessage_WithEmptyC Action action = () => Assert.ContainsSingle(collection, "my custom message"); // Assert - action.Should().Throw().WithMessage("Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 0 element(s). 'collection' expression: 'collection'. my custom message"); + action.Should().Throw().WithMessage(""" + Assert.ContainsSingle(collection) + my custom message + Expected collection to contain exactly one item but found 0 item(s). + collection: [] + """); } #endregion @@ -417,7 +429,11 @@ public void Contains_ValueExpected_ItemDoesNotExist_ThrowsException() Action action = () => Assert.Contains(20, collection, "Item 20 not found"); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. Expected collection to contain the specified item. 'expected' expression: '20', 'collection' expression: 'collection'. Item 20 not found"); + action.Should().Throw().WithMessage(""" + Assert.Contains(20, collection) + Item 20 not found + Expected collection to contain the specified item.* + """); } /// @@ -433,7 +449,11 @@ public void Contains_InNonGenericCollection_ValueExpected_ItemDoesNotExist_Throw Action action = () => Assert.Contains(expected, collection, $"Item {expected} not found"); // Assert - action.Should().Throw().WithMessage($"*Item {expected} not found*"); + action.Should().Throw().WithMessage(""" + Assert.Contains(expected, collection) + Item 20 not found + Expected collection to contain the specified item.* + """); } /// @@ -479,7 +499,11 @@ public void Contains_InNonGenericCollection_NullableValueExpected_ItemDoesNotExi Action action = () => Assert.Contains(expected, collection, $"Item {expected} not found"); // Assert - action.Should().Throw().WithMessage($"*Item {expected} not found*"); + action.Should().Throw().WithMessage(""" + Assert.Contains(expected, collection) + Item not found + Expected collection to contain the specified item.* + """); } /// @@ -528,7 +552,11 @@ public void Contains_WithComparer_ItemDoesNotExist_ThrowsException() Action action = () => Assert.Contains("cherry", collection, comparer, "Missing cherry"); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. Expected collection to contain the specified item. 'expected' expression: '\"cherry\"', 'collection' expression: 'collection'. Missing cherry"); + action.Should().Throw().WithMessage(""" + Assert.Contains("cherry", collection) + Missing cherry + Expected collection to contain the specified item.* + """); } /// @@ -574,7 +602,11 @@ public void Contains_Predicate_NoItemMatches_ThrowsException() Action action = () => Assert.Contains(IsEven, collection, "No even number found"); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. Expected at least one item to match the predicate. 'predicate' expression: 'IsEven', 'collection' expression: 'collection'. No even number found"); + action.Should().Throw().WithMessage(""" + Assert.Contains(IsEven, collection) + No even number found + Expected at least one item to match the predicate.* + """); } /// @@ -590,7 +622,11 @@ public void Contains_InNonGenericCollection_Predicate_NoItemMatches_ThrowsExcept Action action = () => Assert.Contains(IsEven, collection, "No even number found"); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. Expected at least one item to match the predicate. 'predicate' expression: 'IsEven', 'collection' expression: 'collection'. No even number found"); + action.Should().Throw().WithMessage(""" + Assert.Contains(IsEven, collection) + No even number found + Expected at least one item to match the predicate.* + """); } /// @@ -623,7 +659,13 @@ public void Contains_StringVersion_SubstringNotPresent_ThrowsException() Action action = () => Assert.Contains(substring, value, StringComparison.Ordinal, "Missing substring"); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. String 'The quick brown fox' does not contain string 'lazy'. 'substring' expression: 'substring', 'value' expression: 'value'. Missing substring."); + action.Should().Throw().WithMessage(""" + Assert.Contains(substring, value) + Missing substring + Expected string to contain the specified substring. + substring: "lazy" + value: "The quick brown fox" + """); } public void Contains_HashSetWithCustomComparer_ItemExists_DoesNotThrow() @@ -649,7 +691,7 @@ public void Contains_InNonGenericCollection_NullCollection_ThrowsException() Action action = () => Assert.Contains(1, collection); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'collection' is invalid. The value cannot be null."); } /// @@ -666,7 +708,7 @@ public void Contains_InNonGenericCollection_WithComparer_NullCollection_ThrowsEx Action action = () => Assert.Contains(1, collection, comparer); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'collection' is invalid. The value cannot be null."); } /// @@ -699,7 +741,10 @@ public void Contains_InNonGenericCollection_WithComparer_ItemDoesNotExist_Throws Action action = () => Assert.Contains("banana", collection, comparer); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. Expected collection to contain the specified item. 'expected' expression: '\"banana\"', 'collection' expression: 'collection'."); + action.Should().Throw().WithMessage(""" + Assert.Contains("banana", collection) + Expected collection to contain the specified item.* + """); } /// @@ -715,7 +760,7 @@ public void Contains_InNonGenericCollection_Predicate_NullCollection_ThrowsExcep Action action = () => Assert.Contains(Predicate, collection); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'collection' is invalid. The value cannot be null."); // Local functions static bool Predicate(object? x) => x is int i && i > 5; @@ -735,7 +780,7 @@ public void Contains_InNonGenericCollection_NullPredicate_ThrowsException() Action action = () => Assert.Contains(predicate, collection); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'predicate' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'predicate' is invalid. The value cannot be null."); } /// @@ -767,7 +812,7 @@ public void Contains_String_NullSubstring_ThrowsException() Action action = () => Assert.Contains(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'substring' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'substring' is invalid. The value cannot be null."); } /// @@ -784,7 +829,7 @@ public void Contains_String_NullValue_ThrowsException() Action action = () => Assert.Contains(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'value' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'value' is invalid. The value cannot be null."); } /// @@ -801,7 +846,7 @@ public void Contains_String_BothNull_ThrowsException() Action action = () => Assert.Contains(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'value' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'value' is invalid. The value cannot be null."); } /// @@ -834,7 +879,12 @@ public void Contains_String_EmptyValue_WithNonEmptySubstring_ThrowsException() Action action = () => Assert.Contains(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. String '' does not contain string 'test'. 'substring' expression: 'substring', 'value' expression: 'value'.."); + action.Should().Throw().WithMessage(""" + Assert.Contains(substring, value) + Expected string to contain the specified substring. + substring: "test" + value: "" + """); } /// @@ -868,7 +918,7 @@ public void Contains_String_WithComparison_NullSubstring_ThrowsException() Action action = () => Assert.Contains(substring, value, StringComparison.OrdinalIgnoreCase); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'substring' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'substring' is invalid. The value cannot be null."); } /// @@ -885,7 +935,7 @@ public void Contains_String_WithComparison_NullValue_ThrowsException() Action action = () => Assert.Contains(substring, value, StringComparison.OrdinalIgnoreCase); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'value' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'value' is invalid. The value cannot be null."); } /// @@ -902,7 +952,7 @@ public void Contains_InNonGenericCollection_WithComparer_NullComparer_ThrowsExce Action action = () => Assert.Contains("apple", collection, comparer); // Assert - action.Should().Throw().WithMessage("Assert.Contains failed. The parameter 'comparer' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.Contains\nThe parameter 'comparer' is invalid. The value cannot be null."); } #endregion @@ -937,7 +987,11 @@ public void DoesNotContain_ValueExpected_ItemPresent_ThrowsException() Action action = () => Assert.DoesNotContain(10, collection, "Item 10 should not be found"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected collection to not contain the specified item. 'notExpected' expression: '10', 'collection' expression: 'collection'. Item 10 should not be found"); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(10, collection) + Item 10 should not be found + Expected collection to not contain the specified item.* + """); } /// @@ -965,10 +1019,15 @@ public void DoesNotContain_InNonGenericCollection_ValueExpected_ItemPresent_Thro var collection = new ArrayList { 5, 10, 15, "a" }; // Act - Action action = () => Assert.DoesNotContain(10, collection, "Assert.DoesNotContain failed. Expected collection to not contain the specified item. Item {0} should not be found"); + Action action = () => Assert.DoesNotContain(10, collection, "Item 10 should not be found"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected collection to not contain the specified item. 'notExpected' expression: '10', 'collection' expression: 'collection'. Assert.DoesNotContain failed. Expected collection to not contain the specified item. Item {0} should not be found"); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(10, collection) + Item 10 should not be found + Expected collection to not contain the specified item. + collection: [5, 10, 15, "a"] + """); } /// @@ -1017,7 +1076,11 @@ public void DoesNotContain_WithComparer_ItemPresent_ThrowsException() Action action = () => Assert.DoesNotContain("APPLE", collection, comparer, "Unexpected \"APPLE\""); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected collection to not contain the specified item. 'notExpected' expression: '\"APPLE\"', 'collection' expression: 'collection'. Unexpected \"APPLE\""); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain("APPLE", collection) + Unexpected "APPLE" + Expected collection to not contain the specified item.* + """); } /// @@ -1034,7 +1097,11 @@ public void DoesNotContain_InNonGenericCollection_WithComparer_ItemPresent_Throw Action action = () => Assert.DoesNotContain("APPLE", collection, comparer, "APPLE"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected collection to not contain the specified item. 'notExpected' expression: '\"APPLE\"', 'collection' expression: 'collection'. APPLE"); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain("APPLE", collection) + APPLE + Expected collection to not contain the specified item.* + """); } /// @@ -1080,7 +1147,11 @@ public void DoesNotContain_Predicate_AtLeastOneItemMatches_ThrowsException() Action action = () => Assert.DoesNotContain(IsEven, collection, "An even number exists"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected no items to match the predicate. 'predicate' expression: 'IsEven', 'collection' expression: 'collection'. An even number exists"); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(IsEven, collection) + An even number exists + Expected no items to match the predicate.* + """); } /// @@ -1096,7 +1167,11 @@ public void DoesNotContain_InNonGenericCollection_Predicate_AtLeastOneItemMatche Action action = () => Assert.DoesNotContain(IsEven, collection, "An even number exists"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. Expected no items to match the predicate. 'predicate' expression: 'IsEven', 'collection' expression: 'collection'. An even number exists"); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(IsEven, collection) + An even number exists + Expected no items to match the predicate.* + """); } /// @@ -1129,7 +1204,13 @@ public void DoesNotContain_StringVersion_SubstringPresent_ThrowsException() Action action = () => Assert.DoesNotContain(substring, value, StringComparison.Ordinal, "Unexpected substring"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. String 'The quick brown fox' does contain string 'brown'. 'substring' expression: 'substring', 'value' expression: 'value'. Unexpected substring."); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(substring, value) + Unexpected substring + Expected string to not contain the specified substring. + substring: "brown" + value: "The quick brown fox" + """); } /// @@ -1164,7 +1245,13 @@ public void DoesNotContain_StringWithComparisonAndMessage_SubstringPresent_Throw Action action = () => Assert.DoesNotContain(substring, value, StringComparison.OrdinalIgnoreCase, "Found unexpected substring"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. String 'The quick brown fox' does contain string 'BROWN'. 'substring' expression: 'substring', 'value' expression: 'value'. Found unexpected substring."); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(substring, value) + Found unexpected substring + Expected string to not contain the specified substring. + substring: "BROWN" + value: "The quick brown fox" + """); } /// @@ -1197,7 +1284,12 @@ public void DoesNotContain_StringSimpleOverload_SubstringPresent_ThrowsException Action action = () => Assert.DoesNotContain(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. String 'The quick brown fox' does contain string 'brown'. 'substring' expression: 'substring', 'value' expression: 'value'.."); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(substring, value) + Expected string to not contain the specified substring. + substring: "brown" + value: "The quick brown fox" + """); } /// @@ -1230,7 +1322,13 @@ public void DoesNotContain_StringWithMessageOnly_SubstringPresent_ThrowsExceptio Action action = () => Assert.DoesNotContain(substring, value, "Found unexpected substring"); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. String 'The quick brown fox' does contain string 'brown'. 'substring' expression: 'substring', 'value' expression: 'value'. Found unexpected substring."); + action.Should().Throw().WithMessage(""" + Assert.DoesNotContain(substring, value) + Found unexpected substring + Expected string to not contain the specified substring. + substring: "brown" + value: "The quick brown fox" + """); } /// @@ -1246,7 +1344,7 @@ public void DoesNotContain_InNonGenericCollection_NullCollection_ThrowsException Action action = () => Assert.DoesNotContain(1, collection); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'collection' is invalid. The value cannot be null."); } /// @@ -1263,7 +1361,7 @@ public void DoesNotContain_InNonGenericCollection_WithComparer_NullCollection_Th Action action = () => Assert.DoesNotContain(1, collection, comparer); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'collection' is invalid. The value cannot be null."); } /// @@ -1280,7 +1378,7 @@ public void DoesNotContain_InNonGenericCollection_WithComparer_NullComparer_Thro Action action = () => Assert.DoesNotContain("cherry", collection, comparer); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'comparer' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'comparer' is invalid. The value cannot be null."); } /// @@ -1296,7 +1394,7 @@ public void DoesNotContain_InNonGenericCollection_Predicate_NullCollection_Throw Action action = () => Assert.DoesNotContain(Predicate, collection); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'collection' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'collection' is invalid. The value cannot be null."); // Local functions static bool Predicate(object? x) => x is int i && i > 5; @@ -1316,7 +1414,7 @@ public void DoesNotContain_InNonGenericCollection_NullPredicate_ThrowsException( Action action = () => Assert.DoesNotContain(predicate, collection); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'predicate' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'predicate' is invalid. The value cannot be null."); } /// @@ -1333,7 +1431,7 @@ public void DoesNotContain_String_NullSubstring_ThrowsException() Action action = () => Assert.DoesNotContain(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'substring' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'substring' is invalid. The value cannot be null."); } /// @@ -1350,7 +1448,7 @@ public void DoesNotContain_String_NullValue_ThrowsException() Action action = () => Assert.DoesNotContain(substring, value); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'value' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'value' is invalid. The value cannot be null."); } /// @@ -1367,7 +1465,7 @@ public void DoesNotContain_String_WithComparison_NullSubstring_ThrowsException() Action action = () => Assert.DoesNotContain(substring, value, StringComparison.OrdinalIgnoreCase); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'substring' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'substring' is invalid. The value cannot be null."); } /// @@ -1384,7 +1482,7 @@ public void DoesNotContain_String_WithComparison_NullValue_ThrowsException() Action action = () => Assert.DoesNotContain(substring, value, StringComparison.OrdinalIgnoreCase); // Assert - action.Should().Throw().WithMessage("Assert.DoesNotContain failed. The parameter 'value' is invalid. The value cannot be null."); + action.Should().Throw().WithMessage("Assert.DoesNotContain\nThe parameter 'value' is invalid. The value cannot be null."); } private static bool IsEven(int x) => x % 2 == 0; @@ -1473,7 +1571,10 @@ public void ContainsSinglePredicate_NoItemMatches_ThrowsException() // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Expected exactly one item to match the predicate but found 0 item(s). + """); } /// @@ -1490,7 +1591,10 @@ public void ContainsSinglePredicate_InNonGenericCollection_NoItemMatches_ThrowsE // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x is int i && i % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x is int i && i % 2 == 0, collection) + Expected exactly one item to match the predicate but found 0 item(s). + """); } /// @@ -1507,7 +1611,10 @@ public void ContainsSinglePredicate_MultipleItemsMatch_ThrowsException() // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 4 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Expected exactly one item to match the predicate but found 4 item(s). + """); } /// @@ -1524,7 +1631,10 @@ public void ContainsSinglePredicate_InNonGenericCollection_MultipleItemsMatch_Th // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 2 item(s). 'predicate' expression: 'x => x is int i && i % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x is int i && i % 2 == 0, collection) + Expected exactly one item to match the predicate but found 2 item(s). + """); } /// @@ -1541,7 +1651,11 @@ public void ContainsSinglePredicate_WithMessage_NoItemMatches_ThrowsException() // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'. No even numbers found in collection with 3 items"); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + No even numbers found in collection with 3 items + Expected exactly one item to match the predicate but found 0 item(s). + """); } /// @@ -1558,7 +1672,11 @@ public void ContainsSinglePredicate_InNonGenericCollection_WithMessage_NoItemMat // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x is int i && i % 2 == 0', 'collection' expression: 'collection'. No even numbers found in collection with 3 items"); + .WithMessage(""" + Assert.ContainsSingle(x => x is int i && i % 2 == 0, collection) + No even numbers found in collection with 3 items + Expected exactly one item to match the predicate but found 0 item(s). + """); } /// @@ -1575,7 +1693,11 @@ public void ContainsSinglePredicate_WithMessage_MultipleItemsMatch_ThrowsExcepti // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 3 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'. Too many even numbers found: 3"); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Too many even numbers found: 3 + Expected exactly one item to match the predicate but found 3 item(s). + """); } /// @@ -1592,7 +1714,11 @@ public void ContainsSinglePredicate_InNonGenericCollection_WithMessage_MultipleI // Assert action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 2 item(s). 'predicate' expression: 'x => x is int i && i % 2 == 0', 'collection' expression: 'collection'. Too many even numbers found: 2"); + .WithMessage(""" + Assert.ContainsSingle(x => x is int i && i % 2 == 0, collection) + Too many even numbers found: 2 + Expected exactly one item to match the predicate but found 2 item(s). + """); } /// @@ -1684,7 +1810,11 @@ public void Contains_ItemNotFound_ShowsSpecificErrorMessage() // Assert action.Should().Throw() - .WithMessage("Assert.Contains failed. Expected collection to contain the specified item. 'expected' expression: '5', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.Contains(5, collection) + Expected collection to contain the specified item.* + collection: [1, 2, 3] + """); } /// @@ -1700,7 +1830,11 @@ public void Contains_InNonGenericCollection_ItemNotFound_ShowsSpecificErrorMessa // Assert action.Should().Throw() - .WithMessage("Assert.Contains failed. Expected collection to contain the specified item. 'expected' expression: '5', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.Contains(5, collection) + Expected collection to contain the specified item.* + collection: [1, 2, 3] + """); } /// @@ -1716,7 +1850,11 @@ public void Contains_PredicateNotMatched_ShowsSpecificErrorMessage() // Assert action.Should().Throw() - .WithMessage("Assert.Contains failed. Expected at least one item to match the predicate. 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.Contains(x => x % 2 == 0, collection) + Expected at least one item to match the predicate.* + collection: [1, 3, 5] + """); } /// @@ -1732,7 +1870,11 @@ public void DoesNotContain_ItemFound_ShowsSpecificErrorMessage() // Assert action.Should().Throw() - .WithMessage("Assert.DoesNotContain failed. Expected collection to not contain the specified item. 'notExpected' expression: '2', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.DoesNotContain(2, collection) + Expected collection to not contain the specified item.* + collection: [1, 2, 3] + """); } /// @@ -1748,7 +1890,11 @@ public void DoesNotContain_PredicateMatched_ShowsSpecificErrorMessage() // Assert action.Should().Throw() - .WithMessage("Assert.DoesNotContain failed. Expected no items to match the predicate. 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.DoesNotContain(x => x % 2 == 0, collection) + Expected no items to match the predicate.* + collection: [1, 2, 3] + """); } public void DoesNotContains_HashSetWithCustomComparer_ItemDoesNotExist_DoesNotThrow() @@ -1792,4 +1938,88 @@ private AlwaysFalseEqualityComparer() } #endregion + + #region Contains/DoesNotContain string truncation and newline escaping + + public void Contains_String_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.Contains("world", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.Contains("world", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to contain the specified substring. + substring: "world" + value: "hello" + """); + } + + public void Contains_String_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('x', 300); + + Action action = () => Assert.Contains("world", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.Contains("world", longValue) + Expected string to contain the specified substring. + substring: "world" + value: "{new string('x', 255)}... 46 more + """); + } + + public void Contains_String_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.Contains("world", "hello\r\nfoo"); + action.Should().Throw() + .WithMessage(""" + Assert.Contains("world", "hello\r\nfoo") + Expected string to contain the specified substring. + substring: "world" + value: "hello\r\nfoo" + """); + } + + public void DoesNotContain_String_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello world"; + + Action action = () => Assert.DoesNotContain("hello", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotContain("hello", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to not contain the specified substring. + substring: "hello" + value: "hello world" + """); + } + + public void DoesNotContain_String_WithLongValue_ShouldTruncateValue() + { + string longValue = "hello" + new string('x', 300); + + Action action = () => Assert.DoesNotContain("hello", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.DoesNotContain("hello", longValue) + Expected string to not contain the specified substring. + substring: "hello" + value: "hello{new string('x', 250)}... 51 more + """); + } + + public void DoesNotContain_String_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.DoesNotContain("hello", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotContain("hello", "hello\r\nworld") + Expected string to not contain the specified substring. + substring: "hello" + value: "hello\r\nworld" + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.EndsWith.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.EndsWith.cs new file mode 100644 index 0000000000..e7d81b55de --- /dev/null +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.EndsWith.cs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using AwesomeAssertions; + +namespace Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests; + +public partial class AssertTests +{ + #region EndsWith + + public void EndsWith_WhenValueEndsWithSuffix_ShouldPass() + => Assert.EndsWith("world", "hello world"); + + public void EndsWith_WhenValueDoesNotEndWithSuffix_ShouldFail() + { + Action action = () => Assert.EndsWith("hello", "world"); + action.Should().Throw() + .WithMessage(""" + Assert.EndsWith("hello", "world") + Expected string to end with the specified suffix. + expected suffix: "hello" + value: "world" + """); + } + + public void EndsWith_WithMessage_WhenValueDoesNotEndWithSuffix_ShouldFail() + { + Action action = () => Assert.EndsWith("hello", "world", "User message"); + action.Should().Throw() + .WithMessage(""" + Assert.EndsWith("hello", "world") + User message + Expected string to end with the specified suffix. + expected suffix: "hello" + value: "world" + """); + } + + public void DoesNotEndWith_WhenValueDoesNotEndWithSuffix_ShouldPass() + => Assert.DoesNotEndWith("hello", "world"); + + public void DoesNotEndWith_WhenValueEndsWithSuffix_ShouldFail() + { + Action action = () => Assert.DoesNotEndWith("world", "hello world"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotEndWith("world", "hello world") + Expected string to not end with the specified suffix. + unwanted suffix: "world" + value: "hello world" + """); + } + + #endregion + + #region EndsWith/DoesNotEndWith truncation and newline escaping + + public void EndsWith_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello world"; + + Action action = () => Assert.EndsWith("hello", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.EndsWith("hello", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to end with the specified suffix. + expected suffix: "hello" + value: "hello world" + """); + } + + public void EndsWith_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('x', 300); + + Action action = () => Assert.EndsWith("world", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.EndsWith("world", longValue) + Expected string to end with the specified suffix. + expected suffix: "world" + value: "{new string('x', 255)}... 46 more + """); + } + + public void EndsWith_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.EndsWith("world", "hello\r\nfoo"); + action.Should().Throw() + .WithMessage(""" + Assert.EndsWith("world", "hello\r\nfoo") + Expected string to end with the specified suffix. + expected suffix: "world" + value: "hello\r\nfoo" + """); + } + + public void DoesNotEndWith_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello world"; + + Action action = () => Assert.DoesNotEndWith("world", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotEndWith("world", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to not end with the specified suffix. + unwanted suffix: "world" + value: "hello world" + """); + } + + public void DoesNotEndWith_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('x', 300) + "world"; + + Action action = () => Assert.DoesNotEndWith("world", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.DoesNotEndWith("world", longValue) + Expected string to not end with the specified suffix. + unwanted suffix: "world" + value: "{new string('x', 255)}... 51 more + """); + } + + public void DoesNotEndWith_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.DoesNotEndWith("world", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotEndWith("world", "hello\r\nworld") + Expected string to not end with the specified suffix. + unwanted suffix: "world" + value: "hello\r\nworld" + """); + } + + #endregion +} diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IComparableTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IComparableTests.cs index a574b23c53..2a61f1c1d2 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IComparableTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IComparableTests.cs @@ -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 AwesomeAssertions; @@ -42,7 +42,13 @@ public void IsGreaterThanShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsGreaterThan failed. Actual value <5> is not greater than expected value <10>. 'lowerBound' expression: '10', 'value' expression: '5'. A Message"); + .WithMessage(""" + Assert.IsGreaterThan(10, 5) + A Message + Expected value 5 to be greater than 10. + lower bound: 10 + value: 5 + """); } public void IsGreaterThanShouldWorkWithDoubles() => @@ -86,7 +92,13 @@ public void IsGreaterThanOrEqualToShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsGreaterThanOrEqualTo failed. Actual value <5> is not greater than or equal to expected value <10>. 'lowerBound' expression: '10', 'value' expression: '5'. A Message"); + .WithMessage(""" + Assert.IsGreaterThanOrEqualTo(10, 5) + A Message + Expected value 5 to be greater than or equal to 10. + lower bound: 10 + value: 5 + """); } public void IsGreaterThanOrEqualToShouldWorkWithDoubles() => @@ -130,7 +142,13 @@ public void IsLessThanShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsLessThan failed. Actual value <10> is not less than expected value <5>. 'upperBound' expression: '5', 'value' expression: '10'. A Message"); + .WithMessage(""" + Assert.IsLessThan(5, 10) + A Message + Expected value 10 to be less than 5. + upper bound: 5 + value: 10 + """); } public void IsLessThanShouldWorkWithDoubles() => @@ -174,7 +192,13 @@ public void IsLessThanOrEqualToShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsLessThanOrEqualTo failed. Actual value <10> is not less than or equal to expected value <5>. 'upperBound' expression: '5', 'value' expression: '10'. A Message"); + .WithMessage(""" + Assert.IsLessThanOrEqualTo(5, 10) + A Message + Expected value 10 to be less than or equal to 5. + upper bound: 5 + value: 10 + """); } public void IsLessThanOrEqualToShouldWorkWithDoubles() => @@ -233,7 +257,12 @@ public void IsPositiveShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsPositive failed. Expected value <-5> to be positive. 'value' expression: '-5'. A Message"); + .WithMessage(""" + Assert.IsPositive(-5) + A Message + Expected value to be positive. + value: -5 + """); } public void IsPositiveShouldWorkWithDoubles() => @@ -298,7 +327,12 @@ public void IsNegativeShouldThrowWithMessage() // Assert action.Should().Throw() - .WithMessage("Assert.IsNegative failed. Expected value <5> to be negative. 'value' expression: '5'. A Message"); + .WithMessage(""" + Assert.IsNegative(5) + A Message + Expected value to be negative. + value: 5 + """); } public void IsNegativeShouldWorkWithDoubles() => @@ -314,4 +348,232 @@ public void IsNegativeShouldThrowForZeroDouble() } #endregion + + #region IComparable truncation and newline escaping + + public void IsGreaterThan_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 10; + + Action action = () => Assert.IsGreaterThan(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 5); + action.Should().Throw() + .WithMessage(""" + Assert.IsGreaterThan(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 5) + Expected value 5 to be greater than 10. + lower bound: 10 + value: 5 + """); + } + + public void IsGreaterThan_WithLongToStringValue_ShouldTruncateValue() + { + var lowerBound = new ComparableWithLongToString(10); + var value = new ComparableWithLongToString(5); + + Action action = () => Assert.IsGreaterThan(lowerBound, value); + action.Should().Throw() + .WithMessage($""" + Assert.IsGreaterThan(lowerBound, value) + Expected value {new string('V', 256)}... 44 more to be greater than {new string('V', 256)}... 44 more. + lower bound: {new string('V', 256)}... 44 more + value: {new string('V', 256)}... 44 more + """); + } + + public void IsGreaterThan_WithNewlineInToString_ShouldEscapeNewlines() + { + var lowerBound = new ComparableWithNewlineToString(10); + var value = new ComparableWithNewlineToString(5); + + Action action = () => Assert.IsGreaterThan(lowerBound, value); + action.Should().Throw() + .WithMessage(""" + Assert.IsGreaterThan(lowerBound, value) + Expected value line1\r\nline2 to be greater than line1\r\nline2. + lower bound: line1\r\nline2 + value: line1\r\nline2 + """); + } + + public void IsGreaterThanOrEqualTo_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 10; + + Action action = () => Assert.IsGreaterThanOrEqualTo(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 5); + action.Should().Throw() + .WithMessage(""" + Assert.IsGreaterThanOrEqualTo(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 5) + Expected value 5 to be greater than or equal to 10. + lower bound: 10 + value: 5 + """); + } + + public void IsGreaterThanOrEqualTo_WithLongToStringValue_ShouldTruncateValue() + { + var lowerBound = new ComparableWithLongToString(10); + var value = new ComparableWithLongToString(5); + + Action action = () => Assert.IsGreaterThanOrEqualTo(lowerBound, value); + action.Should().Throw() + .WithMessage($""" + Assert.IsGreaterThanOrEqualTo(lowerBound, value) + Expected value {new string('V', 256)}... 44 more to be greater than or equal to {new string('V', 256)}... 44 more. + lower bound: {new string('V', 256)}... 44 more + value: {new string('V', 256)}... 44 more + """); + } + + public void IsGreaterThanOrEqualTo_WithNewlineInToString_ShouldEscapeNewlines() + { + var lowerBound = new ComparableWithNewlineToString(10); + var value = new ComparableWithNewlineToString(5); + + Action action = () => Assert.IsGreaterThanOrEqualTo(lowerBound, value); + action.Should().Throw() + .WithMessage(""" + Assert.IsGreaterThanOrEqualTo(lowerBound, value) + Expected value line1\r\nline2 to be greater than or equal to line1\r\nline2. + lower bound: line1\r\nline2 + value: line1\r\nline2 + """); + } + + public void IsLessThan_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 5; + + Action action = () => Assert.IsLessThan(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 10); + action.Should().Throw() + .WithMessage(""" + Assert.IsLessThan(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 10) + Expected value 10 to be less than 5. + upper bound: 5 + value: 10 + """); + } + + public void IsLessThan_WithLongToStringValue_ShouldTruncateValue() + { + var upperBound = new ComparableWithLongToString(5); + var value = new ComparableWithLongToString(10); + + Action action = () => Assert.IsLessThan(upperBound, value); + action.Should().Throw() + .WithMessage($""" + Assert.IsLessThan(upperBound, value) + Expected value {new string('V', 256)}... 44 more to be less than {new string('V', 256)}... 44 more. + upper bound: {new string('V', 256)}... 44 more + value: {new string('V', 256)}... 44 more + """); + } + + public void IsLessThan_WithNewlineInToString_ShouldEscapeNewlines() + { + var upperBound = new ComparableWithNewlineToString(5); + var value = new ComparableWithNewlineToString(10); + + Action action = () => Assert.IsLessThan(upperBound, value); + action.Should().Throw() + .WithMessage(""" + Assert.IsLessThan(upperBound, value) + Expected value line1\r\nline2 to be less than line1\r\nline2. + upper bound: line1\r\nline2 + value: line1\r\nline2 + """); + } + + public void IsLessThanOrEqualTo_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 5; + + Action action = () => Assert.IsLessThanOrEqualTo(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, 10); + action.Should().Throw() + .WithMessage(""" + Assert.IsLessThanOrEqualTo(aVeryLongVariableNameThatExceedsOneHundredCharacte..., 10) + Expected value 10 to be less than or equal to 5. + upper bound: 5 + value: 10 + """); + } + + public void IsLessThanOrEqualTo_WithLongToStringValue_ShouldTruncateValue() + { + var upperBound = new ComparableWithLongToString(5); + var value = new ComparableWithLongToString(10); + + Action action = () => Assert.IsLessThanOrEqualTo(upperBound, value); + action.Should().Throw() + .WithMessage($""" + Assert.IsLessThanOrEqualTo(upperBound, value) + Expected value {new string('V', 256)}... 44 more to be less than or equal to {new string('V', 256)}... 44 more. + upper bound: {new string('V', 256)}... 44 more + value: {new string('V', 256)}... 44 more + """); + } + + public void IsLessThanOrEqualTo_WithNewlineInToString_ShouldEscapeNewlines() + { + var upperBound = new ComparableWithNewlineToString(5); + var value = new ComparableWithNewlineToString(10); + + Action action = () => Assert.IsLessThanOrEqualTo(upperBound, value); + action.Should().Throw() + .WithMessage(""" + Assert.IsLessThanOrEqualTo(upperBound, value) + Expected value line1\r\nline2 to be less than or equal to line1\r\nline2. + upper bound: line1\r\nline2 + value: line1\r\nline2 + """); + } + + public void IsPositive_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = -5; + + Action action = () => Assert.IsPositive(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsPositive(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to be positive. + value: -5 + """); + } + + public void IsNegative_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 5; + + Action action = () => Assert.IsNegative(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsNegative(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to be negative. + value: 5 + """); + } + + #endregion + + private sealed class ComparableWithLongToString : IComparable + { + private readonly int _value; + + public ComparableWithLongToString(int value) => _value = value; + + public int CompareTo(ComparableWithLongToString? other) => _value.CompareTo(other?._value ?? 0); + + public override string ToString() => new string('V', 300); + } + + private sealed class ComparableWithNewlineToString : IComparable + { + private readonly int _value; + + public ComparableWithNewlineToString(int value) => _value = value; + + public int CompareTo(ComparableWithNewlineToString? other) => _value.CompareTo(other?._value ?? 0); + + public override string ToString() => "line1\r\nline2"; + } } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs index d0b8d8fcc7..68819704e1 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.InconclusiveTests.cs @@ -12,6 +12,6 @@ public void InconclusiveDoesNotThrowWhenMessageContainsInvalidStringFormatCompos { Action action = () => Assert.Inconclusive("{"); action.Should().Throw() - .And.Message.Should().Contain("Assert.Inconclusive failed. {"); + .WithMessage("Assert.Inconclusive failed. {"); } } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsExactInstanceOfTypeTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsExactInstanceOfTypeTests.cs index af72c579fa..3823ad00f3 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsExactInstanceOfTypeTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsExactInstanceOfTypeTests.cs @@ -12,21 +12,34 @@ public void ExactInstanceOfTypeShouldFailWhenValueIsNull() { Action action = () => Assert.IsExactInstanceOfType(null, typeof(AssertTests)); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: 'null'."); + .WithMessage(""" +Assert.IsExactInstanceOfType(null) +Expected value to be exactly . + value: null +"""); } public void ExactInstanceOfTypeShouldFailWhenTypeIsNull() { Action action = () => Assert.IsExactInstanceOfType(5, null); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +Expected value to be exactly null. + value: 5 + expected type: null +"""); } public void ExactInstanceOfTypeShouldFailWhenTypeIsMismatched() { Action action = () => Assert.IsExactInstanceOfType(5, typeof(string)); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +Expected value to be exactly . + value: 5 () +"""); } public void ExactInstanceOfTypeShouldPassOnSameInstance() => Assert.IsExactInstanceOfType(5, typeof(int)); @@ -35,7 +48,11 @@ public void ExactInstanceOfTypeShouldFailOnHigherInstance() { Action action = () => Assert.IsExactInstanceOfType(5, typeof(object)); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +Expected value to be exactly . + value: 5 () +"""); } public void ExactInstanceOfTypeShouldFailOnDerivedType() @@ -43,7 +60,11 @@ public void ExactInstanceOfTypeShouldFailOnDerivedType() object x = new MemoryStream(); Action action = () => Assert.IsExactInstanceOfType(x, typeof(Stream)); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: 'x'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(x) +Expected value to be exactly . + value: +"""); } public void ExactInstanceOfTypeShouldPassOnExactType() @@ -56,21 +77,37 @@ public void ExactInstanceOfType_WithStringMessage_ShouldFailWhenValueIsNull() { Action action = () => Assert.IsExactInstanceOfType(null, typeof(AssertTests), "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: 'null'. User-provided message"); + .WithMessage(""" +Assert.IsExactInstanceOfType(null) +User-provided message +Expected value to be exactly . + value: null +"""); } public void ExactInstanceOfType_WithStringMessage_ShouldFailWhenTypeIsNull() { Action action = () => Assert.IsExactInstanceOfType(5, null, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. User-provided message"); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +User-provided message +Expected value to be exactly null. + value: 5 + expected type: null +"""); } public void ExactInstanceOfType_WithStringMessage_ShouldFailWhenTypeIsMismatched() { Action action = () => Assert.IsExactInstanceOfType(5, typeof(string), "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. User-provided message Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +User-provided message +Expected value to be exactly . + value: 5 () +"""); } public void ExactInstanceOfType_WithStringMessage_ShouldPassWhenTypeIsCorrect() @@ -82,7 +119,12 @@ public async Task ExactInstanceOfType_WithInterpolatedString_ShouldFailWhenValue DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsExactInstanceOfType(null, typeof(AssertTests), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsExactInstanceOfType failed. 'value' expression: 'null'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsExactInstanceOfType(null) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected value to be exactly . + value: null + """); o.WasToStringCalled.Should().BeTrue(); } @@ -91,7 +133,13 @@ public void ExactInstanceOfType_WithInterpolatedString_ShouldFailWhenTypeIsNull( DummyClassTrackingToStringCalls o = new(); Action action = () => Assert.IsExactInstanceOfType(5, null, $"User-provided message {o}"); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. User-provided message DummyClassTrackingToStringCalls"); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +User-provided message DummyClassTrackingToStringCalls +Expected value to be exactly null. + value: 5 + expected type: null +"""); o.WasToStringCalled.Should().BeTrue(); } @@ -100,7 +148,12 @@ public void ExactInstanceOfType_WithInterpolatedString_ShouldFailWhenTypeIsMisma DummyClassTrackingToStringCalls o = new(); Action action = () => Assert.IsExactInstanceOfType(5, typeof(string), $"User-provided message {o}"); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. User-provided message DummyClassTrackingToStringCalls Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +User-provided message DummyClassTrackingToStringCalls +Expected value to be exactly . + value: 5 () +"""); o.WasToStringCalled.Should().BeTrue(); } @@ -116,7 +169,13 @@ public void ExactInstanceOfType_WithInterpolatedString_ShouldPassWhenTypeIsCorre public void ExactInstanceNotOfTypeShouldFailWhenTypeIsNull() { Action action = () => Assert.IsNotExactInstanceOfType(5, null); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" +Assert.IsNotExactInstanceOfType(5) +Expected value to not be exactly null. + value: 5 + wrong type: null +"""); } public void ExactInstanceNotOfTypeShouldPassOnWrongInstance() => Assert.IsNotExactInstanceOfType(5L, typeof(int)); @@ -134,21 +193,33 @@ public void ExactInstanceNotOfTypeShouldFailOnExactType() object x = new MemoryStream(); Action action = () => Assert.IsNotExactInstanceOfType(x, typeof(MemoryStream)); action.Should().Throw() - .WithMessage("Assert.IsNotExactInstanceOfType failed. Wrong exact Type:. Actual type:. 'value' expression: 'x'."); + .WithMessage(""" +Assert.IsNotExactInstanceOfType(x) +Expected value to not be exactly . + value: +"""); } public void IsExactInstanceOfTypeUsingGenericType_WhenValueIsNull_Fails() { Action action = () => Assert.IsExactInstanceOfType(null); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: 'null'."); + .WithMessage(""" +Assert.IsExactInstanceOfType(null) +Expected value to be exactly . + value: null +"""); } public void IsExactInstanceOfTypeUsingGenericType_WhenTypeMismatch_Fails() { Action action = () => Assert.IsExactInstanceOfType(5); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +Expected value to be exactly . + value: 5 () +"""); } public void IsExactInstanceOfTypeUsingGenericType_WhenDerivedType_Fails() @@ -156,7 +227,11 @@ public void IsExactInstanceOfTypeUsingGenericType_WhenDerivedType_Fails() object x = new MemoryStream(); Action action = () => Assert.IsExactInstanceOfType(x); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: 'x'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(x) +Expected value to be exactly . + value: +"""); } public void IsExactInstanceOfTypeUsingGenericType_OnSameInstance_DoesNotThrow() => Assert.IsExactInstanceOfType(5); @@ -178,7 +253,11 @@ public void IsExactInstanceOfTypeUsingGenericType_OnHigherInstance_Fails() { Action action = () => Assert.IsExactInstanceOfType(5); action.Should().Throw() - .WithMessage("Assert.IsExactInstanceOfType failed. 'value' expression: '5'. Expected exact type:. Actual type:."); + .WithMessage(""" +Assert.IsExactInstanceOfType(5) +Expected value to be exactly . + value: 5 () +"""); } public void IsExactInstanceOfTypeUsingGenericTypeWithReturn_OnExactType_DoesNotThrow() @@ -205,7 +284,11 @@ public void IsNotExactInstanceOfTypeUsingGenericType_OnExactType_Fails() object x = new MemoryStream(); Action action = () => Assert.IsNotExactInstanceOfType(x); action.Should().Throw() - .WithMessage("Assert.IsNotExactInstanceOfType failed. Wrong exact Type:. Actual type:. 'value' expression: 'x'."); + .WithMessage(""" +Assert.IsNotExactInstanceOfType(x) +Expected value to not be exactly . + value: +"""); } public void IsExactInstanceOfType_WhenNonNullNullableValue_LearnNonNull() @@ -277,4 +360,86 @@ public void IsNotExactInstanceOfType_WhenNonNullNullableTypeAndMessage_LearnNonN Assert.IsNotExactInstanceOfType(new object(), intType, "my message"); _ = intType.ToString(); // no warning about possible null } + + #region IsExactInstanceOfType/IsNotExactInstanceOfType truncation and newline escaping + + public void IsExactInstanceOfType_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.IsExactInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, typeof(int)); + action.Should().Throw() + .WithMessage(""" + Assert.IsExactInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to be exactly . + value: "hello" () + """); + } + + public void IsExactInstanceOfType_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.IsExactInstanceOfType(obj, typeof(int)); + action.Should().Throw() + .WithMessage($""" + Assert.IsExactInstanceOfType(obj) + Expected value to be exactly . + value: {new string('L', 256)}... 44 more () + """); + } + + public void IsExactInstanceOfType_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.IsExactInstanceOfType(obj, typeof(int)); + action.Should().Throw() + .WithMessage(""" + Assert.IsExactInstanceOfType(obj) + Expected value to be exactly . + value: line1\r\nline2\nline3 () + """); + } + + public void IsNotExactInstanceOfType_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.IsNotExactInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, typeof(string)); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotExactInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to not be exactly . + value: "hello" () + """); + } + + public void IsNotExactInstanceOfType_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.IsNotExactInstanceOfType(obj, typeof(ObjectWithLongToString)); + action.Should().Throw() + .WithMessage($""" + Assert.IsNotExactInstanceOfType(obj) + Expected value to not be exactly . + value: {new string('L', 256)}... 44 more () + """); + } + + public void IsNotExactInstanceOfType_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.IsNotExactInstanceOfType(obj, typeof(ObjectWithNewlineToString)); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotExactInstanceOfType(obj) + Expected value to not be exactly . + value: line1\r\nline2\nline3 () + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInRange.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInRange.cs index b9a6646e91..bf5e83a93c 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInRange.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInRange.cs @@ -57,7 +57,12 @@ public void IsInRange_WithValueBelowRange_ThrowsAssertFailedException() // Act & Assert Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().Throw() - .And.Message.Should().Contain("Value '3' is not within the expected range [5..10]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 3 to be in range [5, 10]. + range: [5, 10] + value: 3 + """); } public void IsInRange_WithValueAboveRange_ThrowsAssertFailedException() @@ -70,7 +75,12 @@ public void IsInRange_WithValueAboveRange_ThrowsAssertFailedException() // Act & Assert Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().Throw() - .And.Message.Should().Contain("Value '8' is not within the expected range [1..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 8 to be in range [1, 5]. + range: [1, 5] + value: 8 + """); } public void IsInRange_WithCustomMessage_IncludesCustomMessage() @@ -86,8 +96,13 @@ public void IsInRange_WithCustomMessage_IncludesCustomMessage() // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '10' is not within the expected range [1..5]") - .And.Contain(customMessage); + .WithMessage(""" + Assert.IsInRange(value) + Custom error message + Expected value 10 to be in range [1, 5]. + range: [1, 5] + value: 10 + """); } public void IsInRange_WithDoubleValues_WorksCorrectly() @@ -102,7 +117,12 @@ public void IsInRange_WithDoubleValues_WorksCorrectly() Assert.IsInRange(minValue, maxValue, valueInRange); Action action = () => Assert.IsInRange(minValue, maxValue, valueOutOfRange); action.Should().Throw() - .And.Message.Should().Contain("Value '6' is not within the expected range [1.5..5.5]"); + .WithMessage(""" + Assert.IsInRange(valueOutOfRange) + Expected value 6 to be in range [1.5, 5.5]. + range: [1.5, 5.5] + value: 6 + """); } public void IsInRange_WithDateTimeValues_WorksCorrectly() @@ -119,7 +139,12 @@ public void IsInRange_WithDateTimeValues_WorksCorrectly() // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("is not within the expected range"); + .WithMessage($""" + Assert.IsInRange(valueOutOfRange) + Expected value {valueOutOfRange} to be in range [{minValue}, {maxValue}]. + range: [{minValue}, {maxValue}] + value: {valueOutOfRange} + """); } public void IsInRange_WithCharValues_WorksCorrectly() @@ -136,7 +161,12 @@ public void IsInRange_WithCharValues_WorksCorrectly() // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value 'a' is not within the expected range [A..Z]"); + .WithMessage(""" + Assert.IsInRange(valueOutOfRange) + Expected value a to be in range [A, Z]. + range: [A, Z] + value: a + """); } public void IsInRange_WithNullMessage_DoesNotThrow() @@ -195,7 +225,12 @@ public void IsInRange_WithAllNegativeValuesBelowRange_ThrowsAssertFailedExceptio // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '-12' is not within the expected range [-10..-5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value -12 to be in range [-10, -5]. + range: [-10, -5] + value: -12 + """); } public void IsInRange_WithAllNegativeValuesAboveRange_ThrowsAssertFailedException() @@ -210,7 +245,12 @@ public void IsInRange_WithAllNegativeValuesAboveRange_ThrowsAssertFailedExceptio // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '-3' is not within the expected range [-10..-5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value -3 to be in range [-10, -5]. + range: [-10, -5] + value: -3 + """); } public void IsInRange_WithRangeSpanningNegativeToPositive_ValueInRange_DoesNotThrow() @@ -258,7 +298,12 @@ public void IsInRange_WithRangeSpanningNegativeToPositive_ValueBelowRange_Throws // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '-7' is not within the expected range [-5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value -7 to be in range [-5, 5]. + range: [-5, 5] + value: -7 + """); } public void IsInRange_WithRangeSpanningNegativeToPositive_ValueAboveRange_ThrowsAssertFailedException() @@ -273,7 +318,12 @@ public void IsInRange_WithRangeSpanningNegativeToPositive_ValueAboveRange_Throws // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '7' is not within the expected range [-5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 7 to be in range [-5, 5]. + range: [-5, 5] + value: 7 + """); } public void IsInRange_WithNegativeDoubleValues_WorksCorrectly() @@ -299,7 +349,7 @@ public void IsInRange_WithMaxValueLessThanMinValue_ThrowsArgumentOutOfRangeExcep // Assert action.Should().ThrowExactly() - .And.Message.Should().Contain("The maximum value must be greater than or equal to the minimum value"); + .WithMessage("The maximum value must be greater than or equal to the minimum value. (Parameter 'maxValue')"); } public void IsInRange_WithMaxValueEqualToMinValue_Int_ShouldPassIfValueIsEqual() @@ -322,7 +372,12 @@ public void IsInRange_WithMaxValueEqualToMinValue_Int_ShouldFailIfValueIsSmaller Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '4' is not within the expected range [5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 4 to be in range [5, 5]. + range: [5, 5] + value: 4 + """); } public void IsInRange_WithMaxValueEqualToMinValue_Int_ShouldFailIfValueIsLarger() @@ -334,7 +389,12 @@ public void IsInRange_WithMaxValueEqualToMinValue_Int_ShouldFailIfValueIsLarger( Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '6' is not within the expected range [5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 6 to be in range [5, 5]. + range: [5, 5] + value: 6 + """); } public void IsInRange_WithMaxValueEqualToMinValue_Float_ShouldPassIfValueIsEqual() @@ -357,7 +417,12 @@ public void IsInRange_WithMaxValueEqualToMinValue_Float_ShouldFailIfValueIsSmall Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '4' is not within the expected range [5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 4f to be in range [5f, 5f]. + range: [5f, 5f] + value: 4f + """); } public void IsInRange_WithMaxValueEqualToMinValue_Float_ShouldFailIfValueIsLarger() @@ -369,8 +434,85 @@ public void IsInRange_WithMaxValueEqualToMinValue_Float_ShouldFailIfValueIsLarge Action action = () => Assert.IsInRange(minValue, maxValue, value); action.Should().ThrowExactly() - .And.Message.Should().Contain("Value '6' is not within the expected range [5..5]"); + .WithMessage(""" + Assert.IsInRange(value) + Expected value 6f to be in range [5f, 5f]. + range: [5f, 5f] + value: 6f + """); } #endregion // IsInRange Tests + + #region IsInRange truncation and newline escaping + + public void IsInRange_WithLongExpression_ShouldTruncateExpression() + { + int aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = 20; + + Action action = () => Assert.IsInRange(1, 10, aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsInRange(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value 20 to be in range [1, 10]. + range: [1, 10] + value: 20 + """); + } + + public void IsInRange_WithLongToStringValue_ShouldTruncateValue() + { + var min = new IsInRangeComparableWithLongToString(1); + var max = new IsInRangeComparableWithLongToString(10); + var value = new IsInRangeComparableWithLongToString(20); + + Action action = () => Assert.IsInRange(min, max, value); + action.Should().Throw() + .WithMessage($""" + Assert.IsInRange(value) + Expected value {new string('R', 256)}... 44 more to be in range [{new string('R', 256)}... 44 more, {new string('R', 256)}... 44 more]. + range: [{new string('R', 256)}... 44 more, {new string('R', 256)}... 44 more] + value: {new string('R', 256)}... 44 more + """); + } + + public void IsInRange_WithNewlineInToString_ShouldEscapeNewlines() + { + var min = new IsInRangeComparableWithNewlineToString(1); + var max = new IsInRangeComparableWithNewlineToString(10); + var value = new IsInRangeComparableWithNewlineToString(20); + + Action action = () => Assert.IsInRange(min, max, value); + action.Should().Throw() + .WithMessage(""" + Assert.IsInRange(value) + Expected value line1\r\nline2 to be in range [line1\r\nline2, line1\r\nline2]. + range: [line1\r\nline2, line1\r\nline2] + value: line1\r\nline2 + """); + } + + #endregion + + private readonly struct IsInRangeComparableWithLongToString : IComparable + { + private readonly int _value; + + public IsInRangeComparableWithLongToString(int value) => _value = value; + + public int CompareTo(IsInRangeComparableWithLongToString other) => _value.CompareTo(other._value); + + public override string ToString() => new string('R', 300); + } + + private readonly struct IsInRangeComparableWithNewlineToString : IComparable + { + private readonly int _value; + + public IsInRangeComparableWithNewlineToString(int value) => _value = value; + + public int CompareTo(IsInRangeComparableWithNewlineToString other) => _value.CompareTo(other._value); + + public override string ToString() => "line1\r\nline2"; + } } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInstanceOfTypeTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInstanceOfTypeTests.cs index 6e5e917ed7..7e1307bb15 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInstanceOfTypeTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsInstanceOfTypeTests.cs @@ -12,21 +12,34 @@ public void InstanceOfTypeShouldFailWhenValueIsNull() { Action action = () => Assert.IsInstanceOfType(null, typeof(AssertTests)); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: 'null'."); + .WithMessage(""" + Assert.IsInstanceOfType(null) + Expected value to be an instance of . + value: null + """); } public void InstanceOfTypeShouldFailWhenTypeIsNull() { Action action = () => Assert.IsInstanceOfType(5, null); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'."); + .WithMessage(""" + Assert.IsInstanceOfType(5) + Expected value to be an instance of null. + value: 5 + expected type: null + """); } public void InstanceOfTypeShouldFailWhenTypeIsMismatched() { Action action = () => Assert.IsInstanceOfType(5, typeof(string)); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. Expected type:. Actual type:."); + .WithMessage(""" + Assert.IsInstanceOfType(5) + Expected value to be an instance of . + value: 5 () + """); } public void InstanceOfTypeShouldPassOnSameInstance() => Assert.IsInstanceOfType(5, typeof(int)); @@ -37,21 +50,37 @@ public void InstanceOfType_WithStringMessage_ShouldFailWhenValueIsNull() { Action action = () => Assert.IsInstanceOfType(null, typeof(AssertTests), "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: 'null'. User-provided message"); + .WithMessage(""" + Assert.IsInstanceOfType(null) + User-provided message + Expected value to be an instance of . + value: null + """); } public void InstanceOfType_WithStringMessage_ShouldFailWhenTypeIsNull() { Action action = () => Assert.IsInstanceOfType(5, null, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. User-provided message"); + .WithMessage(""" + Assert.IsInstanceOfType(5) + User-provided message + Expected value to be an instance of null. + value: 5 + expected type: null + """); } public void InstanceOfType_WithStringMessage_ShouldFailWhenTypeIsMismatched() { Action action = () => Assert.IsInstanceOfType(5, typeof(string), "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. User-provided message Expected type:. Actual type:."); + .WithMessage(""" + Assert.IsInstanceOfType(5) + User-provided message + Expected value to be an instance of . + value: 5 () + """); } public void InstanceOfType_WithStringMessage_ShouldPassWhenTypeIsCorrect() @@ -63,7 +92,12 @@ public async Task InstanceOfType_WithInterpolatedString_ShouldFailWhenValueIsNul DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsInstanceOfType(null, typeof(AssertTests), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsInstanceOfType failed. 'value' expression: 'null'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsInstanceOfType(null) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected value to be an instance of . + value: null + """); o.WasToStringCalled.Should().BeTrue(); } @@ -72,7 +106,13 @@ public void InstanceOfType_WithInterpolatedString_ShouldFailWhenTypeIsNull() DummyClassTrackingToStringCalls o = new(); Action action = () => Assert.IsInstanceOfType(5, null, $"User-provided message {o}"); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. User-provided message DummyClassTrackingToStringCalls"); + .WithMessage(""" + Assert.IsInstanceOfType(5) + User-provided message DummyClassTrackingToStringCalls + Expected value to be an instance of null. + value: 5 + expected type: null + """); o.WasToStringCalled.Should().BeTrue(); } @@ -81,7 +121,12 @@ public void InstanceOfType_WithInterpolatedString_ShouldFailWhenTypeIsMismatched DummyClassTrackingToStringCalls o = new(); Action action = () => Assert.IsInstanceOfType(5, typeof(string), $"User-provided message {o}"); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. User-provided message DummyClassTrackingToStringCalls Expected type:. Actual type:."); + .WithMessage(""" + Assert.IsInstanceOfType(5) + User-provided message DummyClassTrackingToStringCalls + Expected value to be an instance of . + value: 5 () + """); o.WasToStringCalled.Should().BeTrue(); } @@ -97,7 +142,13 @@ public void InstanceOfType_WithInterpolatedString_ShouldPassWhenTypeIsCorrect() public void InstanceNotOfTypeShouldFailWhenTypeIsNull() { Action action = () => Assert.IsNotInstanceOfType(5, null); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotInstanceOfType(5) + Expected value to not be an instance of null. + value: 5 + wrong type: null + """); } public void InstanceNotOfTypeShouldPassOnWrongInstance() => Assert.IsNotInstanceOfType(5L, typeof(int)); @@ -108,14 +159,22 @@ public void IsInstanceOfTypeUsingGenericType_WhenValueIsNull_Fails() { Action action = () => Assert.IsInstanceOfType(null); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: 'null'."); + .WithMessage(""" + Assert.IsInstanceOfType(null) + Expected value to be an instance of . + value: null + """); } public void IsInstanceOfTypeUsingGenericType_WhenTypeMismatch_Fails() { Action action = () => Assert.IsInstanceOfType(5); action.Should().Throw() - .WithMessage("Assert.IsInstanceOfType failed. 'value' expression: '5'. Expected type:. Actual type:."); + .WithMessage(""" + Assert.IsInstanceOfType(5) + Expected value to be an instance of . + value: 5 () + """); } public void IsInstanceOfTypeUsingGenericTypeWithOutParameter_WhenValueIsNull_Fails() @@ -148,11 +207,14 @@ public void IsInstanceOfTypeUsingGenericTypeWithOutParameter_OnHigherInstance_Do instance.Should().BeSameAs(testInstance); } - public void IsNotInstanceOfTypeUsingGenericType_WhenValueIsNull_DoesNotThrow() => Assert.IsNotInstanceOfType(null); + public void IsNotInstanceOfTypeUsingGenericType_WhenValueIsNull_DoesNotThrow() + => Assert.IsNotInstanceOfType(null); - public void IsNotInstanceOfType_OnWrongInstanceUsingGenericType_DoesNotThrow() => Assert.IsNotInstanceOfType(5L); + public void IsNotInstanceOfType_OnWrongInstanceUsingGenericType_DoesNotThrow() + => Assert.IsNotInstanceOfType(5L); - public void IsNotInstanceOfTypeUsingGenericType_OnSubInstance_DoesNotThrow() => Assert.IsNotInstanceOfType(new object()); + public void IsNotInstanceOfTypeUsingGenericType_OnSubInstance_DoesNotThrow() + => Assert.IsNotInstanceOfType(new object()); public void IsInstanceOfType_WhenNonNullNullableValue_LearnNonNull() { @@ -229,4 +291,86 @@ public void IsNotInstanceOfType_WhenNonNullNullableTypeAndMessage_LearnNonNull() private Type? GetObjType() => typeof(object); private Type? GetIntType() => typeof(int); + + #region IsInstanceOfType/IsNotInstanceOfType truncation and newline escaping + + public void IsInstanceOfType_WithLongExpression_ShouldTruncateExpression() + { + object aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.IsInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, typeof(int)); + action.Should().Throw() + .WithMessage(""" + Assert.IsInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to be an instance of . + value: "hello" () + """); + } + + public void IsInstanceOfType_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.IsInstanceOfType(obj, typeof(int)); + action.Should().Throw() + .WithMessage($""" + Assert.IsInstanceOfType(obj) + Expected value to be an instance of . + value: {new string('L', 256)}... 44 more () + """); + } + + public void IsInstanceOfType_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.IsInstanceOfType(obj, typeof(int)); + action.Should().Throw() + .WithMessage(""" + Assert.IsInstanceOfType(obj) + Expected value to be an instance of . + value: line1\r\nline2\nline3 () + """); + } + + public void IsNotInstanceOfType_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.IsNotInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ, typeof(string)); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotInstanceOfType(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to not be an instance of . + value: "hello" () + """); + } + + public void IsNotInstanceOfType_WithLongToStringValue_ShouldTruncateValue() + { + var obj = new ObjectWithLongToString(); + + Action action = () => Assert.IsNotInstanceOfType(obj, typeof(ObjectWithLongToString)); + action.Should().Throw() + .WithMessage($""" + Assert.IsNotInstanceOfType(obj) + Expected value to not be an instance of . + value: {new string('L', 256)}... 44 more () + """); + } + + public void IsNotInstanceOfType_WithNewlineInToString_ShouldEscapeNewlines() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.IsNotInstanceOfType(obj, typeof(ObjectWithNewlineToString)); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotInstanceOfType(obj) + Expected value to not be an instance of . + value: line1\r\nline2\nline3 () + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs index bd365d680a..349d7e002a 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs @@ -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 AwesomeAssertions; @@ -16,7 +16,11 @@ public void IsNull_PassNonNull_ShouldFail() { Action action = () => Assert.IsNull(new object()); action.Should().Throw() - .WithMessage("Assert.IsNull failed. 'value' expression: 'new object()'."); + .WithMessage(""" + Assert.IsNull(new object()) + Expected value to be null. + value: + """); } public void IsNull_StringMessage_PassNull_ShouldPass() @@ -26,7 +30,12 @@ public void IsNull_StringMessage_PassNonNull_ShouldFail() { Action action = () => Assert.IsNull(new object(), "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsNull failed. 'value' expression: 'new object()'. User-provided message"); + .WithMessage(""" + Assert.IsNull(new object()) + User-provided message + Expected value to be null. + value: + """); } public void IsNull_InterpolatedString_PassNull_ShouldPass() @@ -42,7 +51,12 @@ public async Task IsNull_InterpolatedString_PassNonNull_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsNull(new object(), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsNull failed. 'value' expression: 'new object()'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsNull(new object()) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected value to be null. + value: + """); o.WasToStringCalled.Should().BeTrue(); } @@ -73,14 +87,21 @@ public void IsNotNull_PassNull_ShouldFail() { Action action = () => Assert.IsNotNull(null); action.Should().Throw() - .WithMessage("Assert.IsNotNull failed. 'value' expression: 'null'."); + .WithMessage(""" + Assert.IsNotNull(null) + Expected value to not be null. + """); } public void IsNotNull_StringMessage_PassNonNull_ShouldFail() { Action action = () => Assert.IsNotNull(null, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsNotNull failed. 'value' expression: 'null'. User-provided message"); + .WithMessage(""" + Assert.IsNotNull(null) + User-provided message + Expected value to not be null. + """); } public async Task IsNotNull_InterpolatedString_PassNonNull_ShouldFail() @@ -89,7 +110,11 @@ public async Task IsNotNull_InterpolatedString_PassNonNull_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsNotNull(null, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsNotNull failed. 'value' expression: 'null'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsNotNull(null) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected value to not be null. + """); o.WasToStringCalled.Should().BeTrue(); } } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs index a09c1416ef..0d74c076e1 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs @@ -12,7 +12,11 @@ public void IsFalseNullableBooleanShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsFalse(nullBool); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'."); + .WithMessage(""" + Assert.IsFalse(nullBool) + Expected condition to be false. + condition: null + """); } public void IsFalseNullableBooleanShouldFailWithTrue() @@ -20,7 +24,11 @@ public void IsFalseNullableBooleanShouldFailWithTrue() bool? nullBool = true; Action action = () => Assert.IsFalse(nullBool); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'."); + .WithMessage(""" + Assert.IsFalse(nullBool) + Expected condition to be false. + condition: True + """); } public void IsFalseNullableBooleanShouldNotFailWithFalse() @@ -33,7 +41,11 @@ public void IsFalseBooleanShouldFailWithTrue() { Action action = () => Assert.IsFalse(true); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'true'."); + .WithMessage(""" + Assert.IsFalse(true) + Expected condition to be false. + condition: True + """); } public void IsFalseBooleanShouldNotFailWithFalse() @@ -44,7 +56,12 @@ public void IsFalseNullableBooleanStringMessageShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsFalse(nullBool, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'. User-provided message"); + .WithMessage(""" + Assert.IsFalse(nullBool) + User-provided message + Expected condition to be false. + condition: null + """); } public void IsFalseNullableBooleanStringMessageShouldFailWithTrue() @@ -52,7 +69,12 @@ public void IsFalseNullableBooleanStringMessageShouldFailWithTrue() bool? nullBool = true; Action action = () => Assert.IsFalse(nullBool, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'. User-provided message"); + .WithMessage(""" + Assert.IsFalse(nullBool) + User-provided message + Expected condition to be false. + condition: True + """); } public void IsFalseNullableBooleanStringMessageShouldNotFailWithFalse() @@ -65,7 +87,12 @@ public void IsFalseBooleanStringMessageShouldFailWithTrue() { Action action = () => Assert.IsFalse(true, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'true'. User-provided message"); + .WithMessage(""" + Assert.IsFalse(true) + User-provided message + Expected condition to be false. + condition: True + """); } public void IsFalseBooleanStringMessageShouldNotFailWithFalse() @@ -78,7 +105,12 @@ public async Task IsFalseNullableBooleanInterpolatedStringMessageShouldFailWithN DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsFalse(nullBool, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsFalse failed. 'condition' expression: 'nullBool'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsFalse(nullBool) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be false. + condition: null + """); } public async Task IsFalseNullableBooleanInterpolatedStringMessageShouldFailWithTrue() @@ -88,7 +120,12 @@ public async Task IsFalseNullableBooleanInterpolatedStringMessageShouldFailWithT DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsFalse(nullBool, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsFalse failed. 'condition' expression: 'nullBool'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsFalse(nullBool) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be false. + condition: True + """); } public void IsFalseNullableBooleanInterpolatedStringMessageShouldNotFailWithFalse() @@ -103,7 +140,12 @@ public async Task IsFalseBooleanInterpolatedStringMessageShouldFailWithTrue() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsFalse(true, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsFalse failed. 'condition' expression: 'true'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsFalse(true) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be false. + condition: True + """); } public void IsFalseBooleanInterpolatedStringMessageShouldNotFailWithFalse() @@ -114,7 +156,11 @@ public void IsTrueNullableBooleanShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsTrue(nullBool); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'."); + .WithMessage(""" + Assert.IsTrue(nullBool) + Expected condition to be true. + condition: null + """); } public void IsTrueNullableBooleanShouldFailWithFalse() @@ -122,7 +168,11 @@ public void IsTrueNullableBooleanShouldFailWithFalse() bool? nullBool = false; Action action = () => Assert.IsTrue(nullBool); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'."); + .WithMessage(""" + Assert.IsTrue(nullBool) + Expected condition to be true. + condition: False + """); } public void IsTrueNullableBooleanShouldNotFailWithTrue() @@ -135,7 +185,11 @@ public void IsTrueBooleanShouldFailWithFalse() { Action action = () => Assert.IsTrue(false); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'false'."); + .WithMessage(""" + Assert.IsTrue(false) + Expected condition to be true. + condition: False + """); } public void IsTrueBooleanShouldNotFailWithTrue() @@ -146,7 +200,12 @@ public void IsTrueNullableBooleanStringMessageShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsTrue(nullBool, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'. User-provided message"); + .WithMessage(""" + Assert.IsTrue(nullBool) + User-provided message + Expected condition to be true. + condition: null + """); } public void IsTrueNullableBooleanStringMessageShouldFailWithFalse() @@ -154,7 +213,12 @@ public void IsTrueNullableBooleanStringMessageShouldFailWithFalse() bool? nullBool = false; Action action = () => Assert.IsTrue(nullBool, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'. User-provided message"); + .WithMessage(""" + Assert.IsTrue(nullBool) + User-provided message + Expected condition to be true. + condition: False + """); } public void IsTrueNullableBooleanStringMessageShouldNotFailWithTrue() @@ -167,7 +231,12 @@ public void IsTrueBooleanStringMessageShouldFailWithFalse() { Action action = () => Assert.IsTrue(false, "User-provided message"); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'false'. User-provided message"); + .WithMessage(""" + Assert.IsTrue(false) + User-provided message + Expected condition to be true. + condition: False + """); } public void IsTrueBooleanStringMessageShouldNotFailWithTrue() @@ -180,7 +249,12 @@ public async Task IsTrueNullableBooleanInterpolatedStringMessageShouldFailWithNu DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsTrue(nullBool, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsTrue failed. 'condition' expression: 'nullBool'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsTrue(nullBool) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be true. + condition: null + """); } public async Task IsTrueNullableBooleanInterpolatedStringMessageShouldFailWithFalse() @@ -190,7 +264,12 @@ public async Task IsTrueNullableBooleanInterpolatedStringMessageShouldFailWithFa DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsTrue(nullBool, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsTrue failed. 'condition' expression: 'nullBool'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsTrue(nullBool) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be true. + condition: False + """); } public void IsTrueNullableBooleanInterpolatedStringMessageShouldNotFailWithTrue() @@ -205,9 +284,44 @@ public async Task IsTrueBooleanInterpolatedStringMessageShouldFailWithFalse() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsTrue(false, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsTrue failed. 'condition' expression: 'false'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsTrue(false) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected condition to be true. + condition: False + """); } public void IsTrueBooleanInterpolatedStringMessageShouldNotFailWithTrue() => Assert.IsTrue(true, $"User-provided message. Input: {true}"); + + #region IsTrue/IsFalse truncation + + public void IsTrue_WithLongExpression_ShouldTruncateExpression() + { + bool aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = false; + + Action action = () => Assert.IsTrue(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsTrue(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected condition to be true. + condition: False + """); + } + + public void IsFalse_WithLongExpression_ShouldTruncateExpression() + { + bool aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = true; + + Action action = () => Assert.IsFalse(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsFalse(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected condition to be false. + condition: True + """); + } + + #endregion } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Items.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Items.cs index 98a5160f29..3ddb12930a 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Items.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.Items.cs @@ -25,7 +25,13 @@ public void Count_WhenCountIsNotSame_ShouldFail() var collection = new List { 1 }; Action action = () => Assert.HasCount(3, collection); action.Should().Throw() - .WithMessage("Assert.HasCount failed. Expected collection of size 3. Actual: 1. 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.HasCount(collection) + Expected collection to have 3 item(s) but found 1. + collection: [1] + expected count: 3 + actual count: 1 + """); } public async Task Count_InterpolatedString_WhenCountIsNotSame_ShouldFail() @@ -34,7 +40,14 @@ public async Task Count_InterpolatedString_WhenCountIsNotSame_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.HasCount(1, Array.Empty(), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.HasCount failed. Expected collection of size 1. Actual: 0. 'collection' expression: 'Array.Empty()'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.HasCount(Array.Empty()) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected collection to have 1 item(s) but found 0. + collection: [] + expected count: 1 + actual count: 0 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -53,7 +66,13 @@ public void NotAny_WhenNotEmpty_ShouldFail() var collection = new List { 1 }; Action action = () => Assert.IsEmpty(collection); action.Should().Throw() - .WithMessage("Assert.IsEmpty failed. Expected collection of size 0. Actual: 1. 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.IsEmpty(collection) + Expected collection to have 0 item(s) but found 1. + collection: [1] + expected count: 0 + actual count: 1 + """); } public async Task NotAny_InterpolatedString_WhenNotEmpty_ShouldFail() @@ -63,7 +82,14 @@ public async Task NotAny_InterpolatedString_WhenNotEmpty_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsEmpty(collection, $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsEmpty failed. Expected collection of size 0. Actual: 1. 'collection' expression: 'collection'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsEmpty(collection) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected collection to have 0 item(s) but found 1. + collection: [1] + expected count: 0 + actual count: 1 + """); o.WasToStringCalled.Should().BeTrue(); } @@ -86,14 +112,22 @@ public void Single_WhenNoItems_ShouldFail() { Action action = () => Assert.ContainsSingle(Array.Empty()); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 0 element(s). 'collection' expression: 'Array.Empty()'."); + .WithMessage(""" + Assert.ContainsSingle(Array.Empty()) + Expected collection to contain exactly one item but found 0 item(s). + collection: [] + """); } public void Single_WhenMultipleItems_ShouldFail() { Action action = () => Assert.ContainsSingle([1, 2, 3]); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 3 element(s). 'collection' expression: '[1, 2, 3]'."); + .WithMessage(""" + Assert.ContainsSingle([1, 2, 3]) + Expected collection to contain exactly one item but found 3 item(s). + collection: [1, 2, 3] + """); } public async Task Single_InterpolatedString_WhenNoItem_ShouldFail() @@ -102,7 +136,12 @@ public async Task Single_InterpolatedString_WhenNoItem_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.ContainsSingle(Array.Empty(), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 0 element(s). 'collection' expression: 'Array.Empty()'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.ContainsSingle(Array.Empty()) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected collection to contain exactly one item but found 0 item(s). + collection: [] + """); o.WasToStringCalled.Should().BeTrue(); } @@ -112,7 +151,12 @@ public async Task Single_InterpolatedString_WhenMultipleItems_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.ContainsSingle([1, 2, 3], $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.ContainsSingle failed. Expected collection to contain exactly one element but found 3 element(s). 'collection' expression: '[1, 2, 3]'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.ContainsSingle([1, 2, 3]) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected collection to contain exactly one item but found 3 item(s). + collection: [1, 2, 3] + """); o.WasToStringCalled.Should().BeTrue(); } @@ -137,7 +181,10 @@ public void SinglePredicate_WhenNoItemMatches_ShouldFail() var collection = new List { 1, 3, 5 }; Action action = () => Assert.ContainsSingle(x => x % 2 == 0, collection); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Expected exactly one item to match the predicate but found 0 item(s). + """); } public void SinglePredicate_WhenMultipleItemsMatch_ShouldFail() @@ -145,7 +192,10 @@ public void SinglePredicate_WhenMultipleItemsMatch_ShouldFail() var collection = new List { 2, 4, 6 }; Action action = () => Assert.ContainsSingle(x => x % 2 == 0, collection); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 3 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'."); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Expected exactly one item to match the predicate but found 3 item(s). + """); } public void SinglePredicate_Message_WhenNoItemMatches_ShouldFail() @@ -153,7 +203,11 @@ public void SinglePredicate_Message_WhenNoItemMatches_ShouldFail() var collection = new List { 1, 3, 5 }; Action action = () => Assert.ContainsSingle(x => x % 2 == 0, collection, "No even numbers found: test"); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 0 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'. No even numbers found: test"); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + No even numbers found: test + Expected exactly one item to match the predicate but found 0 item(s). + """); } public void SinglePredicate_Message_WhenMultipleItemsMatch_ShouldFail() @@ -161,7 +215,11 @@ public void SinglePredicate_Message_WhenMultipleItemsMatch_ShouldFail() var collection = new List { 2, 4, 6 }; Action action = () => Assert.ContainsSingle(x => x % 2 == 0, collection, "Too many even numbers: test"); action.Should().Throw() - .WithMessage("Assert.ContainsSingle failed. Expected exactly one item to match the predicate but found 3 item(s). 'predicate' expression: 'x => x % 2 == 0', 'collection' expression: 'collection'. Too many even numbers: test"); + .WithMessage(""" + Assert.ContainsSingle(x => x % 2 == 0, collection) + Too many even numbers: test + Expected exactly one item to match the predicate but found 3 item(s). + """); } public void Any_WhenOneItem_ShouldPass() @@ -194,7 +252,10 @@ public void Any_WhenNoItem_ShouldFail() { Action action = () => Assert.IsNotEmpty(Array.Empty()); action.Should().Throw() - .WithMessage("Assert.IsNotEmpty failed. Expected collection to contain any item but it is empty. 'collection' expression: 'Array.Empty()'."); + .WithMessage(""" + Assert.IsNotEmpty(Array.Empty()) + Expected collection to not be empty. + """); } public async Task Any_InterpolatedString_WhenNoItem_ShouldFail() @@ -203,7 +264,11 @@ public async Task Any_InterpolatedString_WhenNoItem_ShouldFail() DateTime dateTime = DateTime.Now; Func action = async () => Assert.IsNotEmpty(Array.Empty(), $"User-provided message. {o}, {o,35}, {await GetHelloStringAsync()}, {new DummyIFormattable()}, {dateTime:tt}, {dateTime,5:tt}"); (await action.Should().ThrowAsync()) - .WithMessage($"Assert.IsNotEmpty failed. Expected collection to contain any item but it is empty. 'collection' expression: 'Array.Empty()'. User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)}"); + .WithMessage(""" + Assert.IsNotEmpty(Array.Empty()) + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString()* + Expected collection to not be empty. + """); o.WasToStringCalled.Should().BeTrue(); } } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.MatchesRegex.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.MatchesRegex.cs new file mode 100644 index 0000000000..b516a5f4e6 --- /dev/null +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.MatchesRegex.cs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using AwesomeAssertions; + +namespace Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests; + +public partial class AssertTests +{ + #region MatchesRegex + + public void MatchesRegex_WhenValueMatchesPattern_ShouldPass() + => Assert.MatchesRegex(@"\d+", "abc123"); + + public void MatchesRegex_WhenValueDoesNotMatchPattern_ShouldFail() + { + Action action = () => Assert.MatchesRegex(@"\d+", "abc"); + action.Should().Throw() + .WithMessage(""" + Assert.MatchesRegex(@"\d+", "abc") + Expected string to match the specified pattern. + pattern: \d+ + value: "abc" + """); + } + + public void DoesNotMatchRegex_WhenValueDoesNotMatchPattern_ShouldPass() + => Assert.DoesNotMatchRegex(@"\d+", "abc"); + + public void DoesNotMatchRegex_WhenValueMatchesPattern_ShouldFail() + { + Action action = () => Assert.DoesNotMatchRegex(@"\d+", "abc123"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotMatchRegex(@"\d+", "abc123") + Expected string to not match the specified pattern. + pattern: \d+ + value: "abc123" + """); + } + + #endregion + + #region MatchesRegex/DoesNotMatchRegex truncation and newline escaping + + public void MatchesRegex_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello"; + + Action action = () => Assert.MatchesRegex(@"\d+", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.MatchesRegex(@"\d+", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to match the specified pattern. + pattern: \d+ + value: "hello" + """); + } + + public void MatchesRegex_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('x', 300); + + Action action = () => Assert.MatchesRegex(@"\d+", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.MatchesRegex(@"\d+", longValue) + Expected string to match the specified pattern. + pattern: \d+ + value: "{new string('x', 255)}... 46 more + """); + } + + public void MatchesRegex_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.MatchesRegex(@"^\d+$", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.MatchesRegex(@"^\d+$", "hello\r\nworld") + Expected string to match the specified pattern. + pattern: ^\d+$ + value: "hello\r\nworld" + """); + } + + public void DoesNotMatchRegex_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "abc123"; + + Action action = () => Assert.DoesNotMatchRegex(@"\d+", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotMatchRegex(@"\d+", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to not match the specified pattern. + pattern: \d+ + value: "abc123" + """); + } + + public void DoesNotMatchRegex_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('1', 300); + + Action action = () => Assert.DoesNotMatchRegex(@"\d+", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.DoesNotMatchRegex(@"\d+", longValue) + Expected string to not match the specified pattern. + pattern: \d+ + value: "{new string('1', 255)}... 46 more + """); + } + + public void DoesNotMatchRegex_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.DoesNotMatchRegex(@"hello", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotMatchRegex(@"hello", "hello\r\nworld") + Expected string to not match the specified pattern. + pattern: hello + value: "hello\r\nworld" + """); + } + + #endregion +} diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.StartsWith.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.StartsWith.cs new file mode 100644 index 0000000000..21f59c04bc --- /dev/null +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.StartsWith.cs @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using AwesomeAssertions; + +namespace Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests; + +public partial class AssertTests +{ + #region StartsWith + + public void StartsWith_WhenValueStartsWithPrefix_ShouldPass() + => Assert.StartsWith("hello", "hello world"); + + public void StartsWith_WhenValueDoesNotStartWithPrefix_ShouldFail() + { + Action action = () => Assert.StartsWith("world", "hello"); + action.Should().Throw() + .WithMessage(""" + Assert.StartsWith("world", "hello") + Expected string to start with the specified prefix. + expected prefix: "world" + value: "hello" + """); + } + + public void StartsWith_WithMessage_WhenValueDoesNotStartWithPrefix_ShouldFail() + { + Action action = () => Assert.StartsWith("world", "hello", "User message"); + action.Should().Throw() + .WithMessage(""" + Assert.StartsWith("world", "hello") + User message + Expected string to start with the specified prefix. + expected prefix: "world" + value: "hello" + """); + } + + public void DoesNotStartWith_WhenValueDoesNotStartWithPrefix_ShouldPass() + => Assert.DoesNotStartWith("world", "hello"); + + public void DoesNotStartWith_WhenValueStartsWithPrefix_ShouldFail() + { + Action action = () => Assert.DoesNotStartWith("hello", "hello world"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotStartWith("hello", "hello world") + Expected string to not start with the specified prefix. + unwanted prefix: "hello" + value: "hello world" + """); + } + + #endregion + + #region StartsWith/DoesNotStartWith truncation and newline escaping + + public void StartsWith_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello world"; + + Action action = () => Assert.StartsWith("world", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.StartsWith("world", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to start with the specified prefix. + expected prefix: "world" + value: "hello world" + """); + } + + public void StartsWith_WithLongValue_ShouldTruncateValue() + { + string longValue = new string('x', 300); + + Action action = () => Assert.StartsWith("world", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.StartsWith("world", longValue) + Expected string to start with the specified prefix. + expected prefix: "world" + value: "{new string('x', 255)}... 46 more + """); + } + + public void StartsWith_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.StartsWith("world", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.StartsWith("world", "hello\r\nworld") + Expected string to start with the specified prefix. + expected prefix: "world" + value: "hello\r\nworld" + """); + } + + public void DoesNotStartWith_WithLongExpression_ShouldTruncateExpression() + { + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = "hello world"; + + Action action = () => Assert.DoesNotStartWith("hello", aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotStartWith("hello", aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected string to not start with the specified prefix. + unwanted prefix: "hello" + value: "hello world" + """); + } + + public void DoesNotStartWith_WithLongValue_ShouldTruncateValue() + { + string longValue = "hello" + new string('x', 300); + + Action action = () => Assert.DoesNotStartWith("hello", longValue); + action.Should().Throw() + .WithMessage($""" + Assert.DoesNotStartWith("hello", longValue) + Expected string to not start with the specified prefix. + unwanted prefix: "hello" + value: "hello{new string('x', 250)}... 51 more + """); + } + + public void DoesNotStartWith_WithNewlineInValue_ShouldEscapeNewlines() + { + Action action = () => Assert.DoesNotStartWith("hello", "hello\r\nworld"); + action.Should().Throw() + .WithMessage(""" + Assert.DoesNotStartWith("hello", "hello\r\nworld") + Expected string to not start with the specified prefix. + unwanted prefix: "hello" + value: "hello\r\nworld" + """); + } + + #endregion +} diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.That.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.That.cs index 62297d11df..8950acd89b 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.That.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.That.cs @@ -31,8 +31,9 @@ public void That_BooleanCondition_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => False) failed. - Message: Boolean condition failed + Assert.That(False) + Boolean condition failed + Expected condition to be true. """); } @@ -45,9 +46,9 @@ public void That_NumericComparison_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => x > 10) failed. - Message: x should be greater than 10 - Details: + Assert.That(x > 10) + x should be greater than 10 + Expected 5 to be greater than 10. x = 5 """); } @@ -61,9 +62,9 @@ public void That_StringEquality_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => s == "world") failed. - Message: String equality failed - Details: + Assert.That(s == "world") + String equality failed + Expected "hello" to equal "world". s = "hello" """); } @@ -77,9 +78,9 @@ public void That_NullString_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => s != null) failed. - Message: String should not be null - Details: + Assert.That(s != null) + String should not be null + Expected null to not equal null. s = null """); } @@ -94,9 +95,9 @@ public void That_CombinedBooleanCondition_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => a && b) failed. - Message: Both should be true - Details: + Assert.That(a && b) + Both should be true + Expected condition to be true. a = True b = False """); @@ -111,9 +112,9 @@ public void That_FormatNestedCollections() action.Should().Throw() .WithMessage( """ - Assert.That(() => nested.Any(arr => arr.Length > 3)) failed. - Message: Check nested arrays - Details: + Assert.That(nested.Any(arr => arr.Length > 3)) + Check nested arrays + Expected at least one item to match the predicate. nested = [[1, 2], [3]] """); } @@ -127,9 +128,9 @@ public void That_PropertyComparison_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => person.Age > 30) failed. - Message: Age should be greater than 30 - Details: + Assert.That(person.Age > 30) + Age should be greater than 30 + Expected 25 to be greater than 30. person.Age = 25 """); } @@ -143,9 +144,9 @@ public void That_MethodCall_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => text.StartsWith("world")) failed. - Message: Text should start with 'world' - Details: + Assert.That(text.StartsWith("world")) + Text should start with 'world' + Expected string to start with the specified prefix. text = "hello" """); } @@ -159,9 +160,9 @@ public void That_ChainedPropertyAccess_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => user.Profile.IsActive) failed. - Message: User profile should be active - Details: + Assert.That(user.Profile.IsActive) + User profile should be active + Expected user.Profile.IsActive to be true. user.Profile.IsActive = False """); } @@ -175,9 +176,9 @@ public void That_ArrayIndexAccess_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => numbers[1] == 5) failed. - Message: Second element should be 5 - Details: + Assert.That(numbers[1] == 5) + Second element should be 5 + Expected 2 to equal 5. numbers[1] = 2 """); } @@ -191,9 +192,9 @@ public void That_NullableComparison_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => nullableValue.HasValue) failed. - Message: Nullable should have value - Details: + Assert.That(nullableValue.HasValue) + Nullable should have value + Expected nullableValue.HasValue to be true. nullableValue.HasValue = False """); } @@ -208,9 +209,9 @@ public void That_OrElseCondition_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => condition1 || condition2) failed. - Message: At least one should be true - Details: + Assert.That(condition1 || condition2) + At least one should be true + Expected condition to be true. condition1 = False condition2 = False """); @@ -227,9 +228,9 @@ public void That_ComplexExpression_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => (x + y) * 2 > z * 3) failed. - Message: Complex calculation should be greater - Details: + Assert.That((x + y) * 2 > z * 3) + Complex calculation should be greater + Expected 30 to be greater than 45. x = 5 y = 10 z = 15 @@ -245,9 +246,9 @@ public void That_LinqExpression_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => numbers.All(n => n > 5)) failed. - Message: All numbers should be greater than 5 - Details: + Assert.That(numbers.All(n => n > 5)) + All numbers should be greater than 5 + Expected all elements to match the predicate. numbers = [1, 2, 3, 4] """); } @@ -261,9 +262,9 @@ public void That_TypeComparison_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => obj is int) failed. - Message: Object should be an integer - Details: + Assert.That(obj is int) + Object should be an integer + Expected condition to be true. obj = "hello" """); } @@ -277,9 +278,9 @@ public void That_NotEqualComparison_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => value != "test") failed. - Message: Value should not be 'test' - Details: + Assert.That(value != "test") + Value should not be 'test' + Expected "test" to not equal "test". value = "test" """); } @@ -295,9 +296,9 @@ public void That_MultipleVariablesInComplexExpression_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => current >= min && current <= max) failed. - Message: Value should be within range - Details: + Assert.That(current >= min && current <= max) + Value should be within range + Expected condition to be true. current = 25 max = 20 min = 10 @@ -313,9 +314,9 @@ public void That_DictionaryAccess_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => dict["key1"] > 15) failed. - Message: Dictionary value should be greater than 15 - Details: + Assert.That(dict["key1"] > 15) + Dictionary value should be greater than 15 + Expected 10 to be greater than 15. dict["key1"] = 10 """); } @@ -329,9 +330,9 @@ public void That_NestedMethodCalls_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => text.Substring(6).StartsWith("Universe")) failed. - Message: Substring should start with 'Universe' - Details: + Assert.That(text.Substring(6).StartsWith("Universe")) + Substring should start with 'Universe' + Expected string to start with the specified prefix. text.Substring(6) = "World" """); } @@ -343,9 +344,9 @@ public void That_StaticPropertyAccess_FailsAsExpected() act.Should().Throw() .WithMessage( $""" - Assert.That(() => DateTime.Now.Year < 2000) failed. - Message: Current year should be before 2000 - Details: + Assert.That(DateTime.Now.Year < 2000) + Current year should be before 2000 + Expected {year} to be less than 2000. DateTime.Now.Year = {year} """); } @@ -359,9 +360,9 @@ public void That_GenericMethodCall_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => list.Contains("d")) failed. - Message: List should contain 'd' - Details: + Assert.That(list.Contains("d")) + List should contain 'd' + Expected collection to contain the specified item. list = ["a", "b", "c"] """); } @@ -377,9 +378,9 @@ public void That_ConditionalExpression_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => (flag ? value1 : value2) > 15) failed. - Message: Conditional result should be greater than 15 - Details: + Assert.That((flag ? value1 : value2) > 15) + Conditional result should be greater than 15 + Expected 5 to be greater than 15. flag = True value1 = 5 value2 = 10 @@ -395,9 +396,9 @@ public void That_ArrayLength_FailsAsExpected() act.Should().Throw() .WithMessage( """ - Assert.That(() => numbers.Length > 10) failed. - Message: Array should have more than 10 elements - Details: + Assert.That(numbers.Length > 10) + Array should have more than 10 elements + Expected 5 to be greater than 10. numbers.Length = 5 """); } @@ -411,8 +412,8 @@ public void That_UnaryExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => !Convert.ToBoolean(value)); action.Should().Throw() .WithMessage(""" - Assert.That(() => !Convert.ToBoolean(value)) failed. - Details: + Assert.That(!Convert.ToBoolean(value)) + Expected condition to be true. value = 5 """); } @@ -426,8 +427,8 @@ public void That_UnaryExpression_WithNegation_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => !flag); action.Should().Throw() .WithMessage(""" - Assert.That(() => !flag) failed. - Details: + Assert.That(!flag) + Expected flag to be false. flag = True """); } @@ -442,8 +443,8 @@ public void That_InvocationExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => predicate(testValue)); action.Should().Throw() .WithMessage(""" - Assert.That(() => predicate(testValue)) failed. - Details: + Assert.That(predicate(testValue)) + Expected condition to be true. testValue = 5 """); } @@ -459,8 +460,8 @@ public void That_InvocationExpression_WithComplexArguments_ExtractsVariablesCorr Action action = () => Assert.That(() => complexFunc(text, expectedLength)); action.Should().Throw() .WithMessage(""" - Assert.That(() => complexFunc(text, expectedLength)) failed. - Details: + Assert.That(complexFunc(text, expectedLength)) + Expected condition to be true. expectedLength = 3 text = "hello" """); @@ -477,8 +478,8 @@ public void That_NewExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => new DateTime(year, month, day) == DateTime.MinValue); action.Should().Throw() .WithMessage($""" - Assert.That(() => new DateTime(year, month, day) == DateTime.MinValue) failed. - Details: + Assert.That(new DateTime(year, month, day) == DateTime.MinValue) + Expected {new DateTime(year, month, day).ToString(CultureInfo.CurrentCulture)} to equal {DateTime.MinValue.ToString(CultureInfo.CurrentCulture)}. DateTime.MinValue = {DateTime.MinValue.ToString(CultureInfo.CurrentCulture)} day = 25 month = 12 @@ -497,8 +498,8 @@ public void That_NewExpression_WithComplexArguments_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => new { Name = firstName + " " + lastName }.Name == "Jane Doe"); action.Should().Throw() .WithMessage(""" - Assert.That(() => new { Name = firstName + " " + lastName }.Name == "Jane Doe") failed. - Details: + Assert.That(new { Name = firstName + " " + lastName }.Name == "Jane Doe") + Expected "John Doe" to equal "Jane Doe". firstName = "John" lastName = "Doe" new { Name = ((firstName + " ") + lastName) }.Name = "John Doe" @@ -516,8 +517,8 @@ public void That_ListInitExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => new List { first, second, third }.Count == 5); action.Should().Throw() .WithMessage(""" - Assert.That(() => new List { first, second, third }.Count == 5) failed. - Details: + Assert.That(new List { first, second, third }.Count == 5) + Expected 3 to equal 5. first = 1 new List { first, second, third }.Count = 3 second = 2 @@ -537,8 +538,8 @@ public void That_ListInitExpression_WithComplexElements_ExtractsVariablesCorrect Action action = () => Assert.That(() => new List { new { Name = name1, Age = age1 }, new { Name = name2, Age = age2 } }.Count == 1); action.Should().Throw() .WithMessage(""" - Assert.That(() => new List { new { Name = name1, Age = age1 }, new { Name = name2, Age = age2 } }.Count == 1) failed. - Details: + Assert.That(new List { new { Name = name1, Age = age1 }, new { Name = name2, Age = age2 } }.Count == 1) + Expected 2 to equal 1. age1 = 25 age2 = 30 name1 = "Alice" @@ -558,8 +559,8 @@ public void That_NewArrayExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => new[] { x, y, z }.Length == 5); action.Should().Throw() .WithMessage(""" - Assert.That(() => new[] { x, y, z }.Length == 5) failed. - Details: + Assert.That(new[] { x, y, z }.Length == 5) + Expected 3 to equal 5. new [] {x, y, z}.Length = 3 x = 10 y = 20 @@ -577,8 +578,8 @@ public void That_NewArrayExpression_WithExpressions_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => new[] { baseValue * multiplier, baseValue + multiplier }.Length == 1); action.Should().Throw() .WithMessage(""" - Assert.That(() => new[] { baseValue * multiplier, baseValue + multiplier }.Length == 1) failed. - Details: + Assert.That(new[] { baseValue * multiplier, baseValue + multiplier }.Length == 1) + Expected 2 to equal 1. baseValue = 3 multiplier = 5 new [] {(baseValue * multiplier), (baseValue + multiplier)}.Length = 2 @@ -596,8 +597,8 @@ public void That_IndexExpression_ExtractsVariablesCorrectly() Action action = () => Assert.That(() => dict[key] == expectedValue); action.Should().Throw() .WithMessage(""" - Assert.That(() => dict[key] == expectedValue) failed. - Details: + Assert.That(dict[key] == expectedValue) + Expected 100 to equal 150. dict[key] = 100 expectedValue = 150 key = "key1" @@ -621,8 +622,8 @@ public void That_IndexExpression_WithMultipleIndices_ExtractsVariablesCorrectly( Action action = () => Assert.That(() => matrix[row, col] == expectedValue); action.Should().Throw() .WithMessage(""" - Assert.That(() => matrix[row, col] == expectedValue) failed. - Details: + Assert.That(matrix[row, col] == expectedValue) + Expected 6 to equal 10. col = 2 expectedValue = 10 matrix[row, col] = 6 @@ -641,8 +642,8 @@ public void That_IndexExpression_WithComplexIndexArguments_ExtractsVariablesCorr Action action = () => Assert.That(() => array[start + offset] == 100); action.Should().Throw() .WithMessage(""" - Assert.That(() => array[start + offset] == 100) failed. - Details: + Assert.That(array[start + offset] == 100) + Expected 40 to equal 100. array[start + offset] = 40 offset = 2 start = 1 @@ -658,9 +659,9 @@ public void That_NonGenericCollection_FormatsCorrectly() Action action = () => Assert.That(() => nonGenericCollection.Count == 10, "Collection should have 10 items"); action.Should().Throw() .WithMessage(""" - Assert.That(() => nonGenericCollection.Count == 10) failed. - Message: Collection should have 10 items - Details: + Assert.That(nonGenericCollection.Count == 10) + Collection should have 10 items + Expected 4 to equal 10. nonGenericCollection.Count = 4 """); } @@ -675,9 +676,9 @@ public void That_NonGenericCollectionInComparison_FormatsCorrectly() Action action = () => Assert.That(() => arrayList.Count == expectedItems.Length, "Collections should have same count"); action.Should().Throw() .WithMessage(""" - Assert.That(() => arrayList.Count == expectedItems.Length) failed. - Message: Collections should have same count - Details: + Assert.That(arrayList.Count == expectedItems.Length) + Collections should have same count + Expected 3 to equal 4. arrayList.Count = 3 expectedItems.Length = 4 """); @@ -692,8 +693,8 @@ public void That_ArrayIndexWithParameterExpression_ExtractsArrayVariable() Action action = () => Assert.That(() => arrayParam[arrayParam.Length - 2] == 999); action.Should().Throw() .WithMessage(""" - Assert.That(() => arrayParam[arrayParam.Length - 2] == 999) failed. - Details: + Assert.That(arrayParam[arrayParam.Length - 2] == 999) + Expected 20 to equal 999. arrayParam.Length = 3 arrayParam[arrayParam.Length - 2] = 20 """); @@ -709,8 +710,8 @@ public void That_WithCapturedVariableConstants_IncludesInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => captured == "wrong_value" && capturedNumber > 50) failed. - Details: + Assert.That(captured == "wrong_value" && capturedNumber > 50) + Expected condition to be true. captured = "captured_value" capturedNumber = 42 """); @@ -725,9 +726,9 @@ public void That_WithStringLiteralsAndCustomMessage_SkipsLiteralInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => testVar == "expected") failed. - Message: Values should match - Details: + Assert.That(testVar == "expected") + Values should match + Expected "actual" to equal "expected". testVar = "actual" """); } @@ -744,8 +745,8 @@ public void That_WithNumericLiterals_SkipsLiteralInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => value == 10 && doubleValue == 2.71 && floatValue == 1.5f && decimalValue == 200.75m) failed. - Details: + Assert.That(value == 10 && doubleValue == 2.71 && floatValue == 1.5f && decimalValue == 200.75m) + Expected condition to be true. decimalValue = 100.50 doubleValue = 3.14 floatValue = 2.5 @@ -763,8 +764,8 @@ public void That_WithBooleanLiterals_SkipsLiteralInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => condition == True) failed. - Details: + Assert.That(condition == True) + Expected False to equal True. condition = False """); } @@ -778,8 +779,8 @@ public void That_WithCharacterLiterals_SkipsLiteralInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => letter == 'b') failed. - Details: + Assert.That(letter == 'b') + Expected a to equal b. letter = a """); } @@ -793,8 +794,8 @@ public void That_WithNullLiterals_SkipsLiteralInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => nullableString == null) failed. - Details: + Assert.That(nullableString == null) + Expected "not null" to equal null. nullableString = "not null" """); } @@ -809,8 +810,8 @@ public void That_WithFuncDelegate_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => predicate(value)) failed. - Details: + Assert.That(predicate(value)) + Expected condition to be true. value = -1 """); } @@ -825,8 +826,8 @@ public void That_WithActionDelegate_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => shouldExecute && action != null) failed. - Details: + Assert.That(shouldExecute && action != null) + Expected condition to be true. shouldExecute = False """); } @@ -842,8 +843,8 @@ public void That_WithGenericFuncDelegate_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => complexFunc(text, threshold)) failed. - Details: + Assert.That(complexFunc(text, threshold)) + Expected condition to be true. text = "hi" threshold = 5 """); @@ -861,8 +862,8 @@ public void That_WithComplexConstantExpression_HandlesCorrectly() act.Should().Throw() .WithMessage(""" - Assert.That(() => dynamicValue.Length == ConstValue && flag == True) failed. - Details: + Assert.That(dynamicValue.Length == ConstValue && flag == True) + Expected condition to be true. dynamicValue.Length = 7 flag = False """); @@ -878,8 +879,8 @@ public void That_WithEmptyStringConstant_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => value == "") failed. - Details: + Assert.That(value == "") + Expected "non-empty" to equal "". value = "non-empty" """); } @@ -893,8 +894,8 @@ public void That_WithNegativeNumericLiterals_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => positiveValue == -10) failed. - Details: + Assert.That(positiveValue == -10) + Expected 5 to equal -10. positiveValue = 5 """); } @@ -908,8 +909,8 @@ public void That_WithFloatAndDoubleNotation_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => value == 2.5d && value != 3.14f) failed. - Details: + Assert.That(value == 2.5d && value != 3.14f) + Expected condition to be true. value = 1 """); } @@ -925,8 +926,8 @@ public void That_WithCapturedVariableNamesContainingKeywords_HandlesCorrectly() act.Should().Throw() .WithMessage(""" - Assert.That(() => @null == null && @true == "true" && @false == 0) failed. - Details: + Assert.That(@null == null && @true == "true" && @false == 0) + Expected condition to be true. false = 1 null = System.Object true = "false" @@ -944,8 +945,8 @@ public void That_WithConstExpressionInIndexAccess_FormatsCorrectly() act.Should().Throw() .WithMessage(""" - Assert.That(() => array[Index] == 5 && array[dynamicIndex] == 10) failed. - Details: + Assert.That(array[Index] == 5 && array[dynamicIndex] == 10) + Expected condition to be true. array[0] = 1 array[dynamicIndex] = 2 dynamicIndex = 1 @@ -962,8 +963,8 @@ public void That_WithMultipleStringLiterals_OnlyIncludesVariables() act.Should().Throw() .WithMessage(""" - Assert.That(() => firstName == "Jane" && lastName == "Smith") failed. - Details: + Assert.That(firstName == "Jane" && lastName == "Smith") + Expected condition to be true. firstName = "John" lastName = "Doe" """); @@ -982,8 +983,8 @@ public void That_WithMixedLiteralsAndVariables_FiltersCorrectly() act.Should().Throw() .WithMessage(""" - Assert.That(() => name == "Admin" && age == 30 && isActive == False && grade == 'A') failed. - Details: + Assert.That(name == "Admin" && age == 30 && isActive == False && grade == 'A') + Expected condition to be true. age = 25 grade = B isActive = True @@ -1001,9 +1002,9 @@ public void That_WithCustomMessageAndLiterals_SkipsLiteralsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => count > 5 && status == "completed") failed. - Message: Operation should be ready - Details: + Assert.That(count > 5 && status == "completed") + Operation should be ready + Expected condition to be true. count = 3 status = "pending" """); @@ -1019,8 +1020,8 @@ public void That_WithCapturedDecimalLiteral_SkipsInDetails() act.Should().Throw() .WithMessage(""" - Assert.That(() => price + tax == 25.00m) failed. - Details: + Assert.That(price + tax == 25.00m) + Expected 22.49 to equal 25.00. price = 19.99 tax = 2.50 """); @@ -1036,8 +1037,8 @@ public void That_WithNullConstantAndVariable_OnlyIncludesVariable() act.Should().Throw() .WithMessage(""" - Assert.That(() => nullVariable != null && nonNullVariable == null) failed. - Details: + Assert.That(nullVariable != null && nonNullVariable == null) + Expected condition to be true. nonNullVariable = "value" nullVariable = null """); diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ThrowsExceptionTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ThrowsExceptionTests.cs index c41eba3302..731a0cdfbd 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ThrowsExceptionTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ThrowsExceptionTests.cs @@ -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 AwesomeAssertions; @@ -13,7 +13,7 @@ public void ThrowAssertFailedDoesNotThrowIfMessageContainsInvalidStringFormatCom { Action action = () => Assert.ThrowAssertFailed("name", "{"); action.Should().Throw() - .WithMessage("*name failed. {*"); + .WithMessage("name\n{"); } #endregion @@ -70,7 +70,13 @@ public void ThrowsAsync_WhenExceptionIsNotExpectedType_ShouldThrow() Action action = t.Wait; action.Should().Throw() .WithInnerException() - .WithMessage("Assert.ThrowsAsync failed. Expected exception type:. Actual exception type:. 'action' expression: '() => throw new Exception()'."); + .WithMessage(""" + Assert.ThrowsAsync + Expected the specified exception type to be thrown. + action: () => throw new Exception() + expected exception type: + actual exception type: + """); } public void ThrowsExactlyAsync_WhenExceptionIsDerivedFromExpectedType_ShouldThrow() @@ -79,7 +85,13 @@ public void ThrowsExactlyAsync_WhenExceptionIsDerivedFromExpectedType_ShouldThro Action action = t.Wait; action.Should().Throw() .WithInnerException() - .WithMessage("Assert.ThrowsExactlyAsync failed. Expected exception type:. Actual exception type:. 'action' expression: '() => throw new ArgumentNullException()'."); + .WithMessage(""" + Assert.ThrowsExactlyAsync + Expected the specified exception type to be thrown. + action: () => throw new ArgumentNullException() + expected exception type: + actual exception type: + """); } public void Throws_WithMessageBuilder_Passes() @@ -105,7 +117,13 @@ public void Throws_WithMessageBuilder_FailsBecauseNoException() return "message constructed via builder."; }); action.Should().Throw() - .WithMessage("Assert.Throws failed. Expected exception type: but no exception was thrown. 'action' expression: '() => { }'. message constructed via builder."); + .WithMessage(""" + Assert.Throws + message constructed via builder. + Expected an exception to be thrown. + action: () => { } + expected exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeNull(); @@ -122,7 +140,14 @@ public void Throws_WithMessageBuilder_FailsBecauseTypeMismatch() return "message constructed via builder."; }); action.Should().Throw() - .WithMessage("Assert.Throws failed. Expected exception type:. Actual exception type:. 'action' expression: '() => throw new ArgumentOutOfRangeException(\"MyParamNameHere\")'. message constructed via builder."); + .WithMessage(""" + Assert.Throws + message constructed via builder. + Expected the specified exception type to be thrown. + action: () => throw new ArgumentOutOfRangeException("MyParamNameHere") + expected exception type: + actual exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeOfType(); @@ -152,7 +177,13 @@ public void ThrowsExactly_WithMessageBuilder_FailsBecauseNoException() return "message constructed via builder."; }); action.Should().Throw() - .WithMessage("Assert.ThrowsExactly failed. Expected exception type: but no exception was thrown. 'action' expression: '() => { }'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsExactly + message constructed via builder. + Expected an exception to be thrown. + action: () => { } + expected exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeNull(); @@ -169,7 +200,14 @@ public void ThrowsExactly_WithMessageBuilder_FailsBecauseTypeMismatch() return "message constructed via builder."; }); action.Should().Throw() - .WithMessage("Assert.ThrowsExactly failed. Expected exception type:. Actual exception type:. 'action' expression: '() => throw new ArgumentOutOfRangeException(\"MyParamNameHere\")'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsExactly + message constructed via builder. + Expected the specified exception type to be thrown. + action: () => throw new ArgumentOutOfRangeException("MyParamNameHere") + expected exception type: + actual exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeOfType(); @@ -199,7 +237,13 @@ public async Task ThrowsAsync_WithMessageBuilder_FailsBecauseNoException() return "message constructed via builder."; }); (await action.Should().ThrowAsync()) - .WithMessage("Assert.ThrowsAsync failed. Expected exception type: but no exception was thrown. 'action' expression: '() => Task.CompletedTask'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsAsync + message constructed via builder. + Expected an exception to be thrown. + action: () => Task.CompletedTask + expected exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeNull(); @@ -216,7 +260,14 @@ public async Task ThrowsAsync_WithMessageBuilder_FailsBecauseTypeMismatch() return "message constructed via builder."; }); (await action.Should().ThrowAsync()) - .WithMessage("Assert.ThrowsAsync failed. Expected exception type:. Actual exception type:. 'action' expression: '() => Task.FromException(new ArgumentOutOfRangeException(\"MyParamNameHere\"))'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsAsync + message constructed via builder. + Expected the specified exception type to be thrown. + action: () => Task.FromException(new ArgumentOutOfRangeException("MyParamNameHere")) + expected exception type: + actual exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeOfType(); @@ -246,7 +297,13 @@ public async Task ThrowsExactlyAsync_WithMessageBuilder_FailsBecauseNoException( return "message constructed via builder."; }); (await action.Should().ThrowAsync()) - .WithMessage("Assert.ThrowsExactlyAsync failed. Expected exception type: but no exception was thrown. 'action' expression: '() => Task.CompletedTask'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsExactlyAsync + message constructed via builder. + Expected an exception to be thrown. + action: () => Task.CompletedTask + expected exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeNull(); @@ -263,7 +320,14 @@ public async Task ThrowsExactlyAsync_WithMessageBuilder_FailsBecauseTypeMismatch return "message constructed via builder."; }); (await action.Should().ThrowAsync()) - .WithMessage("Assert.ThrowsExactlyAsync failed. Expected exception type:. Actual exception type:. 'action' expression: '() => Task.FromException(new ArgumentOutOfRangeException(\"MyParamNameHere\"))'. message constructed via builder."); + .WithMessage(""" + Assert.ThrowsExactlyAsync + message constructed via builder. + Expected the specified exception type to be thrown. + action: () => Task.FromException(new ArgumentOutOfRangeException("MyParamNameHere")) + expected exception type: + actual exception type: + """); wasBuilderCalled.Should().BeTrue(); exceptionPassedToBuilder.Should().BeOfType(); diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.cs index 21dbd8e1ac..9d68d02208 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.cs @@ -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 AwesomeAssertions; @@ -31,7 +31,7 @@ public void ObsoleteEqualsMethodThrowsAssertFailedException() Action act = () => Assert.Equals("test", "test"); #pragma warning restore CS0618 // Type or member is obsolete act.Should().Throw() - .WithMessage("*Assert.Equals should not be used for Assertions*"); + .WithMessage("Assert.Fail\nAssert.Equals should not be used for Assertions. Please use Assert.AreEqual & overloads instead."); } public void ObsoleteReferenceEqualsMethodThrowsAssertFailedException() @@ -41,7 +41,7 @@ public void ObsoleteReferenceEqualsMethodThrowsAssertFailedException() Action act = () => Assert.ReferenceEquals(obj, obj); #pragma warning restore CS0618 // Type or member is obsolete act.Should().Throw() - .WithMessage("*Assert.ReferenceEquals should not be used for Assertions*"); + .WithMessage("Assert.Fail\nAssert.ReferenceEquals should not be used for Assertions. Please use Assert.AreSame & overloads instead."); } #endif #endregion @@ -65,4 +65,263 @@ private sealed class DummyIFormattable : IFormattable public string ToString(string? format, IFormatProvider? formatProvider) => "DummyIFormattable.ToString()"; } + + #region FormatValue truncation + + public void FormatValue_WhenStringExceedsMaxLength_ShouldTruncateWithEllipsis() + { + // FormatValue truncation applies to non-string-diff contexts like IsNull + // 300 'x' chars -> quoted as "xxx..." (302 chars total) -> truncated at 256 chars with ellipsis + string longValue = new('x', 300); + // Truncate takes first 256 chars of quoted string: opening quote + 255 x's, then appends "... 46 more" + string expectedValue = "\"" + new string('x', 255) + "... 46 more"; + + Action action = () => Assert.IsNull(longValue); + action.Should().Throw() + .WithMessage($""" + Assert.IsNull(longValue) + Expected value to be null. + value: {expectedValue} + """); + } + + public void FormatValue_WhenStringIsWithinMaxLength_ShouldNotTruncate() + { + string value = new('x', 50); + string expectedFullValue = "\"" + new string('x', 50) + "\""; + + Action action = () => Assert.IsNull(value); + action.Should().Throw() + .WithMessage($""" + Assert.IsNull(value) + Expected value to be null. + value: {expectedFullValue} + """); + } + + public void FormatValue_WhenCustomToStringExceedsMaxLength_ShouldTruncate() + { + // Custom ToString returns 300 chars ? truncated at 256 + var obj = new ObjectWithLongToString(); + string expectedValue = new string('L', 256) + "... 44 more"; + + Action action = () => Assert.IsNull(obj); + action.Should().Throw() + .WithMessage($""" + Assert.IsNull(obj) + Expected value to be null. + value: {expectedValue} + """); + } + + public void TruncateExpression_WhenExpressionExceeds100Chars_ShouldShowEllipsis() + { + // Variable name is 113 chars ? exceeds 100 char limit ? truncated with "..." + string aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ = null!; + + Action action = () => Assert.IsNotNull(aVeryLongVariableNameThatExceedsOneHundredCharactersInLengthToTestTruncationBehaviorOfExpressionDisplayXYZ); + action.Should().Throw() + .WithMessage(""" + Assert.IsNotNull(aVeryLongVariableNameThatExceedsOneHundredCharacte...) + Expected value to not be null. + """); + } + + #endregion + + #region FormatValue newline escaping + + public void FormatValue_WhenValueContainsNewlines_ShouldEscapeThem() + { + var obj = new ObjectWithNewlineToString(); + + Action action = () => Assert.IsNull(obj); + action.Should().Throw() + .WithMessage(""" + Assert.IsNull(obj) + Expected value to be null. + value: line1\r\nline2\nline3 + """); + } + + public void FormatValue_WhenStringContainsNewlines_ShouldEscapeThem() + { + string value = "hello\nworld"; + + Action action = () => Assert.IsNull(value); + action.Should().Throw() + .WithMessage(""" + Assert.IsNull(value) + Expected value to be null. + value: "hello\nworld" + """); + } + + #endregion + + #region FormatValue collection preview + + public void FormatValue_WhenValueIsCollection_ShouldShowPreview() + { + var collection = new List { 1, 2, 3 }; + + Action action = () => Assert.IsNull(collection); + action.Should().Throw() + .WithMessage(""" + Assert.IsNull(collection) + Expected value to be null. + value: [1, 2, 3] + """); + } + + public void FormatCollectionPreview_WhenTotalStringLengthExceeds256_ShouldTruncate() + { + // Each element is a 30-char string -> FormatValue wraps in quotes -> "aaa...aaa" = 32 chars + // With ", " separator: first = 32, subsequent = 34 each + // 32 + 6*34 = 236 <= 256, 32 + 7*34 = 270 > 256 + // So 7 elements should display, then "...", with total count 20 + var collection = new List(); + for (int i = 0; i < 20; i++) + { + collection.Add(new string((char)('a' + (i % 26)), 30)); + } + + Action action = () => Assert.Contains("not-there", collection); + action.Should().Throw() + .WithMessage($""" + Assert.Contains("not-there", collection) + Expected collection to contain the specified item. + collection: ["{new string('a', 30)}", "{new string('b', 30)}", "{new string('c', 30)}", "{new string('d', 30)}", "{new string('e', 30)}", "{new string('f', 30)}", "{new string('g', 30)}", ... 13 more] + """); + } + + public void FormatCollectionPreview_WhenElementToStringExceeds50_ShouldTruncateElement() + { + // Element has 80-char string ? FormatValue(maxLength:50) ? "zzz..." (82 chars quoted) ? truncated at 50 + var collection = new List { new string('z', 80), "short" }; + string expectedFirstElement = "\"" + new string('z', 49) + "... 32 more"; + + Action action = () => Assert.Contains("not-there", collection); + action.Should().Throw() + .WithMessage($""" + Assert.Contains("not-there", collection) + Expected collection to contain the specified item. + collection: [{expectedFirstElement}, "short"] + """); + } + + public void FormatCollectionPreview_WhenCollectionContainsNestedCollections_ShouldShowNestedPreview() + { + var inner1 = new List { 1, 2 }; + var inner2 = new List { 3, 4 }; + var outer = new List> { inner1, inner2 }; + + Action action = () => Assert.IsNull(outer); + action.Should().Throw() + .WithMessage(""" + Assert.IsNull(outer) + Expected value to be null. + value: [[1, 2], [3, 4]] + """); + } + + public void FormatCollectionPreview_WhenNestedCollectionIsLarge_ShouldTruncateInnerAt50() + { + // Inner collection has many elements -> inner preview string budget is 50 chars + // Elements 0-9 are 1 char each: "0" takes 1, subsequent take 3 (digit + ", ") + // 1 + 9*3 = 28 chars for 0-9. Then 10-99 are 2 char digits + 2 sep = 4 each + // 28 + 4n = 50 -> n = 5.5 -> 5 more (10-14). 28 + 5*4 = 48, next would be 52 > 50 + // So inner preview shows: 0-14 (15 elements), then "..." + var inner = new List(); + for (int i = 0; i < 50; i++) + { + inner.Add(i); + } + + var outer = new List> { inner }; + + Action action = () => Assert.IsNull(outer); + action.Should().Throw() + .WithMessage(""" + Assert.IsNull(outer) + Expected value to be null. + value: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ... 35 more]] + """); + } + + public void FormatCollectionPreview_WhenElementContainsNewlines_ShouldEscapeThem() + { + var collection = new List { "line1\nline2", "ok" }; + + Action action = () => Assert.Contains("not-there", collection); + action.Should().Throw() + .WithMessage(""" + Assert.Contains("not-there", collection) + Expected collection to contain the specified item. + collection: ["line1\nline2", "ok"] + """); + } + + public void FormatCollectionPreview_WhenSingleElement_ShouldShowSingularForm() + { + var collection = new List { 42 }; + + Action action = () => Assert.Contains(99, collection); + action.Should().Throw() + .WithMessage(""" + Assert.Contains(99, collection) + Expected collection to contain the specified item. + collection: [42] + """); + } + + public void FormatCollectionParameter_WhenNonICollectionEnumerable_ShouldNotReEnumerate() + { + // This enumerable yields different results on each enumeration. + // The assertion materializes the enumerable once at the boundary, + // so both the assertion check and the error message use the same snapshot. + int callCount = 0; + IEnumerable NonDeterministicEnumerable() + { + callCount++; + if (callCount == 1) + { + // First (and only) enumeration: materialized by Assert.Contains + yield return 1; + yield return 2; + yield return 3; + } + else + { + // If re-enumerated, yields completely different values + yield return 99; + yield return 100; + } + } + + IEnumerable collection = NonDeterministicEnumerable(); + Action action = () => Assert.Contains(42, collection); + action.Should().Throw() + .WithMessage(""" + Assert.Contains(42, collection) + Expected collection to contain the specified item. + collection: [1, 2, 3] + """); + + // The enumerable should have been enumerated exactly once (materialized at assertion boundary). + // If this were 2, the error message could show [99, 100] instead of [1, 2, 3]. + callCount.Should().Be(1); + } + + #endregion +} + +internal sealed class ObjectWithNewlineToString +{ + public override string ToString() => "line1\r\nline2\nline3"; +} + +internal sealed class ObjectWithLongToString +{ + public override string ToString() => new string('L', 300); } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs index 6e351151dd..1c78467066 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs @@ -103,7 +103,10 @@ public void CollectionAssertIsSubsetOf_ReturnedSubsetValueMessage_ThrowException Action action = () => CollectionAssert.IsSubsetOf(collection, superset); // Assert - action.Should().Throw().WithMessage("CollectionAssert.IsSubsetOf failed. Element(s) is/are not present in the collection."); + action.Should().Throw().WithMessage(""" + CollectionAssert.IsSubsetOf + Element(s) is/are not present in the collection. + """); } public void CollectionAssertIsSubsetOf_WithMessage_ReturnedSubsetValueMessage_ThrowExceptionMessage() @@ -116,7 +119,11 @@ public void CollectionAssertIsSubsetOf_WithMessage_ReturnedSubsetValueMessage_Th Action action = () => CollectionAssert.IsSubsetOf(collection, superset, "message"); // Assert - action.Should().Throw().WithMessage("CollectionAssert.IsSubsetOf failed. Element(s) is/are not present in the collection. message"); + action.Should().Throw().WithMessage(""" + CollectionAssert.IsSubsetOf + message + Element(s) is/are not present in the collection. + """); } public void CollectionAssertIsNotSubsetOfNullabilityPostConditions() @@ -176,7 +183,11 @@ public void CollectionAssertAreEqual_WithNestedDiffSizedArrays_Fails() int[][] expected = [[1, 2], [3, 4], [5, 6], [7, 8], [9]]; int[][] actual = [[1, 2], [999, 999, 999, 999, 999], [5, 6], [], [9]]; Action action = () => CollectionAssert.AreEqual(expected, actual); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreEqual + Different number of elements. + """); } public void CollectionAssertAreEqual_WithCaseSensetiveComparer_Fails() @@ -184,7 +195,13 @@ public void CollectionAssertAreEqual_WithCaseSensetiveComparer_Fails() List expected = ["one", "two"]; List actual = ["ONE", "tWo"]; Action action = () => CollectionAssert.AreEqual(expected, actual, StringComparer.Ordinal); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreEqual + Element at index 1 do not match. + expected: w + actual: W + """); } public void CollectionAssertAreEqualComparerMessageNullabilityPostConditions() @@ -218,7 +235,13 @@ public void CollectionAssertAreEqual_NotEqualNestedLists_Fails() ICollection? collection2 = GetNotMatchingNestedLists(); Action action = () => CollectionAssert.AreEqual(collection1, collection2); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreEqual + Element at index 0 do not match. + expected: 4 + actual: 1 + """); } public void CollectionAssertAreEqual_EqualNonICollectionInnerCollection_Passes() @@ -235,7 +258,13 @@ public void CollectionAssertAreEqual_NotEqualNonICollectionInnerCollection_Fails ICollection? collection2 = GetNotMatchingGetNonICollectionInnerCollection(); Action action = () => CollectionAssert.AreEqual(collection1, collection2); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreEqual + Element at index 0 do not match. + expected: 1 + actual: 6 + """); } public void CollectionAssertAreNotEqual_NotEqualNestedLists_Passes() @@ -251,7 +280,11 @@ public void CollectionAssertAreNotEqual_WithIgnoreCaseComparer_Fails() List expected = ["one", "two"]; List actual = ["ONE", "tWo"]; Action action = () => CollectionAssert.AreNotEqual(expected, actual, StringComparer.OrdinalIgnoreCase); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreNotEqual + Both collections contain the same elements. + """); } public void CollectionAssertAreNotEqual_WithCaseSensitiveComparer_Passes() @@ -267,7 +300,11 @@ public void CollectionAssertAreNotEqual_EqualNestedLists_Fails() ICollection? collection2 = GetNestedLists(); Action action = () => CollectionAssert.AreNotEqual(collection1, collection2); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreNotEqual + Both collections contain the same elements. + """); } public void CollectionAssertAreNotEqual_EqualNonICollectionInnerCollection_Fails() @@ -276,7 +313,11 @@ public void CollectionAssertAreNotEqual_EqualNonICollectionInnerCollection_Fails ICollection? collection2 = GetNonICollectionInnerCollection(); Action action = () => CollectionAssert.AreNotEqual(collection1, collection2); - action.Should().Throw(); + action.Should().Throw() + .WithMessage(""" + CollectionAssert.AreNotEqual + Both collections contain the same elements. + """); } public void CollectionAssertAreNotEqual_NotEqualNonICollectionInnerCollection_Passes() @@ -335,7 +376,13 @@ public void CollectionAssertAreEquivalent_FailWhenNotEquivalent_WithMessage() ICollection? collection2 = GetMatchingSuperset(); Action action = () => CollectionAssert.AreEquivalent(collection1, collection2, "message"); action.Should().Throw() - .WithMessage("*message*"); + .WithMessage(""" + CollectionAssert.AreEquivalent + message + Expected the same number of elements in the collections. + expected count: 1 + actual count: 2 + """); } public void CollectionAssertAreEquivalent_WithInsensitiveCaseComparer_DoesNotThrow() @@ -351,7 +398,13 @@ public void CollectionAssertAreEquivalent_FailsWithInsensitiveCaseComparer_WithM ICollection? collection2 = GetLettersCaseMismatchingSuperset(); Action action = () => CollectionAssert.AreEquivalent(collection1?.Cast(), collection2?.Cast(), new CaseInsensitiveEqualityComparer(), "message"); action.Should().Throw() - .WithMessage("*message*"); + .WithMessage(""" + CollectionAssert.AreEquivalent + message + Expected the same number of elements in the collections. + expected count: 1 + actual count: 2 + """); } public void CollectionAssertAreNotEquivalent_SameItemsWithDifferentOrder_DoesNotThrow() @@ -367,7 +420,11 @@ public void CollectionAssertAreNotEquivalent_FailWhenNotEquivalent_WithMessage() ICollection? collection2 = GetMatchingSuperset(); Action action = () => CollectionAssert.AreNotEquivalent(collection1, collection2, "message"); action.Should().Throw() - .WithMessage("*message*"); + .WithMessage(""" + CollectionAssert.AreNotEquivalent + message + Both collections contain the same elements. + """); } public void CollectionAssertAreNotEquivalent_WithInsensitiveCaseComparer_DoesNotThrow() @@ -383,14 +440,22 @@ public void CollectionAssertAreNotEquivalent_FailsWithInsensitiveCaseComparer_Wi ICollection? collection2 = GetLettersCaseMismatchingSuperset(); Action action = () => CollectionAssert.AreNotEquivalent(collection1?.Cast(), collection2?.Cast(), new CaseInsensitiveNotEqualityComparer(), "message"); action.Should().Throw() - .WithMessage("*message*"); + .WithMessage(""" + CollectionAssert.AreNotEquivalent + message + Both collections contain the same elements. + """); } public void CollectionAssertAreNotEquivalent_FailsWithTwoNullsAndComparer_WithMessageAndParams() { Action action = () => CollectionAssert.AreNotEquivalent(null, null, new CaseInsensitiveNotEqualityComparer(), "message format"); action.Should().Throw() - .WithMessage("*message*"); + .WithMessage(""" + CollectionAssert.AreNotEquivalent + message format + Both collection references point to the same collection object. + """); } public void CollectionAssertAreEqualWithoutUserMessage_FailsWithGoodMessage() @@ -398,9 +463,10 @@ public void CollectionAssertAreEqualWithoutUserMessage_FailsWithGoodMessage() Action action = () => CollectionAssert.AreEqual(new[] { 1, 2, 3 }, new[] { 1, 5, 3 }); action.Should().Throw() .WithMessage(""" - CollectionAssert.AreEqual failed. Element at index 1 do not match. - Expected: 2 - Actual: 5 + CollectionAssert.AreEqual + Element at index 1 do not match. + expected: 2 + actual: 5 """); } @@ -408,11 +474,12 @@ public void CollectionAssertAreEqualWithUserMessage_FailsWithGoodMessage() { Action action = () => CollectionAssert.AreEqual(new[] { 1, 2, 3 }, new[] { 1, 5, 3 }, "User-provided message"); action.Should().Throw() - .WithMessage( - """ - CollectionAssert.AreEqual failed. User-provided message. Element at index 1 do not match. - Expected: 2 - Actual: 5 + .WithMessage(""" + CollectionAssert.AreEqual + User-provided message + Element at index 1 do not match. + expected: 2 + actual: 5 """); } diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/StringAssertTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/StringAssertTests.cs index 662bd5f742..f0b5d3ef7f 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/StringAssertTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/StringAssertTests.cs @@ -19,7 +19,12 @@ public void StringAssertContains() string notInString = "I'm not in the string above"; Action action = () => StringAssert.Contains(actual, notInString); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.Contains failed"); + .WithMessage(""" + StringAssert.Contains + Expected string to contain the specified substring. + substring: "I'm not in the string above" + value: "The quick brown fox jumps over the lazy dog." + """); } public void StringAssertStartsWith() @@ -28,7 +33,12 @@ public void StringAssertStartsWith() string notInString = "I'm not in the string above"; Action action = () => StringAssert.StartsWith(actual, notInString); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.StartsWith failed"); + .WithMessage(""" + StringAssert.StartsWith + Expected string to start with the specified prefix. + expected prefix: "I'm not in the string above" + value: "The quick brown fox jumps over the lazy dog." + """); } public void StringAssertEndsWith() @@ -37,7 +47,12 @@ public void StringAssertEndsWith() string notInString = "I'm not in the string above"; Action action = () => StringAssert.EndsWith(actual, notInString); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.EndsWith failed"); + .WithMessage(""" + StringAssert.EndsWith + Expected string to end with the specified suffix. + expected suffix: "I'm not in the string above" + value: "The quick brown fox jumps over the lazy dog." + """); } public void StringAssertDoesNotMatch() @@ -46,7 +61,12 @@ public void StringAssertDoesNotMatch() Regex doesMatch = new("quick brown fox"); Action action = () => StringAssert.DoesNotMatch(actual, doesMatch); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.DoesNotMatch failed"); + .WithMessage(""" + StringAssert.DoesNotMatch + Expected string to not match the specified pattern. + pattern: quick brown fox + value: "The quick brown fox jumps over the lazy dog." + """); } public void StringAssertContainsIgnoreCase_DoesNotThrow() @@ -75,7 +95,12 @@ public void StringAssertContainsDoesNotThrowFormatException() { Action action = () => StringAssert.Contains(":-{", "x"); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.Contains failed"); + .WithMessage(""" + StringAssert.Contains + Expected string to contain the specified substring. + substring: "x" + value: ":-{" + """); } // See https://github.com/dotnet/sdk/issues/25373 @@ -83,7 +108,13 @@ public void StringAssertContainsDoesNotThrowFormatExceptionWithArguments() { Action action = () => StringAssert.Contains("{", "x", "message"); action.Should().Throw() - .And.Message.Should().Contain("StringAssert.Contains failed"); + .WithMessage(""" + StringAssert.Contains + message + Expected string to contain the specified substring. + substring: "x" + value: "{" + """); } public void StringAssertContainsNullabilitiesPostConditions()