Skip to content
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
8 changes: 4 additions & 4 deletions TUnit.Analyzers.CodeFixers/MSTestMigrationCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,13 @@ protected override bool IsFrameworkAssertionNamespace(string namespaceName)
"AreEqual" => ConvertAreEqual(arguments),
"AreNotEqual" => ConvertAreNotEqual(arguments),
"AreSame" when arguments.Count >= 3 =>
CreateTUnitAssertionWithMessage("IsSameReference", arguments[1].Expression, arguments[2].Expression, arguments[0]),
CreateTUnitAssertionWithMessage("IsSameReferenceAs", arguments[1].Expression, arguments[2].Expression, arguments[0]),
"AreSame" when arguments.Count >= 2 =>
CreateTUnitAssertion("IsSameReference", arguments[1].Expression, arguments[0]),
CreateTUnitAssertion("IsSameReferenceAs", arguments[1].Expression, arguments[0]),
"AreNotSame" when arguments.Count >= 3 =>
CreateTUnitAssertionWithMessage("IsNotSameReference", arguments[1].Expression, arguments[2].Expression, arguments[0]),
CreateTUnitAssertionWithMessage("IsNotSameReferenceAs", arguments[1].Expression, arguments[2].Expression, arguments[0]),
"AreNotSame" when arguments.Count >= 2 =>
CreateTUnitAssertion("IsNotSameReference", arguments[1].Expression, arguments[0]),
CreateTUnitAssertion("IsNotSameReferenceAs", arguments[1].Expression, arguments[0]),

// 1-arg assertions with message as 2nd param
"IsTrue" when arguments.Count >= 2 =>
Expand Down
124 changes: 118 additions & 6 deletions TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,20 @@ protected override bool IsFrameworkAssertionNamespace(string namespaceName)
return ConvertDirectoryAssertion(invocation, directoryAccess.Name.Identifier.Text);
}

// Handle CollectionAssert
if (invocation.Expression is MemberAccessExpressionSyntax collectionAccess &&
collectionAccess.Expression is IdentifierNameSyntax { Identifier.Text: "CollectionAssert" })
{
return ConvertCollectionAssertion(invocation, collectionAccess.Name.Identifier.Text);
}

// Handle StringAssert
if (invocation.Expression is MemberAccessExpressionSyntax stringAccess &&
stringAccess.Expression is IdentifierNameSyntax { Identifier.Text: "StringAssert" })
{
return ConvertStringAssertion(invocation, stringAccess.Name.Identifier.Text);
}

if (!IsFrameworkAssertion(invocation))
{
return null;
Expand Down Expand Up @@ -761,9 +775,9 @@ exactlyInvocation.Expression is MemberAccessExpressionSyntax exactlyMemberAccess
{
return memberName switch
{
"Ascending" => CreateTUnitAssertionWithMessage("IsInAscendingOrder", actualValue, message),
"Ascending" => CreateTUnitAssertionWithMessage("IsInOrder", actualValue, message),
"Descending" => CreateTUnitAssertionWithMessage("IsInDescendingOrder", actualValue, message),
_ => CreateTUnitAssertionWithMessage("IsInAscendingOrder", actualValue, message) // Default to ascending for Is.Ordered
_ => CreateTUnitAssertionWithMessage("IsInOrder", actualValue, message) // Default to ascending for Is.Ordered
};
}

Expand Down Expand Up @@ -797,7 +811,7 @@ exactlyInvocation.Expression is MemberAccessExpressionSyntax exactlyMemberAccess
"Zero" => CreateTUnitAssertionWithMessage("IsZero", actualValue, message),
"NaN" => CreateTUnitAssertionWithMessage("IsNaN", actualValue, message),
"Unique" => CreateTUnitAssertionWithMessage("HasDistinctItems", actualValue, message),
"Ordered" => CreateTUnitAssertionWithMessage("IsInAscendingOrder", actualValue, message),
"Ordered" => CreateTUnitAssertionWithMessage("IsInOrder", actualValue, message),
_ => CreateTUnitAssertionWithMessage("IsEqualTo", actualValue, message, SyntaxFactory.Argument(constraint))
};
}
Expand Down Expand Up @@ -963,9 +977,9 @@ exactlyInvocation.Expression is MemberAccessExpressionSyntax exactlyMemberAccess
{
return memberName switch
{
"Ascending" => CreateTUnitAssertion("IsInAscendingOrder", actualValue),
"Ascending" => CreateTUnitAssertion("IsInOrder", actualValue),
"Descending" => CreateTUnitAssertion("IsInDescendingOrder", actualValue),
_ => CreateTUnitAssertion("IsInAscendingOrder", actualValue) // Default to ascending for Is.Ordered
_ => CreateTUnitAssertion("IsInOrder", actualValue) // Default to ascending for Is.Ordered
};
}

