-
-
Notifications
You must be signed in to change notification settings - Fork 108
refactor: fix xUnit true/false assertion conversion logic when supplying optional message parameter #4010
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
Conversation
…ing optional message parameter
Code Review ✓Thank you for this fix! This PR correctly addresses issue #3857 by properly handling the optional message parameter in xUnit's ✅ Positive Observations1. Correct Fix Implementation
2. Excellent Test Coverage
3. Clean Refactoring 4. Dual-Path Coverage
📋 Minor Observations1. Parameter Naming Inconsistency // Line 161: 'expected' is actually the condition, not expected value
"True" => ConvertTrueAssertion(argumentListArguments, expected, isInSatisfy, parameterName),However, looking at the context, 2. Consistent Pattern Application 3. Code Style Compliance 🔍 Security & PerformanceSecurity: ✅ No security concerns. String interpolation is used safely within Roslyn syntax parsing. Performance: ✅ No performance concerns. The helper methods are simple and don't add allocations in hot paths. ✅ Pre-Commit Checklist VerificationBased on CLAUDE.md requirements:
🎯 RecommendationLGTM! This is a solid fix with excellent test coverage. Action Items:
Great work fixing this bug! The refactoring to extract helper methods makes the code more maintainable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes the xUnit to TUnit assertion conversion for Assert.True and Assert.False when an optional message parameter is supplied. The fix extracts the inline True/False conversion logic into dedicated helper methods that properly handle the optional message by appending .Because(message) to the assertion chain.
Key Changes
- Extracted True/False assertion conversion logic into dedicated helper methods (
ConvertTrueAssertionandConvertFalseAssertion) - Added support for converting the optional message parameter to
.Because()calls - Updated pattern matching in
ConvertLambdaBodyToTUnitAssertionsto handle True/False with messages - Cleaned up unused dead code for non-existent xUnit methods (IsAssignableTo, IsNotAssignableTo, IsNotAssignableFrom)
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| TUnit.Assertions.Analyzers.CodeFixers/XUnitAssertionCodeFixProvider.cs | Added ConvertTrueAssertion and ConvertFalseAssertion helper methods; updated True/False case handlers in switch expressions to use new helpers; added pattern matching cases for True/False with messages in lambda body conversion; removed dead code for non-existent xUnit methods |
| TUnit.Assertions.Analyzers.CodeFixers.Tests/XUnitAssertionCodeFixProviderTests.cs | Added comprehensive test coverage for True/False assertions with and without messages, plus additional tests for other assertion types (Null, NotNull, Same, NotSame, Contains, etc.) |
|
|
||
| private static ExpressionSyntax ConvertTrueAssertion( | ||
| SeparatedSyntaxList<ArgumentSyntax> args, | ||
| ArgumentSyntax? condition, |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name condition could be more descriptive. Consider renaming it to conditionArg or conditionArgument to clearly indicate it's an ArgumentSyntax node, not the condition value itself. This improves code readability and consistency with the args parameter.
|
|
||
| private static ExpressionSyntax ConvertFalseAssertion( | ||
| SeparatedSyntaxList<ArgumentSyntax> args, | ||
| ArgumentSyntax? condition, |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name condition could be more descriptive. Consider renaming it to conditionArg or conditionArgument to clearly indicate it's an ArgumentSyntax node, not the condition value itself. This improves code readability and consistency with the args parameter.
| private static ExpressionSyntax ConvertTrueAssertion( | ||
| SeparatedSyntaxList<ArgumentSyntax> args, | ||
| ArgumentSyntax? condition, | ||
| bool isInSatisfy, | ||
| string? parameterName) | ||
| { | ||
| var baseExpr = isInSatisfy && parameterName != null | ||
| ? $"{condition}.IsTrue()" | ||
| : $"Assert.That({condition}).IsTrue()"; | ||
|
|
||
| // Check for message parameter (second argument) | ||
| if (args.Count >= 2) | ||
| { | ||
| var message = args[1]; | ||
| return SyntaxFactory.ParseExpression($"{baseExpr}.Because({message})"); | ||
| } | ||
|
|
||
| return SyntaxFactory.ParseExpression(baseExpr); | ||
| } | ||
|
|
||
| private static ExpressionSyntax ConvertFalseAssertion( | ||
| SeparatedSyntaxList<ArgumentSyntax> args, | ||
| ArgumentSyntax? condition, | ||
| bool isInSatisfy, | ||
| string? parameterName) | ||
| { | ||
| var baseExpr = isInSatisfy && parameterName != null | ||
| ? $"{condition}.IsFalse()" | ||
| : $"Assert.That({condition}).IsFalse()"; | ||
|
|
||
| // Check for message parameter (second argument) | ||
| if (args.Count >= 2) | ||
| { | ||
| var message = args[1]; | ||
| return SyntaxFactory.ParseExpression($"{baseExpr}.Because({message})"); | ||
| } | ||
|
|
||
| return SyntaxFactory.ParseExpression(baseExpr); | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ConvertTrueAssertion and ConvertFalseAssertion methods are nearly identical, differing only in the assertion method name (.IsTrue() vs .IsFalse()). Consider refactoring to a single method like ConvertBooleanAssertion(args, condition, isInSatisfy, parameterName, assertionMethod) where assertionMethod is either "IsTrue" or "IsFalse". This reduces code duplication and makes the code more maintainable.
| ); | ||
| } | ||
|
|
||
| [Test] |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the new tests cover Assert.True/Assert.False with messages in simple scenarios, there's no test coverage for these assertions with messages when used inside Assert.All lambda bodies (which uses the ConvertLambdaBodyToTUnitAssertions code path at lines 535-542). Consider adding a test like the existing Xunit_All_Converts_To_AssertMultiple_WithForeach test but with Xunit.Assert.True(condition, "message") inside the lambda to ensure both code paths work correctly.
Fixes #3857