Skip to content

Commit 799c193

Browse files
authored
xunit: support for BooleanAsserts (#131)
* add BooleanAsserts * add xunit to tests * introduce base codeFixer for testing libraries
1 parent 7a34a87 commit 799c193

38 files changed

+344
-83
lines changed

src/FluentAssertions.Analyzers.Tests/DiagnosticVerifier.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
using Microsoft.CodeAnalysis.CSharp;
1717
using System.Reflection;
1818

19+
using XunitAssert = Xunit.Assert;
20+
1921
namespace FluentAssertions.Analyzers.Tests
2022
{
2123
/// <summary>
@@ -34,7 +36,8 @@ static DiagnosticVerifier()
3436
typeof(Compilation), // Microsoft.CodeAnalysis
3537
typeof(AssertionScope), // FluentAssertions.Core
3638
typeof(AssertionExtensions), // FluentAssertions
37-
typeof(Microsoft.VisualStudio.TestTools.UnitTesting.Assert) // MsTest
39+
typeof(Microsoft.VisualStudio.TestTools.UnitTesting.Assert), // MsTest
40+
typeof(XunitAssert), // Xunit
3841
}.Select(type => type.GetTypeInfo().Assembly.Location)
3942
.Append(GetSystemAssemblyPathByName("System.Globalization.dll"))
4043
.Append(GetSystemAssemblyPathByName("System.Text.RegularExpressions.dll"))

src/FluentAssertions.Analyzers.Tests/FluentAssertions.Analyzers.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
1212
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
1313
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
14+
<PackageReference Include="xunit.assert" Version="2.4.1" />
1415
</ItemGroup>
1516

1617
<ItemGroup>

src/FluentAssertions.Analyzers.Tests/GenerateCode.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,25 @@ public static string GenericIListExpressionBodyAssertion(string assertion) => Ge
194194
.AppendLine("}")
195195
.ToString();
196196

197+
public static string XunitAssertion(string methodArguments, string assertion) => new StringBuilder()
198+
.AppendLine("using System;")
199+
.AppendLine("using FluentAssertions;")
200+
.AppendLine("using FluentAssertions.Extensions;")
201+
.AppendLine("using Xunit;")
202+
.AppendLine("using System.Threading.Tasks;")
203+
.AppendLine("namespace TestNamespace")
204+
.AppendLine("{")
205+
.AppendLine(" class TestClass")
206+
.AppendLine(" {")
207+
.AppendLine($" void TestMethod({methodArguments})")
208+
.AppendLine(" {")
209+
.AppendLine($" {assertion}")
210+
.AppendLine(" }")
211+
.AppendLine(" }")
212+
.AppendMainMethod()
213+
.AppendLine("}")
214+
.ToString();
215+
197216
private static StringBuilder AppendMainMethod(this StringBuilder builder) => builder
198217
.AppendLine(" class Program")
199218
.AppendLine(" {")
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using FluentAssertions.Analyzers.Xunit;
4+
5+
namespace FluentAssertions.Analyzers.Tests.Tips
6+
{
7+
[TestClass]
8+
public class XunitTests
9+
{
10+
[DataTestMethod]
11+
[DataRow("Assert.True(actual);")]
12+
[DataRow("Assert.True(actual, \"because it's possible\");")]
13+
[DataRow("Assert.True(bool.Parse(\"true\"));")]
14+
[DataRow("Assert.True(bool.Parse(\"true\"), \"because it's possible\");")]
15+
[Implemented]
16+
public void AssertTrue_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertTrueAnalyzer>("bool actual", assertion);
17+
18+
[DataTestMethod]
19+
[DataRow(
20+
/* oldAssertion: */ "Assert.True(actual);",
21+
/* newAssertion: */ "actual.Should().BeTrue();")]
22+
[DataRow(
23+
/* oldAssertion: */ "Assert.True(actual, \"because it's possible\");",
24+
/* newAssertion: */ "actual.Should().BeTrue(\"because it's possible\");")]
25+
[DataRow(
26+
/* oldAssertion: */ "Assert.True(bool.Parse(\"true\"));",
27+
/* newAssertion: */ "bool.Parse(\"true\").Should().BeTrue();")]
28+
[DataRow(
29+
/* oldAssertion: */ "Assert.True(bool.Parse(\"true\"), \"because it's possible\");",
30+
/* newAssertion: */ "bool.Parse(\"true\").Should().BeTrue(\"because it's possible\");")]
31+
[Implemented]
32+
public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion)
33+
=> VerifyCSharpFix<AssertTrueCodeFix, AssertTrueAnalyzer>("bool actual", oldAssertion, newAssertion);
34+
35+
[DataTestMethod]
36+
[DataRow("Assert.False(actual);")]
37+
[DataRow("Assert.False(actual, \"because it's possible\");")]
38+
[DataRow("Assert.False(bool.Parse(\"false\"));")]
39+
[DataRow("Assert.False(bool.Parse(\"false\"), \"because it's possible\");")]
40+
[Implemented]
41+
public void AssertFalse_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertFalseAnalyzer>("bool actual", assertion);
42+
43+
[DataTestMethod]
44+
[DataRow(
45+
/* oldAssertion: */ "Assert.False(actual);",
46+
/* newAssertion: */ "actual.Should().BeFalse();")]
47+
[DataRow(
48+
/* oldAssertion: */ "Assert.False(actual, \"because it's possible\");",
49+
/* newAssertion: */ "actual.Should().BeFalse(\"because it's possible\");")]
50+
[DataRow(
51+
/* oldAssertion: */ "Assert.False(bool.Parse(\"false\"));",
52+
/* newAssertion: */ "bool.Parse(\"false\").Should().BeFalse();")]
53+
[DataRow(
54+
/* oldAssertion: */ "Assert.False(bool.Parse(\"false\"), \"because it's possible\");",
55+
/* newAssertion: */ "bool.Parse(\"false\").Should().BeFalse(\"because it's possible\");")]
56+
[Implemented]
57+
public void AssertFalse_TestCodeFix(string oldAssertion, string newAssertion)
58+
=> VerifyCSharpFix<AssertFalseCodeFix, AssertFalseAnalyzer>("bool actual", oldAssertion, newAssertion);
59+
60+
private void VerifyCSharpDiagnostic<TDiagnosticAnalyzer>(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
61+
{
62+
var source = GenerateCode.XunitAssertion(methodArguments, assertion);
63+
64+
var type = typeof(TDiagnosticAnalyzer);
65+
var diagnosticId = (string)type.GetField("DiagnosticId").GetValue(null);
66+
var message = (string)type.GetField("Message").GetValue(null);
67+
68+
DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(source, new DiagnosticResult
69+
{
70+
Id = diagnosticId,
71+
Message = message,
72+
Locations = new DiagnosticResultLocation[]
73+
{
74+
new DiagnosticResultLocation("Test0.cs", 12, 13)
75+
},
76+
Severity = DiagnosticSeverity.Info
77+
});
78+
}
79+
80+
private void VerifyCSharpFix<TCodeFixProvider, TDiagnosticAnalyzer>(string methodArguments, string oldAssertion, string newAssertion)
81+
where TCodeFixProvider : Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider, new()
82+
where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
83+
{
84+
var oldSource = GenerateCode.XunitAssertion(methodArguments, oldAssertion);
85+
var newSource = GenerateCode.XunitAssertion(methodArguments, newAssertion);
86+
87+
DiagnosticVerifier.VerifyCSharpFix<TCodeFixProvider, TDiagnosticAnalyzer>(oldSource, newSource);
88+
}
89+
}
90+
}

src/FluentAssertions.Analyzers/Constants.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ public static class MsTest
115115
public const string CollectionAssertIsSubsetOf = nameof(CollectionAssertIsSubsetOf);
116116
public const string CollectionAssertIsNotSubsetOf = nameof(CollectionAssertIsNotSubsetOf);
117117
}
118+
119+
public static class Xunit
120+
{
121+
public const string AssertTrue = nameof(AssertTrue);
122+
public const string AssertFalse = nameof(AssertFalse);
123+
}
118124
}
119125

