Skip to content

Commit 5481668

Browse files
authored
feat: nunit null assertions (#293)
* feat: add nunit null assertions
1 parent a5532be commit 5481668

File tree

3 files changed

+201
-20
lines changed

3 files changed

+201
-20
lines changed

src/FluentAssertions.Analyzers.TestUtils/GenerateCode.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,26 @@ public static string GenericIListExpressionBodyAssertion(string assertion) => Ge
254254
.AppendLine(" }")
255255
.AppendLine("}")
256256
.ToString();
257+
258+
public static string Nunit4Assertion(string methodArguments, string assertion) => new StringBuilder()
259+
.AppendLine("using System;")
260+
.AppendLine("using System.Collections.Generic;")
261+
.AppendLine("using System.Collections.Immutable;")
262+
.AppendLine("using System.Text.RegularExpressions;")
263+
.AppendLine("using FluentAssertions;")
264+
.AppendLine("using FluentAssertions.Extensions;")
265+
.AppendLine("using NUnit.Framework; using NUnit.Framework.Legacy;")
266+
.AppendLine("using System.Threading.Tasks;")
267+
.AppendLine("namespace TestNamespace")
268+
.AppendLine("{")
269+
.AppendLine(" class TestClass")
270+
.AppendLine(" {")
271+
.AppendLine($" void TestMethod({methodArguments})")
272+
.AppendLine(" {")
273+
.AppendLine($" {assertion}")
274+
.AppendLine(" }")
275+
.AppendLine(" }")
276+
.AppendLine("}")
277+
.ToString();
257278
}
258279
}

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

Lines changed: 142 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ public class NunitTests
1414
[AssertionDiagnostic("Assert.IsTrue(actual{0});")]
1515
[AssertionDiagnostic("Assert.IsTrue(bool.Parse(\"true\"){0});")]
1616
[Implemented]
17-
public void AssertTrue_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion);
17+
public void Nunit3_AssertTrue_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("bool actual", assertion);
18+
19+
[DataTestMethod]
20+
[AssertionDiagnostic("ClassicAssert.True(actual{0});")]
21+
[AssertionDiagnostic("ClassicAssert.True(bool.Parse(\"true\"){0});")]
22+
[AssertionDiagnostic("ClassicAssert.IsTrue(actual{0});")]
23+
[AssertionDiagnostic("ClassicAssert.IsTrue(bool.Parse(\"true\"){0});")]
24+
[Implemented]
25+
public void Nunit4_AssertTrue_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("bool actual", assertion);
1826

1927
[DataTestMethod]
2028
[AssertionCodeFix(
@@ -42,16 +50,51 @@ public class NunitTests
4250
oldAssertion: "Assert.IsTrue(actual == false{0});",
4351
newAssertion: "(actual == false).Should().BeTrue({0});")]
4452
[Implemented]
45-
public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion)
46-
=> VerifyCSharpFix("bool actual", oldAssertion, newAssertion);
53+
public void Nunit3_AssertTrue_TestCodeFix(string oldAssertion, string newAssertion) => Nunit3VerifyFix("bool actual", oldAssertion, newAssertion);
54+
55+
[DataTestMethod]
56+
[AssertionCodeFix(
57+
oldAssertion: "ClassicAssert.True(actual{0});",
58+
newAssertion: "actual.Should().BeTrue({0});")]
59+
[AssertionCodeFix(
60+
oldAssertion: "ClassicAssert.True(bool.Parse(\"true\"){0});",
61+
newAssertion: "bool.Parse(\"true\").Should().BeTrue({0});")]
62+
[AssertionCodeFix(
63+
oldAssertion: "ClassicAssert.True(!actual{0});",
64+
newAssertion: "(!actual).Should().BeTrue({0});")]
65+
[AssertionCodeFix(
66+
oldAssertion: "ClassicAssert.True(actual == false{0});",
67+
newAssertion: "(actual == false).Should().BeTrue({0});")]
68+
[AssertionCodeFix(
69+
oldAssertion: "ClassicAssert.IsTrue(actual{0});",
70+
newAssertion: "actual.Should().BeTrue({0});")]
71+
[AssertionCodeFix(
72+
oldAssertion: "ClassicAssert.IsTrue(bool.Parse(\"true\"){0});",
73+
newAssertion: "bool.Parse(\"true\").Should().BeTrue({0});")]
74+
[AssertionCodeFix(
75+
oldAssertion: "ClassicAssert.IsTrue(!actual{0});",
76+
newAssertion: "(!actual).Should().BeTrue({0});")]
77+
[AssertionCodeFix(
78+
oldAssertion: "ClassicAssert.IsTrue(actual == false{0});",
79+
newAssertion: "(actual == false).Should().BeTrue({0});")]
80+
[Implemented]
81+
public void Nunit4_AssertTrue_TestCodeFix(string oldAssertion, string newAssertion) => Nunit4VerifyFix("bool actual", oldAssertion, newAssertion);
4782

