From 9cb5ec77a88e84989caad04bd43306ac42b47f85 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Tue, 19 Nov 2024 15:21:47 +0100 Subject: [PATCH] Partially improve CollectionAssert message (#4027) --- .../Assertions/CollectionAssert.cs | 27 ++++++++++++------- .../Resources/FrameworkMessages.Designer.cs | 6 +++-- .../Resources/FrameworkMessages.resx | 6 +++-- .../Resources/xlf/FrameworkMessages.cs.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.de.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.es.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.fr.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.it.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.ja.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.ko.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.pl.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.pt-BR.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.ru.xlf | 16 ++++++----- .../Resources/xlf/FrameworkMessages.tr.xlf | 16 ++++++----- .../xlf/FrameworkMessages.zh-Hans.xlf | 16 ++++++----- .../xlf/FrameworkMessages.zh-Hant.xlf | 16 ++++++----- .../Assertions/CollectionAssertTests.cs | 22 +++++++++++++++ 17 files changed, 178 insertions(+), 91 deletions(-) diff --git a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs index 43465e0d6..b43825c24 100644 --- a/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs +++ b/src/TestFramework/TestFramework/Assertions/CollectionAssert.cs @@ -1158,8 +1158,7 @@ public sealed class CollectionAssert string reason = string.Empty; if (!AreCollectionsEqual(expected, actual, new ObjectComparer(), ref reason)) { - string userMessage = Assert.BuildUserMessage(message, parameters); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); + string finalMessage = ConstructFinalMessage(reason, message, parameters); Assert.ThrowAssertFailed("CollectionAssert.AreEqual", finalMessage); } } @@ -1243,8 +1242,7 @@ public sealed class CollectionAssert string reason = string.Empty; if (AreCollectionsEqual(notExpected, actual, new ObjectComparer(), ref reason)) { - string userMessage = Assert.BuildUserMessage(message, parameters); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); + string finalMessage = ConstructFinalMessage(reason, message, parameters); Assert.ThrowAssertFailed("CollectionAssert.AreNotEqual", finalMessage); } } @@ -1335,8 +1333,7 @@ public sealed class CollectionAssert string reason = string.Empty; if (!AreCollectionsEqual(expected, actual, comparer, ref reason)) { - string userMessage = Assert.BuildUserMessage(message, parameters); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); + string finalMessage = ConstructFinalMessage(reason, message, parameters); Assert.ThrowAssertFailed("CollectionAssert.AreEqual", finalMessage); } } @@ -1427,8 +1424,7 @@ public sealed class CollectionAssert string reason = string.Empty; if (AreCollectionsEqual(notExpected, actual, comparer, ref reason)) { - string userMessage = Assert.BuildUserMessage(message, parameters); - string finalMessage = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); + string finalMessage = ConstructFinalMessage(reason, message, parameters); Assert.ThrowAssertFailed("CollectionAssert.AreNotEqual", finalMessage); } } @@ -1656,7 +1652,9 @@ public sealed class CollectionAssert reason = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.ElementsAtIndexDontMatch, - position); + position, + Assert.ReplaceNulls(curExpected), + Assert.ReplaceNulls(curActual)); return false; } } @@ -1672,6 +1670,17 @@ public sealed class CollectionAssert return true; } + private static string ConstructFinalMessage( + string reason, + [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string? message, + params object?[]? parameters) + { + string userMessage = Assert.BuildUserMessage(message, parameters); + return userMessage.Length == 0 + ? reason + : string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CollectionEqualReason, userMessage, reason); + } + /// /// compares the objects using object.Equals. /// diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs b/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs index edfdc9390..67efb2d94 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs @@ -223,7 +223,7 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting { } /// - /// Looks up a localized string similar to {0}({1}). + /// Looks up a localized string similar to {0}. {1}. /// internal static string CollectionEqualReason { get { @@ -340,7 +340,9 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting { } /// - /// Looks up a localized string similar to Element at index {0} do not match.. + /// Looks up a localized string similar to Element at index {0} do not match. + ///Expected: {1} + ///Actual: {2}. /// internal static string ElementsAtIndexDontMatch { get { diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx index a30aef084..8a0a86b9d 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx @@ -160,7 +160,7 @@ Both collections contain the same elements. {0} - {0}({1}) + {0}. {1} String '{0}' does not contain string '{1}'. {2}. @@ -169,7 +169,9 @@ The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} - Element at index {0} do not match. + Element at index {0} do not match. +Expected: {1} +Actual: {2} Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf index b57c6af5f..22282d68c 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - Element na indexu {0} nesouhlasí. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf index d7e5e4c5e..cd057100c 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - Die Elemente bei Index "{0}" stimmen nicht überein. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf index 882d77943..e2f399945 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - El elemento del índice {0} no coincide. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf index 267574ab0..2281e0041 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - Les éléments à l'index {0} ne correspondent pas. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf index bbc846795..f81156311 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - L'elemento alla posizione di indice {0} non corrisponde. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf index adaeecc7e..bf327a4c7 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - インデックス {0} の要素が一致しません。 - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf index f1864eb87..cf297a289 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - 인덱스 {0}에 있는 요소가 일치하지 않습니다. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf index 0f2afb292..9dd740e17 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - Element w indeksie {0} nie jest zgodny. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf index 4eb59da21..5152025e1 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - O elemento no índice {0} não corresponde. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf index 0f448190b..c30665886 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - Элемент по индексу {0} не совпадает. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf index 8a4ff7a82..94d687505 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - {0} dizinindeki öğe eşleşmiyor. - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf index 8c6998130..b8eb16550 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - 索引 {0} 处的元素不匹配。 - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf index da2fc6697..0ecec48ae 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf @@ -73,9 +73,9 @@ - {0}({1}) - {0}({1}) - + {0}. {1} + {0}({1}) + String '{0}' does not contain string '{1}'. {2}. @@ -98,9 +98,13 @@ - Element at index {0} do not match. - 位於索引 {0} 的項目不符。 - + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {0} do not match. +Expected: {1} +Actual: {2} + Element at index {1} is not of expected type. Expected type:<{2}>. Actual type:<{3}>.{0} diff --git a/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs b/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs index 3be3175bc..908a0d6ec 100644 --- a/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs +++ b/test/UnitTests/TestFramework.UnitTests/Assertions/CollectionAssertTests.cs @@ -465,6 +465,28 @@ public class CollectionAssertTests : TestContainer Verify(ex.Message.Contains("message")); } + public void CollectionAssertAreEqualWithoutUserMessage_FailsWithGoodMessage() + { + Exception ex = VerifyThrows(() => CollectionAssert.AreEqual(new[] { 1, 2, 3 }, new[] { 1, 5, 3 })); + Assert.AreEqual( + """ + CollectionAssert.AreEqual failed. Element at index 1 do not match. + Expected: 2 + Actual: 5 + """, ex.Message); + } + + public void CollectionAssertAreEqualWithUserMessage_FailsWithGoodMessage() + { + Exception ex = VerifyThrows(() => CollectionAssert.AreEqual(new[] { 1, 2, 3 }, new[] { 1, 5, 3 }, "User-provided message")); + Assert.AreEqual( + """ + CollectionAssert.AreEqual failed. User-provided message. Element at index 1 do not match. + Expected: 2 + Actual: 5 + """, ex.Message); + } + #pragma warning disable CA1859 // Use concrete types when possible for improved performance private static List GenerateDeeplyNestedCollection(int depth)