120126
public static class CodeSmell

src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreEqual.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public AssertObjectAreEqualSyntaxVisitor() : base(new MemberValidator("AreEqual"
8080
}
8181

8282
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertAreEqualCodeFix)), Shared]
83-
public class AssertAreEqualCodeFix : MsTestCodeFixProvider
83+
public class AssertAreEqualCodeFix : MsTestAssertCodeFixProvider
8484
{
8585
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertAreEqualAnalyzer.DiagnosticId);
8686

@@ -90,12 +90,12 @@ protected override async Task<ExpressionSyntax> GetNewExpressionAsync(Expression
9090
{
9191
case nameof(AssertAreEqualAnalyzer.AssertFloatAreEqualWithDeltaSyntaxVisitor):
9292
case nameof(AssertAreEqualAnalyzer.AssertDoubleAreEqualWithDeltaSyntaxVisitor):
93-
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "BeApproximately", "Assert");
93+
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "BeApproximately");
9494
case nameof(AssertAreEqualAnalyzer.AssertObjectAreEqualSyntaxVisitor):
95-
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "Be", "Assert");
95+
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "Be");
9696
case nameof(AssertAreEqualAnalyzer.AssertStringAreEqualSyntaxVisitor):
9797
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
98-
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreEqual", "Be", "BeEquivalentTo", "Assert");
98+
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreEqual", "Be", "BeEquivalentTo");
9999
default:
100100
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
101101
}

