Skip to content

Conversation

@thomhurst
Copy link
Owner

Summary

Follow-up improvements to the migration code fixers based on user feedback:

  • Add using System.Threading.Tasks; when async code is present in migration
  • Preserve NUnit TestCase named properties during migration:
    • Map Ignore/IgnoreReason to TUnit's Skip property
    • Add TODO comments for unsupported properties (TestName, Category, Description, Author, Explicit, ExplicitReason)

Test plan

  • NUnit migration tests: 124/124 passed
  • MSTest migration tests: 84/84 passed
  • xUnit migration tests: 131/132 passed (1 infrastructure failure on net10.0)

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings January 1, 2026 16:18
@thomhurst
Copy link
Owner Author

Summary

This PR adds comprehensive improvements to migration code fixers: automatic using System.Threading.Tasks insertion for async code, and preservation of NUnit TestCase properties during migration.

Critical Issues

None found ✅

Suggestions

1. Consider ValueTask for consistency (minor)

The new AsyncMethodSignatureRewriter converts methods to return Task and Task<T>. TUnit's CRITICAL RULE #4 mentions "Use ValueTask for potentially-sync operations" for performance. However, for migration scenarios where the source code is being rewritten, Task is likely the correct choice since:

  • Migration is a one-time operation (not a hot path)
  • Most migrated async methods will actually await something
  • Simpler migration logic

This is working as intended - just noting for awareness.

2. Message handling looks comprehensive

The addition of message/format arg extraction (ExtractMessageWithFormatArgs, CreateMessageExpression) properly handles format strings with string.Format. Good attention to detail mapping MSTest/NUnit assertion messages to TUnit's .Because() fluent API.

3. Test coverage

The PR description mentions:

  • ✅ NUnit migration tests: 124/124 passed
  • ✅ MSTest migration tests: 84/84 passed
  • ✅ xUnit migration tests: 131/132 passed (1 infrastructure failure)

Excellent test coverage for migration scenarios.

TUnit Rules Compliance

Rule 1 (Dual-Mode): Not applicable - analyzer/code fixer changes only
Rule 2 (Snapshot Testing): Not applicable - these tests use Roslyn analyzer testing framework
Rule 3 (No VSTest): No VSTest usage detected
Rule 4 (Performance): Not a hot path - migration is one-time operation
Rule 5 (AOT): Not applicable - analyzers run at compile time
Async/Await: Properly uses await expressions, no blocking calls

Verdict

APPROVE - No critical issues. The code is well-structured, follows TUnit principles, and has comprehensive test coverage. The migration improvements will significantly improve the user experience when migrating from other frameworks.

- Add `using System.Threading.Tasks;` when async code is present in migration
- Preserve NUnit TestCase named properties during migration:
  - Map Ignore/IgnoreReason to TUnit's Skip property
  - Add TODO comments for unsupported properties (TestName, Category, Description, etc.)
- Update test expectations to include System.Threading.Tasks using

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@thomhurst thomhurst force-pushed the feat/comprehensive-migration-code-fixers branch from a9486ef to cf2315d Compare January 1, 2026 16:25
Copy link

Copilot AI left a 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 enhances the test framework migration code fixers by adding automatic using System.Threading.Tasks; imports when async code is detected, and preserving NUnit TestCase properties during migration (mapping Ignore/IgnoreReason to TUnit's Skip, and adding TODO comments for unsupported properties).

Key Changes

  • Automatically adds using System.Threading.Tasks; when async/await patterns are detected during migration
  • Preserves NUnit TestCase named properties with appropriate mappings and TODO comments for unsupported features
  • Extended assertion conversion support across NUnit, xUnit, and MSTest migrations with message parameter handling

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
TUnit.Analyzers/Migrators/Base/MigrationHelpers.cs Adds conditional using System.Threading.Tasks; when async code is detected
TUnit.Analyzers.CodeFixers/NUnitMigrationCodeFixProvider.cs Maps NUnit TestCase properties (Ignore→Skip) and adds extensive assertion conversions with message support
TUnit.Analyzers.CodeFixers/NUnitExpectedResultRewriter.cs Preserves TestCase properties in ExpectedResult scenarios with TODO comments for unsupported properties
TUnit.Analyzers.CodeFixers/XUnitMigrationCodeFixProvider.cs Extended xUnit assertion conversions with comparer detection and message handling
TUnit.Analyzers.CodeFixers/MSTestMigrationCodeFixProvider.cs Extended MSTest assertion conversions with proper message parameter positioning
TUnit.Analyzers.CodeFixers/Base/TestAttributeEnsurer.cs New rewriter ensuring [Test] attribute exists when data attributes are present (NUnit-specific)
TUnit.Analyzers.CodeFixers/Base/BaseMigrationCodeFixProvider.cs Integrates AsyncMethodSignatureRewriter and TestAttributeEnsurer into migration pipeline
TUnit.Analyzers.CodeFixers/Base/AsyncMethodSignatureRewriter.cs New rewriter converting void/T methods to async Task/Task when await is present
TUnit.Analyzers.CodeFixers/Base/AssertionRewriter.cs Adds message handling with .Because() chaining and helper methods for format strings and comparer detection
TUnit.Analyzers.Tests/NUnitMigrationAnalyzerTests.cs Adds comprehensive tests verifying async using import, TestCase handling, and assertion message conversion
TUnit.Analyzers.Tests/MSTestMigrationAnalyzerTests.cs Adds test verifying MSTest assertion message preservation

.Any(n => n is AwaitExpressionSyntax ||
(n is MethodDeclarationSyntax m && m.Modifiers.Any(mod => mod.IsKind(SyntaxKind.AsyncKeyword))));

if (hasAsyncCode && !existingUsings.Any(u => u.Name?.ToString() == "System.Threading.Tasks"))
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check for existing System.Threading.Tasks using should use string comparison with qualified name. The current comparison u.Name?.ToString() == "System.Threading.Tasks" might not work correctly if the using directive uses an alias or has different formatting. Consider checking against the full qualified name more robustly or ensuring the name is normalized before comparison.

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@thomhurst thomhurst merged commit 774a516 into main Jan 1, 2026
13 checks passed
@thomhurst thomhurst deleted the feat/comprehensive-migration-code-fixers branch January 1, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants