Skip to content

Commit

Permalink
Support classic StringAssert in ConstActualValueUsage code fix
Browse files Browse the repository at this point in the history
  • Loading branch information
David Nelson committed May 7, 2022
1 parent 47e5a14 commit 89bec5f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,56 @@ public void Test()

RoslynAssert.NoFix(analyzer, fix, expectedDiagnostic, code);
}

[TestCase(nameof(StringAssert.AreEqualIgnoringCase))]
[TestCase(nameof(StringAssert.AreNotEqualIgnoringCase))]
[TestCase(nameof(StringAssert.Contains))]
[TestCase(nameof(StringAssert.EndsWith))]
[TestCase(nameof(StringAssert.IsMatch))]
[TestCase(nameof(StringAssert.StartsWith))]
[TestCase(nameof(StringAssert.DoesNotContain))]
[TestCase(nameof(StringAssert.DoesNotMatch))]
[TestCase(nameof(StringAssert.DoesNotEndWith))]
[TestCase(nameof(StringAssert.DoesNotStartWith))]
public void LiteralArgumentIsProvidedForClassicStringAssertCodeFix(string classicAssertMethod)
{
var code = TestUtility.WrapMethodInClassNamespaceAndAddUsings($@"
public void Test()
{{
string actual = ""act"";
StringAssert.{classicAssertMethod}(actual, ↓""exp"");
}}");

var fixedCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings($@"
public void Test()
{{
string actual = ""act"";
StringAssert.{classicAssertMethod}(""exp"", actual);
}}");

RoslynAssert.CodeFix(analyzer, fix, expectedDiagnostic, code, fixedCode,
fixTitle: ConstActualValueUsageCodeFix.SwapArgumentsDescription);
}

[Test]
public void LiteralNamedArgumentIsProvidedForStringAssertContainsCodeFix()
{
var code = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@"
public void Test()
{
string actual = ""act"";
StringAssert.Contains(actual: ↓""exp"", expected: actual);
}");

var fixedCode = TestUtility.WrapMethodInClassNamespaceAndAddUsings(@"
public void Test()
{
string actual = ""act"";
StringAssert.Contains(actual: actual, expected: ""exp"");
}");

RoslynAssert.CodeFix(analyzer, fix, expectedDiagnostic, code, fixedCode,
fixTitle: ConstActualValueUsageCodeFix.SwapArgumentsDescription);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ public sealed class NUnitFrameworkConstantsTests
(nameof(NUnitFrameworkConstants.NameOfAssertThrowsAsync), nameof(Assert.ThrowsAsync)),

(nameof(NUnitFrameworkConstants.NameOfStringAssert), nameof(StringAssert)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertAreEqualIgnoringCase), nameof(StringAssert.AreEqualIgnoringCase)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertAreNotEqualIgnoringCase), nameof(StringAssert.AreNotEqualIgnoringCase)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertContains), nameof(StringAssert.Contains)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertDoesNotContain), nameof(StringAssert.DoesNotContain)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertDoesNotEndWith), nameof(StringAssert.DoesNotEndWith)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertDoesNotMatch), nameof(StringAssert.DoesNotMatch)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertDoesNotStartWith), nameof(StringAssert.DoesNotStartWith)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertEndsWith), nameof(StringAssert.EndsWith)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertIsMatch), nameof(StringAssert.IsMatch)),
(nameof(NUnitFrameworkConstants.NameOfStringAssertStartsWith), nameof(StringAssert.StartsWith)),

(nameof(NUnitFrameworkConstants.NameOfConstraint), nameof(Constraint)),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,21 @@ public class ConstActualValueUsageCodeFix : CodeFixProvider
NUnitFrameworkConstants.NameOfAssertAreEqual,
NUnitFrameworkConstants.NameOfAssertAreNotEqual,
NUnitFrameworkConstants.NameOfAssertAreSame,
NUnitFrameworkConstants.NameOfAssertAreNotSame
NUnitFrameworkConstants.NameOfAssertAreNotSame,
};

