diff --git a/TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs b/TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs index a81ead26fe..12f03b5e1b 100644 --- a/TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs +++ b/TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs @@ -1151,6 +1151,7 @@ waitInvocation.Expression is MemberAccessExpressionSyntax waitAccess && "Fail" => CreateFailAssertion(arguments), "Inconclusive" => CreateSkipAssertion(arguments), "Ignore" => CreateSkipAssertion(arguments), + "Warn" => CreateWarnAssertion(arguments), // 2-arg assertions (expected, actual) with optional message at index 2 "AreEqual" when arguments.Count >= 2 => ConvertAreEqualWithComparer(arguments), @@ -1472,6 +1473,46 @@ private ExpressionSyntax CreateSkipAssertion(SeparatedSyntaxList return skipInvocation; } + private ExpressionSyntax CreateWarnAssertion(SeparatedSyntaxList arguments) + { + // NUnit's Assert.Warn outputs a warning but allows the test to continue + // TUnit doesn't have a direct equivalent, so we convert to Skip.Test with a prefix + // Users may want to handle warnings differently (e.g., console output) + var messageArg = arguments.Count > 0 + ? arguments[0] + : SyntaxFactory.Argument( + SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, + SyntaxFactory.Literal("Warning"))); + + // Wrap the message in "Warning: " prefix + var prefixedMessage = SyntaxFactory.Argument( + SyntaxFactory.InterpolatedStringExpression( + SyntaxFactory.Token(SyntaxKind.InterpolatedStringStartToken), + SyntaxFactory.List( + [ + SyntaxFactory.InterpolatedStringText() + .WithTextToken(SyntaxFactory.Token( + SyntaxFactory.TriviaList(), + SyntaxKind.InterpolatedStringTextToken, + "Warning: ", + "Warning: ", + SyntaxFactory.TriviaList())), + SyntaxFactory.Interpolation(messageArg.Expression) + ]))); + + var skipInvocation = SyntaxFactory.InvocationExpression( + SyntaxFactory.MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + SyntaxFactory.IdentifierName("Skip"), + SyntaxFactory.IdentifierName("Test") + ), + SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(prefixedMessage)) + ); + + return skipInvocation; + } + private ExpressionSyntax? ConvertFileAssertion(InvocationExpressionSyntax invocation, string methodName) { var arguments = invocation.ArgumentList.Arguments; diff --git a/TUnit.Analyzers.Tests/NUnitMigrationAnalyzerTests.cs b/TUnit.Analyzers.Tests/NUnitMigrationAnalyzerTests.cs index c07e96f02c..a8382adffc 100644 --- a/TUnit.Analyzers.Tests/NUnitMigrationAnalyzerTests.cs +++ b/TUnit.Analyzers.Tests/NUnitMigrationAnalyzerTests.cs @@ -2268,6 +2268,42 @@ public void TestMethod() ); } + [Test] + public async Task NUnit_Warn_Converted() + { + await CodeFixer.VerifyCodeFixAsync( + """ + using NUnit.Framework; + + {|#0:public class MyClass|} + { + [Test] + public void TestMethod() + { + Assert.Warn("This is a warning"); + } + } + """, + Verifier.Diagnostic(Rules.NUnitMigration).WithLocation(0), + """ + using TUnit.Core; + using TUnit.Assertions; + using static TUnit.Assertions.Assert; + using TUnit.Assertions.Extensions; + + public class MyClass + { + [Test] + public void TestMethod() + { + Skip.Test($"Warning: {"This is a warning"}"); + } + } + """, + ConfigureNUnitTest + ); + } + [Test] public async Task NUnit_Fail_Converted() { @@ -2552,6 +2588,162 @@ public async Task TestMethod() ); } + [Test] + public async Task NUnit_Is_Positive_Converted() + { + await CodeFixer.VerifyCodeFixAsync( + """ + using NUnit.Framework; + + {|#0:public class MyClass|} + { + [Test] + public void TestMethod() + { + int value = 5; + Assert.That(value, Is.Positive); + } + } + """, + Verifier.Diagnostic(Rules.NUnitMigration).WithLocation(0), + """ + using System.Threading.Tasks; + using TUnit.Core; + using TUnit.Assertions; + using static TUnit.Assertions.Assert; + using TUnit.Assertions.Extensions; + + public class MyClass + { + [Test] + public async Task TestMethod() + { + int value = 5; + await Assert.That(value).IsPositive(); + } + } + """, + ConfigureNUnitTest + ); + } + + [Test] + public async Task NUnit_Is_Negative_Converted() + { + await CodeFixer.VerifyCodeFixAsync( + """ + using NUnit.Framework; + + {|#0:public class MyClass|} + { + [Test] + public void TestMethod() + { + int value = -5; + Assert.That(value, Is.Negative); + } + } + """, + Verifier.Diagnostic(Rules.NUnitMigration).WithLocation(0), + """ + using System.Threading.Tasks; + using TUnit.Core; + using TUnit.Assertions; + using static TUnit.Assertions.Assert; + using TUnit.Assertions.Extensions; + + public class MyClass + { + [Test] + public async Task TestMethod() + { + int value = -5; + await Assert.That(value).IsNegative(); + } + } + """, + ConfigureNUnitTest + ); + } + + [Test] + public async Task NUnit_Is_Not_Positive_Converted() + { + await CodeFixer.VerifyCodeFixAsync( + """ + using NUnit.Framework; + + {|#0:public class MyClass|} + { + [Test] + public void TestMethod() + { + int value = -5; + Assert.That(value, Is.Not.Positive); + } + } + """, + Verifier.Diagnostic(Rules.NUnitMigration).WithLocation(0), + """ + using System.Threading.Tasks; + using TUnit.Core; + using TUnit.Assertions; + using static TUnit.Assertions.Assert; + using TUnit.Assertions.Extensions; + + public class MyClass + { + [Test] + public async Task TestMethod() + { + int value = -5; + await Assert.That(value).IsLessThanOrEqualTo(0); + } + } + """, + ConfigureNUnitTest + ); + } + + [Test] + public async Task NUnit_Is_Not_Negative_Converted() + { + await CodeFixer.VerifyCodeFixAsync( + """ + using NUnit.Framework; + + {|#0:public class MyClass|} + { + [Test] + public void TestMethod() + { + int value = 5; + Assert.That(value, Is.Not.Negative); + } + } + """, + Verifier.Diagnostic(Rules.NUnitMigration).WithLocation(0), + """ + using System.Threading.Tasks; + using TUnit.Core; + using TUnit.Assertions; + using static TUnit.Assertions.Assert; + using TUnit.Assertions.Extensions; + + public class MyClass + { + [Test] + public async Task TestMethod() + { + int value = 5; + await Assert.That(value).IsGreaterThanOrEqualTo(0); + } + } + """, + ConfigureNUnitTest + ); + } + [Test] public async Task NUnit_Platform_Attribute_Removed() {