4883
[DataTestMethod]
4984
[AssertionDiagnostic("Assert.False(actual{0});")]
5085
[AssertionDiagnostic("Assert.False(bool.Parse(\"false\"){0});")]
5186
[AssertionDiagnostic("Assert.IsFalse(actual{0});")]
5287
[AssertionDiagnostic("Assert.IsFalse(bool.Parse(\"false\"){0});")]
5388
[Implemented]
54-
public void AssertFalse_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion);
89+
public void Nunit3_AssertFalse_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("bool actual", assertion);
90+
91+
[DataTestMethod]
92+
[AssertionDiagnostic("ClassicAssert.False(actual{0});")]
93+
[AssertionDiagnostic("ClassicAssert.False(bool.Parse(\"false\"){0});")]
94+
[AssertionDiagnostic("ClassicAssert.IsFalse(actual{0});")]
95+
[AssertionDiagnostic("ClassicAssert.IsFalse(bool.Parse(\"false\"){0});")]
96+
[Implemented]
97+
public void Nunit4_AssertFalse_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("bool actual", assertion);
5598

5699
[DataTestMethod]
57100
[AssertionCodeFix(
@@ -67,16 +110,104 @@ public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion)
67110
oldAssertion: "Assert.IsFalse(bool.Parse(\"false\"){0});",
68111
newAssertion: "bool.Parse(\"false\").Should().BeFalse({0});")]
69112
[Implemented]
70-
public void AssertFalse_TestCodeFix(string oldAssertion, string newAssertion)
71-
=> VerifyCSharpFix("bool actual", oldAssertion, newAssertion);
113+
public void Nunit3_AssertFalse_TestCodeFix(string oldAssertion, string newAssertion) => Nunit3VerifyFix("bool actual", oldAssertion, newAssertion);
114+
115+
[DataTestMethod]
116+
[AssertionCodeFix(
117+
oldAssertion: "ClassicAssert.False(actual{0});",
118+
newAssertion: "actual.Should().BeFalse({0});")]
119+
[AssertionCodeFix(
120+
oldAssertion: "ClassicAssert.False(bool.Parse(\"false\"){0});",
121+
newAssertion: "bool.Parse(\"false\").Should().BeFalse({0});")]
122+
[AssertionCodeFix(
123+
oldAssertion: "ClassicAssert.IsFalse(actual{0});",
124+
newAssertion: "actual.Should().BeFalse({0});")]
125+
[AssertionCodeFix(
126+
oldAssertion: "ClassicAssert.IsFalse(bool.Parse(\"false\"){0});",
127+
newAssertion: "bool.Parse(\"false\").Should().BeFalse({0});")]
128+
[Implemented]
129+
public void Nunit4_AssertFalse_TestCodeFix(string oldAssertion, string newAssertion) => Nunit4VerifyFix("bool actual", oldAssertion, newAssertion);
72130

