Skip to content

Commit 44702ca

Browse files
authored
feat: add nunit collectionassert.isempty assertions (#341)
* feat: add nunit collectionassert.isempty assertions
1 parent 9433848 commit 44702ca

File tree

5 files changed

+71
-17
lines changed

5 files changed

+71
-17
lines changed

docs/NunitAnalyzer.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ var collection = new List<int>();
177177
// old assertion:
178178
Assert.IsEmpty(collection);
179179
Assert.That(collection, Is.Empty);
180+
CollectionAssert.IsEmpty(collection);
180181

181182
// new assertion:
182183
collection.Should().BeEmpty();
@@ -194,6 +195,9 @@ Assert.IsEmpty(collection); /* fail message: Expected: <empty>
194195
Assert.That(collection, Is.Empty); /* fail message: Expected: <empty>
195196
But was: < 1, 2, 3 >
196197
*/
198+
CollectionAssert.IsEmpty(collection); /* fail message: Expected: <empty>
199+
But was: < 1, 2, 3 >
200+
*/
197201

198202
// new assertion:
199203
collection.Should().BeEmpty(); /* fail message: Expected collection to be empty, but found {1, 2, 3}. */
@@ -208,6 +212,7 @@ var collection = new List<int> { 1, 2, 3 };
208212
// old assertion:
209213
Assert.IsNotEmpty(collection);
210214
Assert.That(collection, Is.Not.Empty);
215+
CollectionAssert.IsNotEmpty(collection);
211216

212217
// new assertion:
213218
collection.Should().NotBeEmpty();
@@ -225,6 +230,9 @@ Assert.IsNotEmpty(collection); /* fail message: Expected: not <empty>
225230
Assert.That(collection, Is.Not.Empty); /* fail message: Expected: not <empty>
226231
But was: <empty>
227232
*/
233+
CollectionAssert.IsNotEmpty(collection); /* fail message: Expected: not <empty>
234+
But was: <empty>
235+
*/
228236

229237
// new assertion:
230238
collection.Should().NotBeEmpty(); /* fail message: Expected collection not to be empty. */

src/FluentAssertions.Analyzers.FluentAssertionAnalyzerDocs/NunitAnalyzerTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using Assert = NUnit.Framework.Assert;
3+
using CollectionAssert = NUnit.Framework.CollectionAssert;
34
using System.Collections.Generic;
45
using NUnit.Framework;
56
using FluentAssertions;
@@ -271,6 +272,7 @@ public void AssertIsEmpty()
271272
// old assertion:
272273
Assert.IsEmpty(collection);
273274
Assert.That(collection, Is.Empty);
275+
CollectionAssert.IsEmpty(collection);
274276

275277
// new assertion:
276278
collection.Should().BeEmpty();
@@ -296,6 +298,16 @@ public void AssertIsEmpty_Failure_OldAssertion_1()
296298
Assert.That(collection, Is.Empty);
297299
}
298300

301+
[TestMethod, ExpectedTestFrameworkException]
302+
public void AssertIsEmpty_Failure_OldAssertion_2()
303+
{
304+
// arrange
305+
var collection = new List<int> { 1, 2, 3 };
306+
307+
// old assertion:
308+
CollectionAssert.IsEmpty(collection);
309+
}
310+
299311
[TestMethod, ExpectedTestFrameworkException]
300312
public void AssertIsEmpty_Failure_NewAssertion()
301313
{
@@ -315,6 +327,7 @@ public void AssertIsNotEmpty()
315327
// old assertion:
316328
Assert.IsNotEmpty(collection);
317329
Assert.That(collection, Is.Not.Empty);
330+
CollectionAssert.IsNotEmpty(collection);
318331

319332
// new assertion:
320333
collection.Should().NotBeEmpty();
@@ -340,6 +353,16 @@ public void AssertIsNotEmpty_Failure_OldAssertion_1()
340353
Assert.That(collection, Is.Not.Empty);
341354
}
342355

