Skip to content

Commit e8faa6a

Browse files
authored
[rel/4.0] Complete caller argument expression for all assertions (#6329)
1 parent d4688d7 commit e8faa6a

32 files changed

+1036
-364
lines changed

src/TestFramework/TestFramework/Assertions/Assert.AreEqual.cs

Lines changed: 235 additions & 85 deletions
Large diffs are not rendered by default.

src/TestFramework/TestFramework/Assertions/Assert.AreSame.cs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
namespace Microsoft.VisualStudio.TestTools.UnitTesting;
77

8+
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
9+
810
/// <summary>
911
/// A collection of helper classes to test various conditions within
1012
/// unit tests. If the condition being tested is not met, an exception
@@ -32,10 +34,11 @@ public AssertAreSameInterpolatedStringHandler(int literalLength, int formattedCo
3234
}
3335
}
3436

35-
internal void ComputeAssertion()
37+
internal void ComputeAssertion(string expectedExpression, string actualExpression)
3638
{
3739
if (_builder is not null)
3840
{
41+
_builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "expected", expectedExpression, "actual", actualExpression) + " ");
3942
ThrowAssertAreSameFailed(_expected, _actual, _builder.ToString());
4043
}
4144
}
@@ -65,12 +68,10 @@ internal void ComputeAssertion()
6568

6669
public void AppendFormatted(string? value) => _builder!.Append(value);
6770

68-
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
6971
#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
7072
public void AppendFormatted(string? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value);
7173

7274
public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value);
73-
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
7475
#pragma warning restore RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
7576
}
7677

@@ -89,10 +90,11 @@ public AssertAreNotSameInterpolatedStringHandler(int literalLength, int formatte
8990
}
9091
}
9192

92-
internal void ComputeAssertion()
93+
internal void ComputeAssertion(string notExpectedExpression, string actualExpression)
9394
{
9495
if (_builder is not null)
9596
{
97+
_builder.Insert(0, string.Format(CultureInfo.CurrentCulture, FrameworkMessages.CallerArgumentExpressionTwoParametersMessage, "notExpected", notExpectedExpression, "actual", actualExpression) + " ");
9698
ThrowAssertAreNotSameFailed(_builder.ToString());
9799
}
98100
}
@@ -122,23 +124,20 @@ internal void ComputeAssertion()
122124

123125
public void AppendFormatted(string? value) => _builder!.Append(value);
124126

125-
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
126127
#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
127128
public void AppendFormatted(string? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value);
128129

129130
public void AppendFormatted(object? value, int alignment = 0, string? format = null) => _builder!.AppendFormat(null, $"{{0,{alignment}:{format}}}", value);
130-
#pragma warning restore RS0026 // Do not add multiple public overloads with optional parameters
131131
#pragma warning restore RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
132132
}
133133
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
134134

135-
/// <inheritdoc cref="AreSame{T}(T, T, string?)" />
135+
/// <inheritdoc cref="AreSame{T}(T, T, string?, string, string)" />
136136
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
137-
public static void AreSame<T>(T? expected, T? actual, [InterpolatedStringHandlerArgument(nameof(expected), nameof(actual))] ref AssertAreSameInterpolatedStringHandler<T> message)
137+
public static void AreSame<T>(T? expected, T? actual, [InterpolatedStringHandlerArgument(nameof(expected), nameof(actual))] ref AssertAreSameInterpolatedStringHandler<T> message, [CallerArgumentExpression(nameof(expected))] string expectedExpression = "", [CallerArgumentExpression(nameof(actual))] string actualExpression = "")
138138
#pragma warning restore IDE0060 // Remove unused parameter
139-
=> message.ComputeAssertion();
139+
=> message.ComputeAssertion(expectedExpression, actualExpression);
140140

141-
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters
142141
#pragma warning disable RS0027 // API with optional parameter(s) should have the most parameters amongst its public overloads
143142