73-
private void VerifyCSharpDiagnostic(string methodArguments, string assertion)
131+
[DataTestMethod]
132+
[AssertionDiagnostic("Assert.Null(actual{0});")]
133+
[AssertionDiagnostic("Assert.IsNull(actual{0});")]
134+
[Implemented]
135+
public void Nunit3_AssertNull_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("object actual", assertion);
136+
137+
[DataTestMethod]
138+
[AssertionDiagnostic("ClassicAssert.Null(actual{0});")]
139+
[AssertionDiagnostic("ClassicAssert.IsNull(actual{0});")]
140+
[Implemented]
141+
public void Nunit4_AssertNull_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("object actual", assertion);
142+
143+
[DataTestMethod]
144+
[AssertionCodeFix(
145+
oldAssertion: "Assert.Null(actual{0});",
146+
newAssertion: "actual.Should().BeNull({0});")]
147+
[AssertionCodeFix(
148+
oldAssertion: "Assert.IsNull(actual{0});",
149+
newAssertion: "actual.Should().BeNull({0});")]
150+
[Implemented]
151+
public void Nunit3_AssertNull_TestCodeFix(string oldAssertion, string newAssertion) => Nunit3VerifyFix("object actual", oldAssertion, newAssertion);
152+
153+
[DataTestMethod]
154+
[AssertionCodeFix(
155+
oldAssertion: "ClassicAssert.Null(actual{0});",
156+
newAssertion: "actual.Should().BeNull({0});")]
157+
[AssertionCodeFix(
158+
oldAssertion: "ClassicAssert.IsNull(actual{0});",
159+
newAssertion: "actual.Should().BeNull({0});")]
160+
[Implemented]
161+
public void Nunit4_AssertNull_TestCodeFix(string oldAssertion, string newAssertion) => Nunit4VerifyFix("object actual", oldAssertion, newAssertion);
162+
163+
[DataTestMethod]
164+
[AssertionDiagnostic("Assert.NotNull(actual{0});")]
165+
[AssertionDiagnostic("Assert.IsNotNull(actual{0});")]
166+
[Implemented]
167+
public void Nunit3_AssertNotNull_TestAnalyzer(string assertion) => Nunit3VerifyDiagnostic("object actual", assertion);
168+
169+
[DataTestMethod]
170+
[AssertionDiagnostic("ClassicAssert.NotNull(actual{0});")]
171+
[AssertionDiagnostic("ClassicAssert.IsNotNull(actual{0});")]
172+
[Implemented]
173+
public void Nunit4_AssertNotNull_TestAnalyzer(string assertion) => Nunit4VerifyDiagnostic("object actual", assertion);
174+
175+
[DataTestMethod]
176+
[AssertionCodeFix(
177+
oldAssertion: "Assert.NotNull(actual{0});",
178+
newAssertion: "actual.Should().NotBeNull({0});")]
179+
[AssertionCodeFix(
180+
oldAssertion: "Assert.IsNotNull(actual{0});",
181+
newAssertion: "actual.Should().NotBeNull({0});")]
182+
[Implemented]
183+
public void Nunit3_AssertNotNull_TestCodeFix(string oldAssertion, string newAssertion) => Nunit3VerifyFix("object actual", oldAssertion, newAssertion);
184+
185+
[DataTestMethod]
186+
[AssertionCodeFix(
187+
oldAssertion: "ClassicAssert.NotNull(actual{0});",
188+
newAssertion: "actual.Should().NotBeNull({0});")]
189+
[AssertionCodeFix(
190+
oldAssertion: "ClassicAssert.IsNotNull(actual{0});",
191+
newAssertion: "actual.Should().NotBeNull({0});")]
192+
[Implemented]
193+
public void Nunit4_AssertNotNull_TestCodeFix(string oldAssertion, string newAssertion) => Nunit4VerifyFix("object actual", oldAssertion, newAssertion);
194+
195+
private void Nunit3VerifyDiagnostic(string methodArguments, string assertion)
196+
=> VerifyDiagnostic(GenerateCode.Nunit3Assertion(methodArguments, assertion), PackageReference.Nunit_3_14_0);
197+
private void Nunit3VerifyFix(string methodArguments, string oldAssertion, string newAssertion)
198+
=> VerifyFix(GenerateCode.Nunit3Assertion(methodArguments, oldAssertion), GenerateCode.Nunit3Assertion(methodArguments, newAssertion), PackageReference.Nunit_3_14_0);
199+
200+
private void Nunit4VerifyDiagnostic(string methodArguments, string assertion)
201+
=> VerifyDiagnostic(GenerateCode.Nunit4Assertion(methodArguments, assertion), PackageReference.Nunit_4_0_1);
202+
private void Nunit4VerifyFix(string methodArguments, string oldAssertion, string newAssertion)
203+
=> VerifyFix(GenerateCode.Nunit4Assertion(methodArguments, oldAssertion), GenerateCode.Nunit4Assertion(methodArguments, newAssertion), PackageReference.Nunit_4_0_1);
204+
205+
private void VerifyDiagnostic(string source, PackageReference nunit)
74206
{
75-
var source = GenerateCode.Nunit3Assertion(methodArguments, assertion);
76207
DiagnosticVerifier.VerifyDiagnostic(new DiagnosticVerifierArguments()
77208
.WithAllAnalyzers()
78209
.WithSources(source)
79-
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.Nunit_3_14_0)
210+
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, nunit)
80211
.WithExpectedDiagnostics(new DiagnosticResult
81212
{
82213
Id = AssertAnalyzer.NUnitRule.Id,
@@ -90,17 +221,14 @@ private void VerifyCSharpDiagnostic(string methodArguments, string assertion)
90221
);
91222
}
92223