356+
[TestMethod, ExpectedTestFrameworkException]
357+
public void AssertIsNotEmpty_Failure_OldAssertion_2()
358+
{
359+
// arrange
360+
var collection = new List<int>();
361+
362+
// old assertion:
363+
CollectionAssert.IsNotEmpty(collection);
364+
}
365+
343366
[TestMethod, ExpectedTestFrameworkException]
344367
public void AssertIsNotEmpty_Failure_NewAssertion()
345368
{

src/FluentAssertions.Analyzers.Tests/Tips/NunitTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ public void Nunit4_AssertIsNaN_TestAnalyzer(string assertion)
272272
[DataTestMethod]
273273
[AssertionDiagnostic("Assert.IsEmpty(actual{0});")]
274274
[AssertionDiagnostic("Assert.That(actual, Is.Empty{0});")]
275+
[AssertionDiagnostic("CollectionAssert.IsEmpty(actual{0});")]
275276
[Implemented]
276277
public void Nunit3_AssertIsEmpty_TestAnalyzer(string assertion)
277278
{
@@ -284,6 +285,7 @@ public void Nunit3_AssertIsEmpty_TestAnalyzer(string assertion)
284285
[DataTestMethod]
285286
[AssertionDiagnostic("ClassicAssert.IsEmpty(actual{0});")]
286287
[AssertionDiagnostic("Assert.That(actual, Is.Empty);")]
288+
[AssertionDiagnostic("CollectionAssert.IsEmpty(actual{0});")]
287289
[Implemented]
288290
public void Nunit4_AssertIsEmpty_TestAnalyzer(string assertion)
289291
{
@@ -300,6 +302,9 @@ public void Nunit4_AssertIsEmpty_TestAnalyzer(string assertion)
300302
[AssertionCodeFix(
301303
oldAssertion: "Assert.That(actual, Is.Empty{0});",
302304
newAssertion: "actual.Should().BeEmpty({0});")]
305+
[AssertionCodeFix(
306+
oldAssertion: "CollectionAssert.IsEmpty(actual{0});",
307+
newAssertion: "actual.Should().BeEmpty({0});")]
303308
[Implemented]
304309
public void Nunit3_AssertIsEmpty_TestCodeFix(string oldAssertion, string newAssertion)
305310
{
@@ -316,6 +321,9 @@ public void Nunit3_AssertIsEmpty_TestCodeFix(string oldAssertion, string newAsse
316321
[AssertionCodeFix(
317322
oldAssertion: "Assert.That(actual, Is.Empty);",
318323
newAssertion: "actual.Should().BeEmpty();")]
324+
[AssertionCodeFix(
325+
oldAssertion: "CollectionAssert.IsEmpty(actual{0});",
326+
newAssertion: "actual.Should().BeEmpty({0});")]
319327
[Implemented]
320328
public void Nunit4_AssertIsEmpty_TestCodeFix(string oldAssertion, string newAssertion)
321329
{
@@ -329,6 +337,7 @@ public void Nunit4_AssertIsEmpty_TestCodeFix(string oldAssertion, string newAsse
329337
[DataTestMethod]
330338
[AssertionDiagnostic("Assert.IsNotEmpty(actual{0});")]
331339
[AssertionDiagnostic("Assert.That(actual, Is.Not.Empty{0});")]
340+
[AssertionDiagnostic("CollectionAssert.IsNotEmpty(actual{0});")]
332341
[Implemented]
333342
public void Nunit3_AssertIsNotEmpty_TestAnalyzer(string assertion)
334343
{
@@ -341,6 +350,7 @@ public void Nunit3_AssertIsNotEmpty_TestAnalyzer(string assertion)
341350
[DataTestMethod]
342351
[AssertionDiagnostic("ClassicAssert.IsNotEmpty(actual{0});")]
343352
[AssertionDiagnostic("Assert.That(actual, Is.Not.Empty);")]
353+
[AssertionDiagnostic("CollectionAssert.IsNotEmpty(actual{0});")]
344354
[Implemented]
345355
public void Nunit4_AssertIsNotEmpty_TestAnalyzer(string assertion)
346356
{
@@ -357,6 +367,9 @@ public void Nunit4_AssertIsNotEmpty_TestAnalyzer(string assertion)
357367
[AssertionCodeFix(
358368
oldAssertion: "Assert.That(actual, Is.Not.Empty{0});",
359369
newAssertion: "actual.Should().NotBeEmpty({0});")]
370+
[AssertionCodeFix(
371+
oldAssertion: "CollectionAssert.IsNotEmpty(actual{0});",
372+
newAssertion: "actual.Should().NotBeEmpty({0});")]
360373
[Implemented]
361374
public void Nunit3_AssertIsNotEmpty_TestCodeFix(string oldAssertion, string newAssertion)
362375
{
@@ -373,6 +386,9 @@ public void Nunit3_AssertIsNotEmpty_TestCodeFix(string oldAssertion, string newA
373386
[AssertionCodeFix(
374387
oldAssertion: "Assert.That(actual, Is.Not.Empty);",
375388
newAssertion: "actual.Should().NotBeEmpty();")]
389+
[AssertionCodeFix(
390+
oldAssertion: "CollectionAssert.IsNotEmpty(actual{0});",
391+
newAssertion: "actual.Should().NotBeEmpty({0});")]
376392
[Implemented]
377393
public void Nunit4_AssertIsNotEmpty_TestCodeFix(string oldAssertion, string newAssertion)
378394
{

src/FluentAssertions.Analyzers/Tips/AssertAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ private sealed class AnalyzerContext(Compilation compilation)
108108

109109
private readonly INamedTypeSymbol _nunitAssertionExceptionSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.AssertionException");
110110
private readonly INamedTypeSymbol _nunitAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.Assert");
111-
private readonly INamedTypeSymbol _nunitCollectionAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.CollectionAssert");
111+
private readonly INamedTypeSymbol _nunitCollectionAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.CollectionAssert") ?? compilation.GetTypeByMetadataName("NUnit.Framework.Legacy.CollectionAssert");
112112
private readonly INamedTypeSymbol _nunitDirectoryAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.DirectoryAssert");
113113
private readonly INamedTypeSymbol _nunitFileAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.FileAssert");
114114
private readonly INamedTypeSymbol _nunitStringAssertSymbol = compilation.GetTypeByMetadataName("NUnit.Framework.StringAssert");

src/FluentAssertions.Analyzers/Tips/NunitCodeFixProvider.cs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ protected override CreateChangedDocument TryComputeFixCore(IInvocationOperation
2828
"Assert" when invocation.TargetMethod.Name is "That" => TryComputeFixForNunitThat(invocation, context, t),
2929
"Assert" when isNunit3 => TryComputeFixForNunitClassicAssert(invocation, context, t),
3030
"ClassicAssert" when isNunit4 => TryComputeFixForNunitClassicAssert(invocation, context, t),
31-
//"StringAssert" => TryComputeFixForStringAssert(invocation, context, testContext),
32-
//"CollectionAssert" => TryComputeFixForCollectionAssert(invocation, context, testContext),
31+
//"StringAssert" => TryComputeFixForStringAssert(invocation, context, t),
32+
"CollectionAssert" => TryComputeFixForCollectionAssert(invocation, context, t),
3333
_ => null
3434
};
3535
}
@@ -52,17 +52,9 @@ private CreateChangedDocument TryComputeFixForNunitClassicAssert(IInvocationOper
5252
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", subjectIndex: 0, argumentsToRemove: []);
5353
case "IsNaN": // Assert.IsNaN(double actual)
5454
return null;
55-
case "IsEmpty": // Assert.IsEmpty(IEnumerable collection) | Assert.IsEmpty(string s)
56-
if (invocation.Arguments[0].Value.UnwrapConversion().Type.SpecialType is SpecialType.System_Collections_IEnumerable)
57-
{
58-
return null;
59-
}
55+
case "IsEmpty" when !IsArgumentTypeOfNonGenericEnumerable(invocation, argumentIndex: 0): // Assert.IsEmpty(IEnumerable collection) | Assert.IsEmpty(string s)
6056
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeEmpty", subjectIndex: 0, argumentsToRemove: []);
61-
case "IsNotEmpty": // Assert.IsNotEmpty(IEnumerable collection) | Assert.IsNotEmpty(string s)
62-
if (invocation.Arguments[0].Value.UnwrapConversion().Type.SpecialType is SpecialType.System_Collections_IEnumerable)
63-
{
64-
return null;
65-
}
57+
case "IsNotEmpty" when !IsArgumentTypeOfNonGenericEnumerable(invocation, argumentIndex: 0): // Assert.IsNotEmpty(IEnumerable collection) | Assert.IsNotEmpty(string s)
6658
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeEmpty", subjectIndex: 0, argumentsToRemove: []);
6759
case "Zero": // Assert.Zero(int anObject)
6860
return DocumentEditorUtils.RewriteExpression(invocation, [
@@ -231,13 +223,25 @@ private CreateChangedDocument TryComputeFixForNunitClassicAssert(IInvocationOper
231223
return null;
232224
}
233225

226+
private CreateChangedDocument TryComputeFixForCollectionAssert(IInvocationOperation invocation, CodeFixContext context, NunitCodeFixContext t)
227+
{
228+
switch (invocation.TargetMethod.Name)
229+
{
230+
case "IsEmpty" when !IsArgumentTypeOfNonGenericEnumerable(invocation, argumentIndex: 0): // CollectionAssert.IsEmpty(IEnumerable collection)
231+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeEmpty", subjectIndex: 0, argumentsToRemove: []);
232+
case "IsNotEmpty" when !IsArgumentTypeOfNonGenericEnumerable(invocation, argumentIndex: 0) : // CollectionAssert.IsNotEmpty(IEnumerable collection)
233+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeEmpty", subjectIndex: 0, argumentsToRemove: []);
234+
}
235+
return null;
236+
}
237+
234238
private CreateChangedDocument TryComputeFixForNunitThat(IInvocationOperation invocation, CodeFixContext context, NunitCodeFixContext t)
235239
{
236240
// Assert.That(condition)
237241
if (invocation.Arguments[0].Value.Type.EqualsSymbol(t.Boolean)
238-
&& (invocation.Arguments.Length is 1
239-
|| (invocation.Arguments.Length >= 2
240-
&& (invocation.Arguments[1].Value.Type.EqualsSymbol(t.NUnitString)
242+
&& (invocation.Arguments.Length is 1
243+
|| (invocation.Arguments.Length >= 2
244+
&& (invocation.Arguments[1].Value.Type.EqualsSymbol(t.NUnitString)
241245
|| invocation.Arguments[1].Value.Type.EqualsSymbol(t.String))
242246
)
243247
)
@@ -259,7 +263,7 @@ private CreateChangedDocument TryComputeFixForNunitThat(IInvocationOperation inv
259263
return RenameAssertThatAssertionToSubjectShouldAssertion("BeNull");
260264
else if (IsPropertyOfSymbol(constraint, "Not", "Null", t.Is)) // Assert.That(subject, Is.Not.Null)
261265
return RenameAssertThatAssertionToSubjectShouldAssertion("NotBeNull");
262-
else if (subject.Type.SpecialType is not SpecialType.System_Collections_IEnumerable)
266+
else if (!IsArgumentTypeOfNonGenericEnumerable(invocation, argumentIndex: 0))
263267
{
264268
if (IsPropertyOfSymbol(constraint, "Empty", t.Is)) // Assert.That(subject, Is.Empty)
265269
return RenameAssertThatAssertionToSubjectShouldAssertion("BeEmpty");
@@ -290,6 +294,9 @@ private static bool IsPropertyOfSymbol(IPropertyReferenceOperation propertyRefer
290294
private static bool IsPropertyOfSymbol(IOperation operation, string property, INamedTypeSymbol type)
291295
=> operation is IPropertyReferenceOperation propertyReference && propertyReference.Property.Name == property && IsPropertyReferencedFromType(propertyReference, type);
292296

297+
private static bool IsArgumentTypeOfNonGenericEnumerable(IInvocationOperation invocation, int argumentIndex) => IsArgumentTypeOf(invocation, argumentIndex, SpecialType.System_Collections_IEnumerable);
298+
private static bool IsArgumentTypeOf(IInvocationOperation invocation, int argumentIndex, SpecialType specialType)
299+
=> invocation.Arguments[argumentIndex].Value.UnwrapConversion().Type.SpecialType == specialType;
293300
public class NunitCodeFixContext(Compilation compilation) : TestingFrameworkCodeFixProvider.TestingFrameworkCodeFixContext(compilation)
294301
{
295302
public INamedTypeSymbol Is { get; } = compilation.GetTypeByMetadataName("NUnit.Framework.Is");

0 commit comments

Comments
 (0)