144143
/// <summary>
@@ -159,18 +158,26 @@ public static void AreSame<T>(T? expected, T? actual, [InterpolatedStringHandler
159158
/// is not the same as <paramref name="expected"/>. The message is shown
160159
/// in test results.
161160
/// </param>
161+
/// <param name="expectedExpression">
162+
/// The syntactic expression of expected as given by the compiler via caller argument expression.
163+
/// Users shouldn't pass a value for this parameter.
164+
/// </param>
165+
/// <param name="actualExpression">
166+
/// The syntactic expression of actual as given by the compiler via caller argument expression.
167+
/// Users shouldn't pass a value for this parameter.
168+
/// </param>
162169
/// <exception cref="AssertFailedException">
163170
/// Thrown if <paramref name="expected"/> does not refer to the same object
164171
/// as <paramref name="actual"/>.
165172
/// </exception>
166-
public static void AreSame<T>(T? expected, T? actual, string message = "")
173+
public static void AreSame<T>(T? expected, T? actual, string message = "", [CallerArgumentExpression(nameof(expected))] string expectedExpression = "", [CallerArgumentExpression(nameof(actual))] string actualExpression = "")
167174
{
168175
if (!IsAreSameFailing(expected, actual))
169176
{
170177
return;
171178
}
172179

173-
string userMessage = BuildUserMessage(message);
180+
string userMessage = BuildUserMessageForExpectedExpressionAndActualExpression(message, expectedExpression, actualExpression);
174181
ThrowAssertAreSameFailed(expected, actual, userMessage);
175182
}
176183

@@ -192,11 +199,11 @@ private static void ThrowAssertAreSameFailed<T>(T? expected, T? actual, string u
192199
ThrowAssertFailed("Assert.AreSame", finalMessage);
193200
}
194201

195-
/// <inheritdoc cref="AreNotSame{T}(T, T, string?)" />
202+
/// <inheritdoc cref="AreNotSame{T}(T, T, string?, string, string)" />
196203
#pragma warning disable IDE0060 // Remove unused parameter - https://github.com/dotnet/roslyn/issues/76578
197-
public static void AreNotSame<T>(T? notExpected, T? actual, [InterpolatedStringHandlerArgument(nameof(notExpected), nameof(actual))] ref AssertAreNotSameInterpolatedStringHandler<T> message)
204+
public static void AreNotSame<T>(T? notExpected, T? actual, [InterpolatedStringHandlerArgument(nameof(notExpected), nameof(actual))] ref AssertAreNotSameInterpolatedStringHandler<T> message, [CallerArgumentExpression(nameof(notExpected))] string notExpectedExpression = "", [CallerArgumentExpression(nameof(actual))] string actualExpression = "")
198205
#pragma warning restore IDE0060 // Remove unused parameter
199-
=> message.ComputeAssertion();
206+
=> message.ComputeAssertion(notExpectedExpression, actualExpression);
200207

201208
/// <summary>
202209
/// Tests whether the specified objects refer to different objects and
@@ -217,15 +224,23 @@ public static void AreNotSame<T>(T? notExpected, T? actual, [InterpolatedStringH
217224
/// is the same as <paramref name="notExpected"/>. The message is shown in
218225
/// test results.
219226
/// </param>
227+
/// <param name="notExpectedExpression">
228+
/// The syntactic expression of notExpected as given by the compiler via caller argument expression.
229+
/// Users shouldn't pass a value for this parameter.
230+
/// </param>
231+
/// <param name="actualExpression">
232+
/// The syntactic expression of actual as given by the compiler via caller argument expression.
233+
/// Users shouldn't pass a value for this parameter.
234+
/// </param>
220235
/// <exception cref="AssertFailedException">
221236
/// Thrown if <paramref name="notExpected"/> refers to the same object
222237
/// as <paramref name="actual"/>.
223238
/// </exception>
224-
public static void AreNotSame<T>(T? notExpected, T? actual, string message = "")
239+
public static void AreNotSame<T>(T? notExpected, T? actual, string message = "", [CallerArgumentExpression(nameof(notExpected))] string notExpectedExpression = "", [CallerArgumentExpression(nameof(actual))] string actualExpression = "")
225240
{
226241
if (IsAreNotSameFailing(notExpected, actual))
227242
{
228-
ThrowAssertAreNotSameFailed(BuildUserMessage(message));
243+
ThrowAssertAreNotSameFailed(BuildUserMessageForNotExpectedExpressionAndActualExpression(message, notExpectedExpression, actualExpression));
229244
}
230245
}
231246

0 commit comments

Comments
 (0)