93-
private void VerifyCSharpFix(string methodArguments, string oldAssertion, string newAssertion)
224+
private void VerifyFix(string oldSource, string newSource, PackageReference nunit)
94225
{
95-
var oldSource = GenerateCode.Nunit3Assertion(methodArguments, oldAssertion);
96-
var newSource = GenerateCode.Nunit3Assertion(methodArguments, newAssertion);
97-
98226
DiagnosticVerifier.VerifyFix(new CodeFixVerifierArguments()
99227
.WithDiagnosticAnalyzer<AssertAnalyzer>()
100228
.WithCodeFixProvider<NunitCodeFixProvider>()
101229
.WithSources(oldSource)
102230
.WithFixedSources(newSource)
103-
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.Nunit_3_14_0)
231+
.WithPackageReferences(PackageReference.FluentAssertions_6_12_0, nunit)
104232
);
105233
}
106234
}

src/FluentAssertions.Analyzers/Tips/NunitCodeFixProvider.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,58 @@ public class NunitCodeFixProvider : TestingFrameworkCodeFixProvider
1515
protected override CreateChangedDocument TryComputeFixCore(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t, Diagnostic diagnostic)
1616
{
1717
var assertType = invocation.TargetMethod.ContainingType;
18+
var nunitVersion = assertType.ContainingAssembly.Identity.Version;
19+
20+
var isNunit3 = nunitVersion >= new Version(3, 0, 0, 0) && nunitVersion < new Version(4, 0, 0, 0);
21+
var isNunit4 = nunitVersion >= new Version(4, 0, 0, 0) && nunitVersion < new Version(5, 0, 0, 0);
22+
1823
return assertType.Name switch
1924
{
20-
"Assert" => TryComputeFixForAssert(invocation, context, t),
25+
"Assert" when isNunit3 => TryComputeFixForNunit3Assert(invocation, context, t),
26+
"ClassicAssert" when isNunit4 => TryComputeFixForNunit4ClassicAssert(invocation, context, t),
2127
//"StringAssert" => TryComputeFixForStringAssert(invocation, context, testContext),
2228
//"CollectionAssert" => TryComputeFixForCollectionAssert(invocation, context, testContext),
2329
_ => null
2430
};
2531
}
2632

27-
private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t)
33+
private CreateChangedDocument TryComputeFixForNunit3Assert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t)
2834
{
2935
switch (invocation.TargetMethod.Name)
3036
{
31-
case "True":
32-
case "IsTrue":
37+
case "True": // Assert.True(bool condition)
38+
case "IsTrue": // Assert.IsTrue(bool condition)
3339
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeTrue", subjectIndex: 0, argumentsToRemove: []);
40+
case "False": // Assert.False(bool condition)
41+
case "IsFalse": // Assert.IsFalse(bool condition)
42+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeFalse", subjectIndex: 0, argumentsToRemove: []);
43+
case "Null": // Assert.Null(object anObject)
44+
case "IsNull": // Assert.IsNull(object anObject)
45+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", subjectIndex: 0, argumentsToRemove: []);
46+
case "NotNull": // Assert.NotNull(object anObject)
47+
case "IsNotNull": // Assert.IsNotNull(object anObject)
48+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", subjectIndex: 0, argumentsToRemove: []);
49+
}
50+
51+
return null;
52+
}
3453

35-
case "False":
36-
case "IsFalse":
54+
private CreateChangedDocument TryComputeFixForNunit4ClassicAssert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t)
55+
{
56+
switch (invocation.TargetMethod.Name)
57+
{
58+
case "True": // Assert.True(bool condition)
59+
case "IsTrue": // Assert.IsTrue(bool condition)
60+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeTrue", subjectIndex: 0, argumentsToRemove: []);
61+
case "False": // Assert.False(bool condition)
62+
case "IsFalse": // Assert.IsFalse(bool condition)
3763
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeFalse", subjectIndex: 0, argumentsToRemove: []);
64+
case "Null": // Assert.Null(object anObject)
65+
case "IsNull": // Assert.IsNull(object anObject)
66+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", subjectIndex: 0, argumentsToRemove: []);
67+
case "NotNull": // Assert.NotNull(object anObject)
68+
case "IsNotNull": // Assert.IsNotNull(object anObject)
69+
return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", subjectIndex: 0, argumentsToRemove: []);
3870
}
3971

4072
return null;

0 commit comments

Comments
 (0)