src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreNotEqual.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public AssertObjectAreNotEqualSyntaxVisitor() : base(new MemberValidator("AreNot
8181
}
8282

8383
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertAreNotEqualCodeFix)), Shared]
84-
public class AssertAreNotEqualCodeFix : MsTestCodeFixProvider
84+
public class AssertAreNotEqualCodeFix : MsTestAssertCodeFixProvider
8585
{
8686
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertAreNotEqualAnalyzer.DiagnosticId);
8787

@@ -91,12 +91,12 @@ protected override async Task<ExpressionSyntax> GetNewExpressionAsync(Expression
9191
{
9292
case nameof(AssertAreNotEqualAnalyzer.AssertFloatAreNotEqualWithDeltaSyntaxVisitor):
9393
case nameof(AssertAreNotEqualAnalyzer.AssertDoubleAreNotEqualWithDeltaSyntaxVisitor):
94-
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBeApproximately", "Assert");
94+
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBeApproximately");
9595
case nameof(AssertAreNotEqualAnalyzer.AssertObjectAreNotEqualSyntaxVisitor):
96-
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBe", "Assert");
96+
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBe");
9797
case nameof(AssertAreNotEqualAnalyzer.AssertStringAreNotEqualSyntaxVisitor):
9898
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
99-
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreNotEqual", "NotBe", "NotBeEquivalentTo", "Assert");
99+
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreNotEqual", "NotBe", "NotBeEquivalentTo");
100100
default:
101101
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
102102
}

src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreNotSame.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ public AssertAreNotSameSyntaxVisitor() : base(new MemberValidator("AreNotSame"))
3434
}
3535

3636
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertAreNotSameCodeFix)), Shared]
37-
public class AssertAreNotSameCodeFix : MsTestCodeFixProvider
37+
public class AssertAreNotSameCodeFix : MsTestAssertCodeFixProvider
3838
{
3939
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertAreNotSameAnalyzer.DiagnosticId);
4040

4141
protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
42-
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotSame", "NotBeSameAs", "Assert");
42+
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotSame", "NotBeSameAs");
4343
}
4444
}

src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreSame.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ public AssertAreSameSyntaxVisitor() : base(new MemberValidator("AreSame"))
3434
}
3535

3636
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertAreSameCodeFix)), Shared]
37-
public class AssertAreSameCodeFix : MsTestCodeFixProvider
37+
public class AssertAreSameCodeFix : MsTestAssertCodeFixProvider
3838
{
3939
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertAreSameAnalyzer.DiagnosticId);
4040

4141
protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
42-
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreSame", "BeSameAs", "Assert");
42+
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreSame", "BeSameAs");
4343
}
4444
}

src/FluentAssertions.Analyzers/Tips/MsTest/AssertIsFalse.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ public AssertIsFalseSyntaxVisitor() : base(new MemberValidator("IsFalse"))
3434
}
3535

3636
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsFalseCodeFix)), Shared]
37-
public class AssertIsFalseCodeFix : MsTestCodeFixProvider
37+
public class AssertIsFalseCodeFix : MsTestAssertCodeFixProvider
3838
{
3939
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeEmptyAnalyzer.DiagnosticId);
4040

4141
protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
42-
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsFalse", "BeFalse", "Assert");
42+
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsFalse", "BeFalse");
4343
}
4444
}

0 commit comments

Comments
 (0)