Skip to content

Commit

Permalink
Detect & fix inverted NUnit asserts
Browse files Browse the repository at this point in the history
  • Loading branch information
jairbubbles committed Dec 8, 2023
1 parent f83f98d commit 4bdd826
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -564,4 +564,68 @@ public void MyTest()
}
""");
}

[Theory]
[InlineData(@"ClassicAssert.AreEqual(test, 6)", @"test.Should().Be(6)")]
[InlineData(@"ClassicAssert.AreNotEqual(test, 6)", @"test.Should().NotBe(6)")]
[InlineData(@"ClassicAssert.AreEqual(test, ""test"")", @"test.Should().Be(""test"")")]
[InlineData(@"ClassicAssert.AreNotEqual(test, ""test"")", @"test.Should().NotBe(""test"")")]
public Task Assert_Inverted_Asserts(string code, string fix)
{
return Assert(
$$"""
using NUnit.Framework.Legacy;
class Test
{
public void MyTest(object test)
{
[|{{code}}|];
}
}
""",
$$"""
using FluentAssertions;
using NUnit.Framework.Legacy;
class Test
{
public void MyTest(object test)
{
{{fix}};
}
}
""");
}

[Theory]
[InlineData(@"ClassicAssert.AreEqual(test, 6.0, delta: 2.0)", @"test.Should().BeApproximately(6.0, 2.0)")]
[InlineData(@"ClassicAssert.AreEqual(test, 6.0)", @"test.Should().Be(6.0)")]
public Task Assert_Inverted_Asserts_double(string code, string fix)
{
return Assert(
$$"""
using NUnit.Framework.Legacy;
class Test
{
public void MyTest(double test)
{
[|{{code}}|];
}
}
""",
$$"""
using FluentAssertions;
using NUnit.Framework.Legacy;
class Test
{
public void MyTest(double test)
{
{{fix}};
}
}
""");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,17 @@ private static async Task<Document> Rewrite(Document document, SyntaxNode nodeTo
{
if (methodName is "AreEqual")
{
if (method.Parameters[0].Type.SpecialType == SpecialType.System_Double)
{
result = rewrite.UsingShould(arguments[1], "BeApproximately", ArgumentList(arguments[0], arguments.Skip(2)));
}
else
{
result = rewrite.UsingShould(arguments[1], "Be", ArgumentList(arguments[0], arguments.Skip(2)));
}
var (left, right) = GetLeftRight(arguments, semanticModel, cancellationToken);

var useBeApproximately = semanticModel.GetTypeInfo(left.Expression, cancellationToken).Type?.SpecialType == SpecialType.System_Double
&& arguments.FirstOrDefault(x => x.NameColon?.Name.Identifier.ValueText is "delta") is not null;

result = rewrite.UsingShould(right, useBeApproximately ? "BeApproximately" : "Be", ArgumentList(left, arguments.Skip(2)));
}
else if (methodName is "AreNotEqual")
{
result = rewrite.UsingShould(arguments[1], "NotBe", ArgumentList(arguments[0], arguments.Skip(2)));
var (left, right) = GetLeftRight(arguments, semanticModel, cancellationToken);
result = rewrite.UsingShould(right, "NotBe", ArgumentList(left, arguments.Skip(2)));
}
else if (methodName is "AreSame")
{
Expand Down Expand Up @@ -855,6 +854,28 @@ bool IsGenericMethod(out ITypeSymbol typeArgument, ITypeSymbol root, params stri
return document;
}

private static (ArgumentSyntax left, ArgumentSyntax right) GetLeftRight(SeparatedSyntaxList<ArgumentSyntax> arguments, SemanticModel semanticModel, CancellationToken cancellationToken)
{
var left = arguments[0];
var right = arguments[1];
var leftValue = semanticModel.GetConstantValue(left.Expression, cancellationToken);
var rightValue = semanticModel.GetConstantValue(right.Expression, cancellationToken);

// Don't invert if both are constant
if (leftValue.HasValue && rightValue.HasValue)
{
return (left, right);
}

// Invert if right is constant
if (rightValue.HasValue)
{
return (right, left);
}

return (left, right);
}

private static ITypeSymbol GetConstantTypeValue(SemanticModel semanticModel, ExpressionSyntax expression, CancellationToken cancellationToken)
{
var operation = semanticModel.GetOperation(expression, cancellationToken);
Expand Down

0 comments on commit 4bdd826

Please sign in to comment.