diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs index 00b3e1eec6..1a9a7c9162 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsNull.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.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 System.ComponentModel; @@ -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) + " "); - ReportAssertIsNullFailed(_builder.ToString()); + ReportAssertIsNullFailed(_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) + " "); - ReportAssertIsNotNullFailed(_builder.ToString()); + ReportAssertIsNotNullFailed(_builder.ToString(), valueExpression, "value"); } } @@ -152,14 +152,27 @@ public static void IsNull(object? value, string? message = "", [CallerArgumentEx { if (IsNullFailing(value)) { - ReportAssertIsNullFailed(BuildUserMessageForValueExpression(message, valueExpression)); + ReportAssertIsNullFailed(value, message, valueExpression); } } private static bool IsNullFailing(object? value) => value is not null; - private static void ReportAssertIsNullFailed(string? message) - => ReportAssertFailed("Assert.IsNull", message); + [DoesNotReturn] + private static void ReportAssertIsNullFailed(object? value, string? message, string valueExpression) + { + string actualValue = AssertionValueRenderer.RenderValue(value); + EvidenceBlock evidence = EvidenceBlock.Create() + .AddLine("actual:", actualValue); + + StructuredAssertionMessage structured = new(FrameworkMessages.IsNullFailedSummary); + structured.WithUserMessage(message); + structured.WithEvidence(evidence); + structured.WithExpectedAndActual(AssertionValueRenderer.RenderValue(null), actualValue); + structured.WithCallSiteExpression(FormatCallSiteExpression("Assert.IsNull", valueExpression, nameof(value))); + + ReportAssertFailed(structured); + } /// #pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578 @@ -191,13 +204,25 @@ public static void IsNotNull([NotNull] object? value, string? message = "", [Cal { if (IsNotNullFailing(value)) { - ReportAssertIsNotNullFailed(BuildUserMessageForValueExpression(message, valueExpression)); + ReportAssertIsNotNullFailed(message, valueExpression, nameof(value)); } } private static bool IsNotNullFailing([NotNullWhen(false)] object? value) => value is null; [DoesNotReturn] - private static void ReportAssertIsNotNullFailed(string? message) - => ReportAssertFailed("Assert.IsNotNull", message); + private static void ReportAssertIsNotNullFailed(string? message, string valueExpression, string paramName) + { + string actualValue = AssertionValueRenderer.RenderValue(null); + EvidenceBlock evidence = EvidenceBlock.Create() + .AddLine("actual:", actualValue); + + StructuredAssertionMessage structured = new(FrameworkMessages.IsNotNullFailedSummary); + structured.WithUserMessage(message); + structured.WithEvidence(evidence); + structured.WithExpectedAndActual("not null", actualValue); + structured.WithCallSiteExpression(FormatCallSiteExpression("Assert.IsNotNull", valueExpression, paramName)); + + ReportAssertFailed(structured); + } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs b/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs index d1480fe701..4f24f6200f 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.IsTrue.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 System.ComponentModel; @@ -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) + " "); - ReportAssertIsTrueFailed(_builder.ToString()); + ReportAssertIsTrueFailed(_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) + " "); - ReportAssertIsFalseFailed(_builder.ToString()); + ReportAssertIsFalseFailed(_condition, _builder.ToString(), conditionExpression); } } @@ -150,15 +152,28 @@ public static void IsTrue([DoesNotReturnIf(false)] bool? condition, string? mess { if (IsTrueFailing(condition)) { - ReportAssertIsTrueFailed(BuildUserMessageForConditionExpression(message, conditionExpression)); + ReportAssertIsTrueFailed(condition, message, conditionExpression); } } private static bool IsTrueFailing(bool? condition) => condition is false or null; - private static void ReportAssertIsTrueFailed(string? message) - => ReportAssertFailed("Assert.IsTrue", message); + [DoesNotReturn] + private static void ReportAssertIsTrueFailed(bool? condition, string? message, string conditionExpression) + { + string actualValue = AssertionValueRenderer.RenderValue(condition); + EvidenceBlock evidence = EvidenceBlock.Create() + .AddLine("actual:", actualValue); + + StructuredAssertionMessage structured = new(FrameworkMessages.IsTrueFailedSummary); + structured.WithUserMessage(message); + structured.WithEvidence(evidence); + structured.WithExpectedAndActual(AssertionValueRenderer.RenderValue(true), actualValue); + structured.WithCallSiteExpression(FormatCallSiteExpression("Assert.IsTrue", conditionExpression, nameof(condition))); + + ReportAssertFailed(structured); + } /// #pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578 @@ -188,7 +203,7 @@ public static void IsFalse([DoesNotReturnIf(true)] bool? condition, string? mess { if (IsFalseFailing(condition)) { - ReportAssertIsFalseFailed(BuildUserMessageForConditionExpression(message, conditionExpression)); + ReportAssertIsFalseFailed(condition, message, conditionExpression); } } @@ -196,6 +211,18 @@ private static bool IsFalseFailing(bool? condition) => condition is true or null; [DoesNotReturn] - private static void ReportAssertIsFalseFailed(string userMessage) - => ReportAssertFailed("Assert.IsFalse", userMessage); + private static void ReportAssertIsFalseFailed(bool? condition, string? message, string conditionExpression) + { + string actualValue = AssertionValueRenderer.RenderValue(condition); + EvidenceBlock evidence = EvidenceBlock.Create() + .AddLine("actual:", actualValue); + + StructuredAssertionMessage structured = new(FrameworkMessages.IsFalseFailedSummary); + structured.WithUserMessage(message); + structured.WithEvidence(evidence); + structured.WithExpectedAndActual(AssertionValueRenderer.RenderValue(false), actualValue); + structured.WithCallSiteExpression(FormatCallSiteExpression("Assert.IsFalse", conditionExpression, nameof(condition))); + + ReportAssertFailed(structured); + } } diff --git a/src/TestFramework/TestFramework/Assertions/Assert.cs b/src/TestFramework/TestFramework/Assertions/Assert.cs index 56b13403ec..fda02ab91b 100644 --- a/src/TestFramework/TestFramework/Assertions/Assert.cs +++ b/src/TestFramework/TestFramework/Assertions/Assert.cs @@ -176,6 +176,26 @@ internal static void ThrowAssertFailed(StructuredAssertionMessage structuredMess throw CreateAssertFailedException(structuredMessage); } + /// + /// Formats a call-site expression for display at the bottom of a structured assertion message. + /// When the expression is empty, the call-site is omitted. When the expression contains newlines, + /// it is replaced with a <paramName> placeholder. + /// + internal static string? FormatCallSiteExpression(string assertionMethodName, string expression, string paramName) + { + if (string.IsNullOrWhiteSpace(expression)) + { + return null; + } + + // If expression contains newlines (multiline constant), replace with placeholder per RFC + string arg = expression.IndexOf('\n') >= 0 || expression.IndexOf('\r') >= 0 + ? $"<{paramName}>" + : expression; + + return $"{assertionMethodName}({arg})"; + } + private static string FormatAssertionFailed(string assertionName, string? message) { string failedMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AssertionFailed, assertionName); @@ -240,9 +260,6 @@ private static string BuildUserMessageForThreeExpressions(string? format, string : $"{callerArgMessagePart} {userMessage}"; } - private static string BuildUserMessageForConditionExpression(string? format, string conditionExpression) - => BuildUserMessageForSingleExpression(format, conditionExpression, "condition"); - private static string BuildUserMessageForValueExpression(string? format, string valueExpression) => BuildUserMessageForSingleExpression(format, valueExpression, "value"); diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx index 90350e2434..691f3edab7 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx @@ -408,4 +408,16 @@ Actual: {2} [STATestMethod] is not supported on non-Windows platforms. STA (Single Threaded Apartment) is a Windows-only COM threading concept. Use [OSCondition(OperatingSystems.Windows)] to skip this test on non-Windows platforms. - \ No newline at end of file + + Expected condition to be true. + + + Expected condition to be false. + + + Expected value to be null. + + + Expected value to not be null. + + diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf index c8794c978c..4ad5deac23 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf @@ -272,6 +272,11 @@ Skutečnost: {2} Neplatná adresa URL lístku GitHubu + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Hodnota {0} není v očekávaném rozsahu [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Skutečnost: {2} Řetězec „{0}“ odpovídá vzoru „{1}“. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf index ed1690341f..f61ee46c58 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf @@ -272,6 +272,11 @@ Tatsächlich: {2} Ungültige GitHub-Ticket-URL. + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Der Wert „{0}“ liegt nicht im erwarteten Bereich [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Tatsächlich: {2} Die Zeichenfolge „{0}“ stimmt mit dem Muster „{1}“ überein. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf index a3c92fbdb9..94a5797fc0 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf @@ -272,6 +272,11 @@ Real: {2} Dirección URL de vale de GitHub no válida + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} El valor "{0}" no está dentro del rango esperado [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Real: {2} La cadena "{0}" coincide con el patrón "{1}". {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf index 946c62ffb2..00d78302f3 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf @@ -272,6 +272,11 @@ Réel : {2} URL de ticket GitHub non valide + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} La valeur « {0} » n'est pas dans la plage attendue [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Réel : {2} La chaîne '{0}' correspond au modèle '{1}'. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf index 2ab47d7812..80b0b1b715 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf @@ -272,6 +272,11 @@ Effettivo: {2} L'URL del ticket GitHub non è valido + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Il valore '{0}' non è compreso nell'intervallo previsto [{1}, {2}]. {3} @@ -317,6 +322,21 @@ Effettivo: {2} La stringa '{0}' corrisponde al criterio '{1}'. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf index 12c82093c0..ee5344f86b 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf @@ -272,6 +272,11 @@ Actual: {2} GitHub チケット URL が無効です + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} 値 '{0}' は予期される範囲 [{1}..{2}] 内にありません。{3} @@ -317,6 +322,21 @@ Actual: {2} 文字列 '{0}' はパターン '{1}' と一致します。{2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf index a8ed4a21e8..e1d64ff123 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf @@ -272,6 +272,11 @@ Actual: {2} 잘못된 GitHub 티켓 URL + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} '{0}' 값이 예상 범위 [{1}..{2}] 내에 있지 않습니다. {3} @@ -317,6 +322,21 @@ Actual: {2} '{0}' 문자열이 '{1}' 패턴과 일치합니다. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf index ccbabc8449..b09f5eb893 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf @@ -272,6 +272,11 @@ Rzeczywiste: {2} Nieprawidłowy adres URL biletu usługi GitHub + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Wartość „{0}” nie mieści się w oczekiwanym zakresie [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Rzeczywiste: {2} Ciąg „{0}” jest zgodny ze wzorcem „{1}”. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf index d9463e35f0..3fdabfe37d 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf @@ -272,6 +272,11 @@ Real: {2} URL de tíquete do GitHub inválida + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} O valor '{0}' não está dentro do intervalo esperado [{1}.. {2}]. {3} @@ -317,6 +322,21 @@ Real: {2} A cadeia de caracteres “{0}” corresponde ao padrão “{1}”. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf index b21cf7dbcb..8262985ee7 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf @@ -272,6 +272,11 @@ Actual: {2} Недопустимый URL-адрес билета GitHub + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Значение "{0}" не находится в пределах ожидаемого диапазона [{1}..{2}]. {3} @@ -317,6 +322,21 @@ Actual: {2} Строка "{0}" соответствует шаблону "{1}". {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf index f25bf59562..8420e144a3 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf @@ -272,6 +272,11 @@ Gerçekte olan: {2} Geçersiz GitHub anahtar URL'si + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} Değer '{0}' beklenen aralık [{1}..{2}] içinde değil. {3} @@ -317,6 +322,21 @@ Gerçekte olan: {2} '{0}' dizesi, '{1}' deseni ile eşleşiyor. {2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf index 349be0a344..0b7558f104 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf @@ -272,6 +272,11 @@ Actual: {2} GitHub 票证 URL 无效 + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} 值 "{0}" 不在预期范围 [{1}..{2}] 内。{3} @@ -317,6 +322,21 @@ Actual: {2} 字符串 '{0}' 与模式 '{1}' 匹配。{2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf index 6362c9e608..cc658d8057 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf @@ -272,6 +272,11 @@ Actual: {2} 無效的 GitHub 票證 URL + + Expected condition to be false. + Expected condition to be false. + + Value '{0}' is not within the expected range [{1}..{2}]. {3} 值 '{0}' 不在預期的範圍 [{1}, {2}] 內。{3} @@ -317,6 +322,21 @@ Actual: {2} 字串 '{0}' 與模式 '{1}' 相符。{2} + + Expected value to not be null. + Expected value to not be null. + + + + Expected value to be null. + Expected value to be null. + + + + Expected condition to be true. + Expected condition to be true. + + The member specified ({0}) could not be found. You might need to regenerate your private accessor, diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/SoftAssertionTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/SoftAssertionTests.cs index ebef8904a1..13129811e4 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/SoftAssertionTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/SoftAssertionTests.cs @@ -77,7 +77,7 @@ public async Task ScopeWithIsNotNullSoftFailure_CollectsFailure() testHostResult.AssertExitCodeIs(ExitCode.AtLeastOneTestFailed); testHostResult.AssertOutputMatchesRegex( - """failed ScopeWithIsNotNullSoftFailure \(\d+ms\)[\s\S]+Assert\.IsNotNull failed\.[\s\S]+at UnitTest1\.ScopeWithIsNotNullSoftFailure\(\)"""); + """failed ScopeWithIsNotNullSoftFailure \(\d+ms\)[\s\S]+Assertion failed\. Expected value to not be null\.[\s\S]+at UnitTest1\.ScopeWithIsNotNullSoftFailure\(\)"""); } [TestMethod] diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs index bd365d680a..f1aba913c4 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsNull.cs @@ -16,7 +16,14 @@ public void IsNull_PassNonNull_ShouldFail() { Action action = () => Assert.IsNull(new object()); action.Should().Throw() - .WithMessage("Assert.IsNull failed. 'value' expression: 'new object()'."); + .WithMessage( + """ + Assertion failed. Expected value to be null. + + actual: System.Object + + Assert.IsNull(new object()) + """); } public void IsNull_StringMessage_PassNull_ShouldPass() @@ -26,7 +33,15 @@ 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( + """ + Assertion failed. Expected value to be null. + User-provided message + + actual: System.Object + + Assert.IsNull(new object()) + """); } public void IsNull_InterpolatedString_PassNull_ShouldPass() @@ -42,7 +57,15 @@ 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( + $""" + Assertion failed. Expected value to be null. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: System.Object + + Assert.IsNull(new object()) + """); o.WasToStringCalled.Should().BeTrue(); } @@ -73,14 +96,29 @@ public void IsNotNull_PassNull_ShouldFail() { Action action = () => Assert.IsNotNull(null); action.Should().Throw() - .WithMessage("Assert.IsNotNull failed. 'value' expression: 'null'."); + .WithMessage( + """ + Assertion failed. Expected value to not be null. + + actual: null + + Assert.IsNotNull(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( + """ + Assertion failed. Expected value to not be null. + User-provided message + + actual: null + + Assert.IsNotNull(null) + """); } public async Task IsNotNull_InterpolatedString_PassNonNull_ShouldFail() @@ -89,7 +127,15 @@ 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( + $""" + Assertion failed. Expected value to not be null. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: null + + Assert.IsNotNull(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..f6bcd2cb25 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.IsTrueTests.cs @@ -12,7 +12,14 @@ public void IsFalseNullableBooleanShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsFalse(nullBool); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'."); + .WithMessage( + """ + Assertion failed. Expected condition to be false. + + actual: null + + Assert.IsFalse(nullBool) + """); } public void IsFalseNullableBooleanShouldFailWithTrue() @@ -20,7 +27,14 @@ public void IsFalseNullableBooleanShouldFailWithTrue() bool? nullBool = true; Action action = () => Assert.IsFalse(nullBool); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'nullBool'."); + .WithMessage( + """ + Assertion failed. Expected condition to be false. + + actual: true + + Assert.IsFalse(nullBool) + """); } public void IsFalseNullableBooleanShouldNotFailWithFalse() @@ -33,7 +47,14 @@ public void IsFalseBooleanShouldFailWithTrue() { Action action = () => Assert.IsFalse(true); action.Should().Throw() - .WithMessage("Assert.IsFalse failed. 'condition' expression: 'true'."); + .WithMessage( + """ + Assertion failed. Expected condition to be false. + + actual: true + + Assert.IsFalse(true) + """); } public void IsFalseBooleanShouldNotFailWithFalse() @@ -44,7 +65,15 @@ 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( + """ + Assertion failed. Expected condition to be false. + User-provided message + + actual: null + + Assert.IsFalse(nullBool) + """); } public void IsFalseNullableBooleanStringMessageShouldFailWithTrue() @@ -52,7 +81,15 @@ 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( + """ + Assertion failed. Expected condition to be false. + User-provided message + + actual: true + + Assert.IsFalse(nullBool) + """); } public void IsFalseNullableBooleanStringMessageShouldNotFailWithFalse() @@ -65,7 +102,15 @@ 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( + """ + Assertion failed. Expected condition to be false. + User-provided message + + actual: true + + Assert.IsFalse(true) + """); } public void IsFalseBooleanStringMessageShouldNotFailWithFalse() @@ -78,7 +123,15 @@ 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( + $""" + Assertion failed. Expected condition to be false. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: null + + Assert.IsFalse(nullBool) + """); } public async Task IsFalseNullableBooleanInterpolatedStringMessageShouldFailWithTrue() @@ -88,7 +141,15 @@ 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( + $""" + Assertion failed. Expected condition to be false. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: true + + Assert.IsFalse(nullBool) + """); } public void IsFalseNullableBooleanInterpolatedStringMessageShouldNotFailWithFalse() @@ -103,7 +164,15 @@ 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( + $""" + Assertion failed. Expected condition to be false. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: true + + Assert.IsFalse(true) + """); } public void IsFalseBooleanInterpolatedStringMessageShouldNotFailWithFalse() @@ -114,7 +183,14 @@ public void IsTrueNullableBooleanShouldFailWithNull() bool? nullBool = null; Action action = () => Assert.IsTrue(nullBool); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'."); + .WithMessage( + """ + Assertion failed. Expected condition to be true. + + actual: null + + Assert.IsTrue(nullBool) + """); } public void IsTrueNullableBooleanShouldFailWithFalse() @@ -122,7 +198,14 @@ public void IsTrueNullableBooleanShouldFailWithFalse() bool? nullBool = false; Action action = () => Assert.IsTrue(nullBool); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'nullBool'."); + .WithMessage( + """ + Assertion failed. Expected condition to be true. + + actual: false + + Assert.IsTrue(nullBool) + """); } public void IsTrueNullableBooleanShouldNotFailWithTrue() @@ -135,7 +218,14 @@ public void IsTrueBooleanShouldFailWithFalse() { Action action = () => Assert.IsTrue(false); action.Should().Throw() - .WithMessage("Assert.IsTrue failed. 'condition' expression: 'false'."); + .WithMessage( + """ + Assertion failed. Expected condition to be true. + + actual: false + + Assert.IsTrue(false) + """); } public void IsTrueBooleanShouldNotFailWithTrue() @@ -146,7 +236,15 @@ 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( + """ + Assertion failed. Expected condition to be true. + User-provided message + + actual: null + + Assert.IsTrue(nullBool) + """); } public void IsTrueNullableBooleanStringMessageShouldFailWithFalse() @@ -154,7 +252,15 @@ 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( + """ + Assertion failed. Expected condition to be true. + User-provided message + + actual: false + + Assert.IsTrue(nullBool) + """); } public void IsTrueNullableBooleanStringMessageShouldNotFailWithTrue() @@ -167,7 +273,15 @@ 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( + """ + Assertion failed. Expected condition to be true. + User-provided message + + actual: false + + Assert.IsTrue(false) + """); } public void IsTrueBooleanStringMessageShouldNotFailWithTrue() @@ -180,7 +294,15 @@ 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( + $""" + Assertion failed. Expected condition to be true. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: null + + Assert.IsTrue(nullBool) + """); } public async Task IsTrueNullableBooleanInterpolatedStringMessageShouldFailWithFalse() @@ -190,7 +312,15 @@ 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( + $""" + Assertion failed. Expected condition to be true. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: false + + Assert.IsTrue(nullBool) + """); } public void IsTrueNullableBooleanInterpolatedStringMessageShouldNotFailWithTrue() @@ -205,7 +335,15 @@ 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( + $""" + Assertion failed. Expected condition to be true. + User-provided message. DummyClassTrackingToStringCalls, DummyClassTrackingToStringCalls, Hello, DummyIFormattable.ToString(), {string.Format(null, "{0:tt}", dateTime)}, {string.Format(null, "{0,5:tt}", dateTime)} + + actual: false + + Assert.IsTrue(false) + """); } public void IsTrueBooleanInterpolatedStringMessageShouldNotFailWithTrue() diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs index 096dbb9905..e78cd8e747 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/AssertTests.ScopeTests.cs @@ -49,7 +49,14 @@ public void Scope_MultipleFailures_CollectsAllErrors() innerException.InnerExceptions.Should().HaveCount(2); innerException.InnerExceptions[0].Message.Should().Be("Assert.AreEqual failed. Expected:<1>. Actual:<2>. 'expected' expression: '1', 'actual' expression: '2'."); - innerException.InnerExceptions[1].Message.Should().Be("Assert.IsTrue failed. 'condition' expression: 'false'."); + innerException.InnerExceptions[1].Message.Should().Be( + """ + Assertion failed. Expected condition to be true. + + actual: false + + Assert.IsTrue(false) + """); } public void Scope_AfterDispose_AssertionsThrowNormally() @@ -137,7 +144,14 @@ public void Scope_AssertIsNotNull_IsSoftFailure() .Which; innerException.InnerExceptions.Should().HaveCount(2); - innerException.InnerExceptions[0].Message.Should().Be("Assert.IsNotNull failed. 'value' expression: 'value'."); + innerException.InnerExceptions[0].Message.Should().Be( + """ + Assertion failed. Expected value to not be null. + + actual: null + + Assert.IsNotNull(value) + """); innerException.InnerExceptions[1].Message.Should().Contain("Assert.AreEqual failed."); }