Partially improve CollectionAssert message (#4027)

This commit is contained in:
Youssef Victor 2024-11-19 15:21:47 +01:00 коммит произвёл GitHub
Родитель 1012c29696
Коммит 9cb5ec77a8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
17 изменённых файлов: 178 добавлений и 91 удалений

Просмотреть файл

@ -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);
}
/// <summary>
/// compares the objects using object.Equals.
/// </summary>

Просмотреть файл

@ -223,7 +223,7 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting {
}
/// <summary>
/// Looks up a localized string similar to {0}({1}).
/// Looks up a localized string similar to {0}. {1}.
/// </summary>
internal static string CollectionEqualReason {
get {
@ -340,7 +340,9 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting {
}
/// <summary>
/// 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}.
/// </summary>
internal static string ElementsAtIndexDontMatch {
get {

Просмотреть файл

@ -160,7 +160,7 @@
<value>Both collections contain the same elements. {0}</value>
</data>
<data name="CollectionEqualReason" xml:space="preserve">
<value>{0}({1})</value>
<value>{0}. {1}</value>
</data>
<data name="ContainsFail" xml:space="preserve">
<value>String '{0}' does not contain string '{1}'. {2}.</value>
@ -169,7 +169,9 @@
<value>The number of elements in the collections do not match. Expected:&lt;{1}&gt;. Actual:&lt;{2}&gt;.{0}</value>
</data>
<data name="ElementsAtIndexDontMatch" xml:space="preserve">
<value>Element at index {0} do not match.</value>
<value>Element at index {0} do not match.
Expected: {1}
Actual: {2}</value>
</data>
<data name="ElementTypesAtIndexDontMatch" xml:space="preserve">
<value>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</value>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">Element na indexu {0} nesouhlasí.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">Die Elemente bei Index "{0}" stimmen nicht überein.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">El elemento del índice {0} no coincide.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">Les éléments à l'index {0} ne correspondent pas.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">L'elemento alla posizione di indice {0} non corrisponde.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">インデックス {0} の要素が一致しません。</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">인덱스 {0}에 있는 요소가 일치하지 않습니다.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">Element w indeksie {0} nie jest zgodny.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">O elemento no índice {0} não corresponde.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">Элемент по индексу {0} не совпадает.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">{0} dizinindeki öğe eşleşmiyor.</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">索引 {0} 处的元素不匹配。</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -73,9 +73,9 @@
<note></note>
</trans-unit>
<trans-unit id="CollectionEqualReason">
<source>{0}({1})</source>
<target state="translated">{0}({1})</target>
<note></note>
<source>{0}. {1}</source>
<target state="needs-review-translation">{0}({1})</target>
<note />
</trans-unit>
<trans-unit id="ContainsFail">
<source>String '{0}' does not contain string '{1}'. {2}.</source>
@ -98,9 +98,13 @@
<note></note>
</trans-unit>
<trans-unit id="ElementsAtIndexDontMatch">
<source>Element at index {0} do not match.</source>
<target state="translated">位於索引 {0} 的項目不符。</target>
<note></note>
<source>Element at index {0} do not match.
Expected: {1}
Actual: {2}</source>
<target state="new">Element at index {0} do not match.
Expected: {1}
Actual: {2}</target>
<note />
</trans-unit>
<trans-unit id="ElementTypesAtIndexDontMatch">
<source>Element at index {1} is not of expected type. Expected type:&lt;{2}&gt;. Actual type:&lt;{3}&gt;.{0}</source>

Просмотреть файл

@ -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<object> GenerateDeeplyNestedCollection(int depth)