private static readonly string[] SupportedStringAsserts = new[]
{
NUnitFrameworkConstants.NameOfStringAssertAreEqualIgnoringCase,
NUnitFrameworkConstants.NameOfStringAssertAreNotEqualIgnoringCase,
NUnitFrameworkConstants.NameOfStringAssertContains,
NUnitFrameworkConstants.NameOfStringAssertDoesNotContain,
NUnitFrameworkConstants.NameOfStringAssertDoesNotEndWith,
NUnitFrameworkConstants.NameOfStringAssertDoesNotMatch,
NUnitFrameworkConstants.NameOfStringAssertDoesNotStartWith,
NUnitFrameworkConstants.NameOfStringAssertEndsWith,
NUnitFrameworkConstants.NameOfStringAssertIsMatch,
NUnitFrameworkConstants.NameOfStringAssertStartsWith,
};

private static readonly string[] SupportedIsConstraints = new[]
Expand Down Expand Up @@ -88,11 +102,12 @@ private static bool TryFindArguments(SemanticModel semanticModel, InvocationExpr

var methodSymbol = semanticModel.GetSymbolInfo(invocationSyntax).Symbol as IMethodSymbol;

if (methodSymbol is null || !methodSymbol.ContainingType.IsAssert())
if (methodSymbol is null || !methodSymbol.ContainingType.IsAnyAssert())
return false;

// option 1: Classic assert (e.g. Assert.AreEqual(expected, actual) )
if (SupportedClassicAsserts.Contains(methodSymbol.Name) && methodSymbol.Parameters.Length >= 2)
if ((IsSupportedAssert(methodSymbol) || IsSupportedStringAssert(methodSymbol))
&& methodSymbol.Parameters.Length >= 2)
{
expectedArgument = invocationSyntax.ArgumentList.Arguments[0].Expression;
actualArgument = invocationSyntax.ArgumentList.Arguments[1].Expression;
Expand Down Expand Up @@ -135,5 +150,15 @@ private static bool TryFindArguments(SemanticModel semanticModel, InvocationExpr

return false;
}

private static bool IsSupportedAssert(IMethodSymbol methodSymbol)
{
return methodSymbol.ContainingType.Name == NUnitFrameworkConstants.NameOfAssert && SupportedClassicAsserts.Contains(methodSymbol.Name);
}

private static bool IsSupportedStringAssert(IMethodSymbol methodSymbol)
{
return methodSymbol.ContainingType.Name == NUnitFrameworkConstants.NameOfStringAssert && SupportedStringAsserts.Contains(methodSymbol.Name);
}
}
}
10 changes: 10 additions & 0 deletions src/nunit.analyzers/Constants/NUnitFrameworkConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ public static class NUnitFrameworkConstants
public const string NameOfAssertThrowsAsync = "ThrowsAsync";

public const string NameOfStringAssert = "StringAssert";
public const string NameOfStringAssertAreEqualIgnoringCase = "AreEqualIgnoringCase";
public const string NameOfStringAssertAreNotEqualIgnoringCase = "AreNotEqualIgnoringCase";
public const string NameOfStringAssertContains = "Contains";
public const string NameOfStringAssertDoesNotContain = "DoesNotContain";
public const string NameOfStringAssertDoesNotEndWith = "DoesNotEndWith";
public const string NameOfStringAssertDoesNotMatch = "DoesNotMatch";
public const string NameOfStringAssertDoesNotStartWith = "DoesNotStartWith";
public const string NameOfStringAssertEndsWith = "EndsWith";
public const string NameOfStringAssertIsMatch = "IsMatch";
public const string NameOfStringAssertStartsWith = "StartsWith";

public const string FullNameOfTypeIs = "NUnit.Framework.Is";
public const string FullNameOfTypeTestCaseAttribute = "NUnit.Framework.TestCaseAttribute";
Expand Down

0 comments on commit 89bec5f

Please sign in to comment.