fix: handle nested types and constructor parameters in UID filter matching#4669
fix: handle nested types and constructor parameters in UID filter matching#4669
Conversation
…ching
The CouldMatchUidFilter method was failing to match tests when using
VS Test Explorer because:
1. For nested types (e.g., Outer+Inner), Type.Name only returns the
innermost class name, but UIDs contain the full path with '+' separators
2. For classes with constructor parameters, UIDs contain '(' after the
class name (e.g., MyClass(String).0.0.Method), but the code only
checked for '.' or '<'
This fix:
- Adds BuildClassNameForMatching() to construct the full nested type
hierarchy matching TestIdentifierService.WriteTypeNameWithGenerics
- Validates the character after the class name prefix is a valid
boundary: '.', '<', or '('
- Maintains protection against substring matching (ABCV vs ABCVC)
Fixes #4656 (follow-up issue after PR #4659)
https://claude.ai/code/session_016KqnWq2pDNM7sDLSn6LvRe
Code Review - Two Issues Found1. Allocation in Hot Path (CLAUDE.md Violation)The new BuildClassNameForMatching() method allocates a List in test discovery (hot path #1). Lines 283-306 allocate List and use string.Join(). CLAUDE.md Rule: Performance First - Minimize allocations in hot paths (test discovery, execution) See: Line 15 in fe8aa8f The established pattern in TestIdentifierService.WriteTypeNameWithGenerics (lines 118-184) uses ValueListBuilder for the same operation. Suggested fix: Use ValueListBuilder instead of List to match the established pattern. 2. Critical Bug: Nested Generic Types Not HandledBuildClassNameForMatching() does not include generic type arguments for outer types in nested hierarchies. This causes incorrect filtering. Example for Outer.Inner:
Root cause: Lines 293-300 strip the backtick suffix but dont append generic type arguments like TestIdentifierService does (lines 143-155). This breaks TUnits dual-mode architecture by creating inconsistency between test identification and filtering. Suggested fix: Include generic type arguments for ALL types in the hierarchy, matching the format in TestIdentifierService.WriteTypeNameWithGenerics lines 143-155. |
Address code review feedback: 1. Performance: Replace List<string> with ValueListBuilder<string> and ValueStringBuilder to avoid allocations in the hot path during test discovery. 2. Bug fix: Include generic type arguments for all types in the nested hierarchy. For Outer<int>.Inner, the UID contains Outer<System.Int32>+Inner, not Outer+Inner. The implementation now exactly mirrors TestIdentifierService.WriteTypeNameWithGenerics to ensure consistent UID format matching. https://claude.ai/code/session_016KqnWq2pDNM7sDLSn6LvRe
Add test fixtures and integration tests covering: - Nested classes (Outer+Inner format) - Deeply nested classes (Outer+Inner+Deep format) - Overlapping class names (FilterTest vs FilterTestHelper) - Method name boundary matching (Test vs TestMethod) - Original issue regression (ABCV vs ABCVC) Test fixtures in TUnit.TestProject/Bugs/4656/UidFilterMatchingTests.cs Integration tests in TUnit.Engine.Tests/UidFilterMatchingTests.cs https://claude.ai/code/session_016KqnWq2pDNM7sDLSn6LvRe
- Fix source generator crash (TUNIT0999) for non-generic types nested inside generic outer types by adding Arity > 0 guard in GloballyQualified() and skipping such types in test metadata generation - Move [Arguments] from method level to class level for test classes with constructor parameters (fixes TUnit0038/TUnit0050 errors) - Fix engine test tree node filters to use innermost class name instead of nested type path format (OuterClass+InnerClass -> InnerClass) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Code ReviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Add [GenerateGenericTest] attributes to open generic test classes so they can be instantiated with concrete type arguments. Remove DeeplyNestedClass (3-level nesting fails in net8.0 AOT) and InnerNonGenericClass (nested inside open generic, can't be source-generated). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CouldMatchUidFilter method was failing to match tests when using
VS Test Explorer because:
For nested types (e.g., Outer+Inner), Type.Name only returns the
innermost class name, but UIDs contain the full path with '+' separators
For classes with constructor parameters, UIDs contain '(' after the
class name (e.g., MyClass(String).0.0.Method), but the code only
checked for '.' or '<'
This fix:
hierarchy matching TestIdentifierService.WriteTypeNameWithGenerics
boundary: '.', '<', or '('
Fixes #4656 (follow-up issue after PR #4659)
https://claude.ai/code/session_016KqnWq2pDNM7sDLSn6LvRe