Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xunit: support for BooleanAsserts #131

Merged
merged 3 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/FluentAssertions.Analyzers.Tests/DiagnosticVerifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
using Microsoft.CodeAnalysis.CSharp;
using System.Reflection;

using XunitAssert = Xunit.Assert;

namespace FluentAssertions.Analyzers.Tests
{
/// <summary>
Expand All @@ -34,7 +36,8 @@ static DiagnosticVerifier()
typeof(Compilation), // Microsoft.CodeAnalysis
typeof(AssertionScope), // FluentAssertions.Core
typeof(AssertionExtensions), // FluentAssertions
typeof(Microsoft.VisualStudio.TestTools.UnitTesting.Assert) // MsTest
typeof(Microsoft.VisualStudio.TestTools.UnitTesting.Assert), // MsTest
typeof(XunitAssert), // Xunit
}.Select(type => type.GetTypeInfo().Assembly.Location)
.Append(GetSystemAssemblyPathByName("System.Globalization.dll"))
.Append(GetSystemAssemblyPathByName("System.Text.RegularExpressions.dll"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
<PackageReference Include="xunit.assert" Version="2.4.1" />
</ItemGroup>

<ItemGroup>
Expand Down
19 changes: 19 additions & 0 deletions src/FluentAssertions.Analyzers.Tests/GenerateCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,25 @@ public static string GenericIListExpressionBodyAssertion(string assertion) => Ge
.AppendLine("}")
.ToString();

public static string XunitAssertion(string methodArguments, string assertion) => new StringBuilder()
.AppendLine("using System;")
.AppendLine("using FluentAssertions;")
.AppendLine("using FluentAssertions.Extensions;")
.AppendLine("using Xunit;")
.AppendLine("using System.Threading.Tasks;")
.AppendLine("namespace TestNamespace")
.AppendLine("{")
.AppendLine(" class TestClass")
.AppendLine(" {")
.AppendLine($" void TestMethod({methodArguments})")
.AppendLine(" {")
.AppendLine($" {assertion}")
.AppendLine(" }")
.AppendLine(" }")
.AppendMainMethod()
.AppendLine("}")
.ToString();

private static StringBuilder AppendMainMethod(this StringBuilder builder) => builder
.AppendLine(" class Program")
.AppendLine(" {")
Expand Down
90 changes: 90 additions & 0 deletions src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using FluentAssertions.Analyzers.Xunit;

namespace FluentAssertions.Analyzers.Tests.Tips
{
[TestClass]
public class XunitTests
{
[DataTestMethod]
[DataRow("Assert.True(actual);")]
[DataRow("Assert.True(actual, \"because it's possible\");")]
[DataRow("Assert.True(bool.Parse(\"true\"));")]
[DataRow("Assert.True(bool.Parse(\"true\"), \"because it's possible\");")]
[Implemented]
public void AssertTrue_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertTrueAnalyzer>("bool actual", assertion);

[DataTestMethod]
[DataRow(
/* oldAssertion: */ "Assert.True(actual);",
/* newAssertion: */ "actual.Should().BeTrue();")]
[DataRow(
/* oldAssertion: */ "Assert.True(actual, \"because it's possible\");",
/* newAssertion: */ "actual.Should().BeTrue(\"because it's possible\");")]
[DataRow(
/* oldAssertion: */ "Assert.True(bool.Parse(\"true\"));",
/* newAssertion: */ "bool.Parse(\"true\").Should().BeTrue();")]
[DataRow(
/* oldAssertion: */ "Assert.True(bool.Parse(\"true\"), \"because it's possible\");",
/* newAssertion: */ "bool.Parse(\"true\").Should().BeTrue(\"because it's possible\");")]
[Implemented]
public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertTrueCodeFix, AssertTrueAnalyzer>("bool actual", oldAssertion, newAssertion);

[DataTestMethod]
[DataRow("Assert.False(actual);")]
[DataRow("Assert.False(actual, \"because it's possible\");")]
[DataRow("Assert.False(bool.Parse(\"false\"));")]
[DataRow("Assert.False(bool.Parse(\"false\"), \"because it's possible\");")]
[Implemented]
public void AssertFalse_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic<AssertFalseAnalyzer>("bool actual", assertion);

[DataTestMethod]
[DataRow(
/* oldAssertion: */ "Assert.False(actual);",
/* newAssertion: */ "actual.Should().BeFalse();")]
[DataRow(
/* oldAssertion: */ "Assert.False(actual, \"because it's possible\");",
/* newAssertion: */ "actual.Should().BeFalse(\"because it's possible\");")]
[DataRow(
/* oldAssertion: */ "Assert.False(bool.Parse(\"false\"));",
/* newAssertion: */ "bool.Parse(\"false\").Should().BeFalse();")]
[DataRow(
/* oldAssertion: */ "Assert.False(bool.Parse(\"false\"), \"because it's possible\");",
/* newAssertion: */ "bool.Parse(\"false\").Should().BeFalse(\"because it's possible\");")]
[Implemented]
public void AssertFalse_TestCodeFix(string oldAssertion, string newAssertion)
=> VerifyCSharpFix<AssertFalseCodeFix, AssertFalseAnalyzer>("bool actual", oldAssertion, newAssertion);

private void VerifyCSharpDiagnostic<TDiagnosticAnalyzer>(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
{
var source = GenerateCode.XunitAssertion(methodArguments, assertion);

var type = typeof(TDiagnosticAnalyzer);
var diagnosticId = (string)type.GetField("DiagnosticId").GetValue(null);
var message = (string)type.GetField("Message").GetValue(null);

DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(source, new DiagnosticResult
{
Id = diagnosticId,
Message = message,
Locations = new DiagnosticResultLocation[]
{
new DiagnosticResultLocation("Test0.cs", 12, 13)
},
Severity = DiagnosticSeverity.Info
});
}

private void VerifyCSharpFix<TCodeFixProvider, TDiagnosticAnalyzer>(string methodArguments, string oldAssertion, string newAssertion)
where TCodeFixProvider : Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider, new()
where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new()
{
var oldSource = GenerateCode.XunitAssertion(methodArguments, oldAssertion);
var newSource = GenerateCode.XunitAssertion(methodArguments, newAssertion);

DiagnosticVerifier.VerifyCSharpFix<TCodeFixProvider, TDiagnosticAnalyzer>(oldSource, newSource);
}
}
}
6 changes: 6 additions & 0 deletions src/FluentAssertions.Analyzers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ public static class MsTest
public const string CollectionAssertIsSubsetOf = nameof(CollectionAssertIsSubsetOf);
public const string CollectionAssertIsNotSubsetOf = nameof(CollectionAssertIsNotSubsetOf);
}

public static class Xunit
{
public const string AssertTrue = nameof(AssertTrue);
public const string AssertFalse = nameof(AssertFalse);
}
}

public static class CodeSmell
Expand Down
8 changes: 4 additions & 4 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreEqual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public AssertObjectAreEqualSyntaxVisitor() : base(new MemberValidator("AreEqual"
}

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

Expand All @@ -90,12 +90,12 @@ protected override async Task<ExpressionSyntax> GetNewExpressionAsync(Expression
{
case nameof(AssertAreEqualAnalyzer.AssertFloatAreEqualWithDeltaSyntaxVisitor):
case nameof(AssertAreEqualAnalyzer.AssertDoubleAreEqualWithDeltaSyntaxVisitor):
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "BeApproximately", "Assert");
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "BeApproximately");
case nameof(AssertAreEqualAnalyzer.AssertObjectAreEqualSyntaxVisitor):
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "Be", "Assert");
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreEqual", "Be");
case nameof(AssertAreEqualAnalyzer.AssertStringAreEqualSyntaxVisitor):
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreEqual", "Be", "BeEquivalentTo", "Assert");
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreEqual", "Be", "BeEquivalentTo");
default:
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public AssertObjectAreNotEqualSyntaxVisitor() : base(new MemberValidator("AreNot
}

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

Expand All @@ -91,12 +91,12 @@ protected override async Task<ExpressionSyntax> GetNewExpressionAsync(Expression
{
case nameof(AssertAreNotEqualAnalyzer.AssertFloatAreNotEqualWithDeltaSyntaxVisitor):
case nameof(AssertAreNotEqualAnalyzer.AssertDoubleAreNotEqualWithDeltaSyntaxVisitor):
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBeApproximately", "Assert");
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBeApproximately");
case nameof(AssertAreNotEqualAnalyzer.AssertObjectAreNotEqualSyntaxVisitor):
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBe", "Assert");
return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotEqual", "NotBe");
case nameof(AssertAreNotEqualAnalyzer.AssertStringAreNotEqualSyntaxVisitor):
var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreNotEqual", "NotBe", "NotBeEquivalentTo", "Assert");
return GetNewExpressionForAreNotEqualOrAreEqualStrings(expression, semanticModel, "AreNotEqual", "NotBe", "NotBeEquivalentTo");
default:
throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertAreNotSameSyntaxVisitor() : base(new MemberValidator("AreNotSame"))
}

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

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotSame", "NotBeSameAs", "Assert");
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreNotSame", "NotBeSameAs");
}
}
4 changes: 2 additions & 2 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertAreSame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertAreSameSyntaxVisitor() : base(new MemberValidator("AreSame"))
}

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

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreSame", "BeSameAs", "Assert");
=> RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "AreSame", "BeSameAs");
}
}
4 changes: 2 additions & 2 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertIsFalse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertIsFalseSyntaxVisitor() : base(new MemberValidator("IsFalse"))
}

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

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsFalse", "BeFalse", "Assert");
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsFalse", "BeFalse");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public AssertIsInstanceOfTypeSyntaxVisitor() : base(new MemberValidator("IsInsta
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsInstanceOfTypeCodeFix)), Shared]
public class AssertIsInstanceOfTypeCodeFix : MsTestCodeFixProvider
public class AssertIsInstanceOfTypeCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertIsInstanceOfTypeAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
{
var newExpression = RenameMethodAndReplaceWithSubjectShould(expression, "IsInstanceOfType", "BeOfType", "Assert");
var newExpression = RenameMethodAndReplaceWithSubjectShould(expression, "IsInstanceOfType", "BeOfType");

var beOfType = newExpression.DescendantNodes()
.OfType<MemberAccessExpressionSyntax>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public AssertIsNotInstanceOfTypeSyntaxVisitor() : base(new MemberValidator("IsNo
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsNotInstanceOfTypeCodeFix)), Shared]
public class AssertIsNotInstanceOfTypeCodeFix : MsTestCodeFixProvider
public class AssertIsNotInstanceOfTypeCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertIsNotInstanceOfTypeAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
{
var newExpression = RenameMethodAndReplaceWithSubjectShould(expression, "IsNotInstanceOfType", "NotBeOfType", "Assert");
var newExpression = RenameMethodAndReplaceWithSubjectShould(expression, "IsNotInstanceOfType", "NotBeOfType");

var beOfType = newExpression.DescendantNodes()
.OfType<MemberAccessExpressionSyntax>()
Expand Down
4 changes: 2 additions & 2 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertIsNotNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertIsNotNullSyntaxVisitor() : base(new MemberValidator("IsNotNull"))
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsNotNullCodeFix)), Shared]
public class AssertIsNotNullCodeFix : MsTestCodeFixProvider
public class AssertIsNotNullCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertIsNotNullAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsNotNull", "NotBeNull", "Assert");
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsNotNull", "NotBeNull");
}
}
4 changes: 2 additions & 2 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertIsNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertIsNullSyntaxVisitor() : base(new MemberValidator("IsNull"))
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsNullCodeFix)), Shared]
public class AssertIsNullCodeFix : MsTestCodeFixProvider
public class AssertIsNullCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertIsNullAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsNull", "BeNull", "Assert");
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsNull", "BeNull");
}
}
4 changes: 2 additions & 2 deletions src/FluentAssertions.Analyzers/Tips/MsTest/AssertIsTrue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertIsTrueSyntaxVisitor() : base(new MemberValidator("IsTrue"))
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsTrueCodeFix)), Shared]
public class AssertIsTrueCodeFix : MsTestCodeFixProvider
public class AssertIsTrueCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(CollectionShouldBeEmptyAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsTrue", "BeTrue", "Assert");
=> RenameMethodAndReplaceWithSubjectShould(expression, "IsTrue", "BeTrue");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public AssertThrowsExceptionSyntaxVisitor() : base(new MemberValidator("ThrowsEx
}

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertThrowsExceptionCodeFix)), Shared]
public class AssertThrowsExceptionCodeFix : MsTestCodeFixProvider
public class AssertThrowsExceptionCodeFix : MsTestAssertCodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(AssertThrowsExceptionAnalyzer.DiagnosticId);

protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties)
=> RenameMethodAndReplaceWithSubjectShould(expression, "ThrowsException", "ThrowExactly", "Assert");
=> RenameMethodAndReplaceWithSubjectShould(expression, "ThrowsException", "ThrowExactly");
}
}
Loading