Expand Down Expand Up @@ -999,7 +1013,7 @@ exactlyInvocation.Expression is MemberAccessExpressionSyntax exactlyMemberAccess
"Zero" => CreateTUnitAssertion("IsZero", actualValue),
"NaN" => CreateTUnitAssertion("IsNaN", actualValue),
"Unique" => CreateTUnitAssertion("HasDistinctItems", actualValue),
"Ordered" => CreateTUnitAssertion("IsInAscendingOrder", actualValue),
"Ordered" => CreateTUnitAssertion("IsInOrder", actualValue),
_ => CreateTUnitAssertion("IsEqualTo", actualValue, SyntaxFactory.Argument(constraint))
};
}
Expand Down Expand Up @@ -1665,6 +1679,104 @@ private static ExpressionSyntax CreateDirectoryInfoExpression(ExpressionSyntax p
return pathOrDirectoryInfo;
}

private ExpressionSyntax? ConvertCollectionAssertion(InvocationExpressionSyntax invocation, string methodName)
{
var arguments = invocation.ArgumentList.Arguments;

// CollectionAssert methods - note the argument order varies by method
return methodName switch
{
// CollectionAssert.AreEqual(expected, actual) -> Assert.That(actual).IsEquivalentTo(expected)
"AreEqual" when arguments.Count >= 2 => CreateTUnitAssertion("IsEquivalentTo", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// CollectionAssert.AreNotEqual(expected, actual) -> Assert.That(actual).IsNotEquivalentTo(expected)
"AreNotEqual" when arguments.Count >= 2 => CreateTUnitAssertion("IsNotEquivalentTo", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// CollectionAssert.AreEquivalent(expected, actual) -> Assert.That(actual).IsEquivalentTo(expected)
"AreEquivalent" when arguments.Count >= 2 => CreateTUnitAssertion("IsEquivalentTo", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// CollectionAssert.AreNotEquivalent(expected, actual) -> Assert.That(actual).IsNotEquivalentTo(expected)
"AreNotEquivalent" when arguments.Count >= 2 => CreateTUnitAssertion("IsNotEquivalentTo", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// CollectionAssert.Contains(collection, item) -> Assert.That(collection).Contains(item)
"Contains" when arguments.Count >= 2 => CreateTUnitAssertion("Contains", arguments[0].Expression, SyntaxFactory.Argument(arguments[1].Expression)),
// CollectionAssert.DoesNotContain(collection, item) -> Assert.That(collection).DoesNotContain(item)
"DoesNotContain" when arguments.Count >= 2 => CreateTUnitAssertion("DoesNotContain", arguments[0].Expression, SyntaxFactory.Argument(arguments[1].Expression)),
// CollectionAssert.IsEmpty(collection) -> Assert.That(collection).IsEmpty()
"IsEmpty" when arguments.Count >= 1 => CreateTUnitAssertion("IsEmpty", arguments[0].Expression),
// CollectionAssert.IsNotEmpty(collection) -> Assert.That(collection).IsNotEmpty()
"IsNotEmpty" when arguments.Count >= 1 => CreateTUnitAssertion("IsNotEmpty", arguments[0].Expression),
// CollectionAssert.AllItemsAreUnique(collection) -> Assert.That(collection).HasDistinctItems()
"AllItemsAreUnique" when arguments.Count >= 1 => CreateTUnitAssertion("HasDistinctItems", arguments[0].Expression),
// CollectionAssert.IsOrdered(collection) -> Assert.That(collection).IsInOrder()
"IsOrdered" when arguments.Count >= 1 => CreateTUnitAssertion("IsInOrder", arguments[0].Expression),
// CollectionAssert.IsSubsetOf(subset, superset) -> Assert.That(subset).IsSubsetOf(superset)
"IsSubsetOf" when arguments.Count >= 2 => CreateTUnitAssertion("IsSubsetOf", arguments[0].Expression, SyntaxFactory.Argument(arguments[1].Expression)),
// CollectionAssert.IsSupersetOf(superset, subset) -> Assert.That(superset).IsSupersetOf(subset)
"IsSupersetOf" when arguments.Count >= 2 => CreateTUnitAssertion("IsSupersetOf", arguments[0].Expression, SyntaxFactory.Argument(arguments[1].Expression)),
// CollectionAssert.AllItemsAreNotNull(collection) -> Assert.That(collection).DoesNotContain(null)
"AllItemsAreNotNull" when arguments.Count >= 1 => CreateTUnitAssertion("DoesNotContain", arguments[0].Expression, SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression))),
_ => null
};
}

private ExpressionSyntax? ConvertStringAssertion(InvocationExpressionSyntax invocation, string methodName)
{
var arguments = invocation.ArgumentList.Arguments;

// StringAssert methods - note: NUnit uses (expected, actual) order
return methodName switch
{
// StringAssert.Contains(expected, actual) -> Assert.That(actual).Contains(expected)
"Contains" when arguments.Count >= 2 => CreateTUnitAssertion("Contains", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.DoesNotContain(expected, actual) -> Assert.That(actual).DoesNotContain(expected)
"DoesNotContain" when arguments.Count >= 2 => CreateTUnitAssertion("DoesNotContain", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.StartsWith(expected, actual) -> Assert.That(actual).StartsWith(expected)
"StartsWith" when arguments.Count >= 2 => CreateTUnitAssertion("StartsWith", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.DoesNotStartWith(expected, actual) -> Assert.That(actual).DoesNotStartWith(expected)
"DoesNotStartWith" when arguments.Count >= 2 => CreateTUnitAssertion("DoesNotStartWith", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.EndsWith(expected, actual) -> Assert.That(actual).EndsWith(expected)
"EndsWith" when arguments.Count >= 2 => CreateTUnitAssertion("EndsWith", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.DoesNotEndWith(expected, actual) -> Assert.That(actual).DoesNotEndWith(expected)
"DoesNotEndWith" when arguments.Count >= 2 => CreateTUnitAssertion("DoesNotEndWith", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.IsMatch(pattern, actual) -> Assert.That(actual).Matches(pattern)
"IsMatch" when arguments.Count >= 2 => CreateTUnitAssertion("Matches", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.DoesNotMatch(pattern, actual) -> Assert.That(actual).DoesNotMatch(pattern)
"DoesNotMatch" when arguments.Count >= 2 => CreateTUnitAssertion("DoesNotMatch", arguments[1].Expression, SyntaxFactory.Argument(arguments[0].Expression)),
// StringAssert.AreEqualIgnoringCase(expected, actual) -> Assert.That(actual).IsEqualTo(expected, StringComparison.OrdinalIgnoreCase)
"AreEqualIgnoringCase" when arguments.Count >= 2 => CreateStringComparisonAssertion("IsEqualTo", arguments[1].Expression, arguments[0].Expression),
// StringAssert.AreNotEqualIgnoringCase(expected, actual) -> Assert.That(actual).IsNotEqualTo(expected, StringComparison.OrdinalIgnoreCase)
"AreNotEqualIgnoringCase" when arguments.Count >= 2 => CreateStringComparisonAssertion("IsNotEqualTo", arguments[1].Expression, arguments[0].Expression),
_ => null
};
}

private ExpressionSyntax CreateStringComparisonAssertion(string methodName, ExpressionSyntax actual, ExpressionSyntax expected)
{
// Create Assert.That(actual)
var assertThatInvocation = SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
SyntaxFactory.IdentifierName("Assert"),
SyntaxFactory.IdentifierName("That")),
SyntaxFactory.ArgumentList(
SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(actual))));

// Create Assert.That(actual).IsEqualTo(expected, StringComparison.OrdinalIgnoreCase)
var stringComparisonArg = SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
SyntaxFactory.IdentifierName("StringComparison"),
SyntaxFactory.IdentifierName("OrdinalIgnoreCase"));

return SyntaxFactory.InvocationExpression(
SyntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
assertThatInvocation,
SyntaxFactory.IdentifierName(methodName)),
SyntaxFactory.ArgumentList(
SyntaxFactory.SeparatedList(new[]
{
SyntaxFactory.Argument(expected),
SyntaxFactory.Argument(stringComparisonArg)
})));
}

}

public class NUnitBaseTypeRewriter : CSharpSyntaxRewriter
Expand Down
4 changes: 2 additions & 2 deletions TUnit.Analyzers.Tests/MSTestMigrationAnalyzerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -686,8 +686,8 @@ public async Task TestReferences()
var obj2 = obj1;
var obj3 = new object();

await Assert.That(obj2).IsSameReference(obj1);
await Assert.That(obj3).IsNotSameReference(obj1);
await Assert.That(obj2).IsSameReferenceAs(obj1);
await Assert.That(obj3).IsNotSameReferenceAs(obj1);
}
}
""",
Expand Down
Loading
Loading