Extract shared TestResultCapture helpers to SharedExtensionHelpers#9044
Conversation
…8986) Move the shared truncation limits, truncation implementation, test method name projection, and common outcome classification into a linked SharedExtensionHelpers helper. Keep HTML and JUnit report-specific capture DTOs and cancellation mapping wrappers local so each report preserves its existing behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR reduces duplicated result-capture logic across Microsoft.Testing.Platform report extensions by extracting shared truncation/classification/projection utilities into SharedExtensionHelpers, while keeping format-specific behavior (notably cancellation outcome handling and DTO differences) within each report extension.
Changes:
- Added
TestResultCaptureHelperto centralize truncation limits, safe truncation, class/method projection, and common outcome classification. - Updated HtmlReport and JUnitReport
TestResultCaptureto delegate to the shared helper and link the helper viaCompile Include ... Link=.... - Preserved report-specific cancellation outcome mapping behavior in each extension.
Show a summary per file
| File | Description |
|---|---|
| src/Platform/SharedExtensionHelpers/TestResultCaptureHelper.cs | New shared helper for truncation, class/method naming, and common outcome classification. |
| src/Platform/Microsoft.Testing.Extensions.JUnitReport/TestResultCapture.cs | Delegates shared logic to helper; keeps JUnit-specific cancellation mapping. |
| src/Platform/Microsoft.Testing.Extensions.JUnitReport/Microsoft.Testing.Extensions.JUnitReport.csproj | Links the shared helper into the JUnitReport build. |
| src/Platform/Microsoft.Testing.Extensions.HtmlReport/TestResultCapture.cs | Delegates shared logic to helper; retains HTML-specific behavior. |
| src/Platform/Microsoft.Testing.Extensions.HtmlReport/Microsoft.Testing.Extensions.HtmlReport.csproj | Links the shared helper into the HtmlReport build. |
Copilot's findings
- Files reviewed: 5/5 changed files
- Comments generated: 1
Evangelink
left a comment
There was a problem hiding this comment.
Note
🤖 Automated review by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.
Review: Extract shared TestResultCapture helpers to SharedExtensionHelpers
| Dimension | Verdict | Severity |
|---|---|---|
| 1. Algorithmic Correctness | MAJOR | |
| 2. Threading & Concurrency | ✅ | BLOCKING |
| 3. Memory & Resource Management | ✅ Surrogate-pair fix is an improvement | MAJOR |
| 4. Error Handling | ✅ ApplicationStateGuard.Unreachable() preserved |
MAJOR |
| 5. Naming Conventions | ✅ | MINOR |
| 6. Code Style & Formatting | ✅ | MINOR |
| 7. Public API Surface | ✅ All internal |
MAJOR |
| 8. Backward Compatibility | ✅ JUnit "cancelled", HTML "failed" both preserved | BLOCKING |
| 9. Test Coverage | MAJOR | |
| 10. Performance | ✅ | MAJOR |
| 11. Security | ✅ | BLOCKING |
| 12. Localization | ✅ | MINOR |
| 13. Documentation | ✅ | MINOR |
| 14. Unused Code | if block in HTML ClassifyOutcome |
MINOR |
| 15. Dependency Management | ✅ | MINOR |
| 16. Cross-TFM Compatibility | ✅ File-link pattern unchanged | MAJOR |
| 17. IPC Contract Stability | ✅ | BLOCKING |
| 18. Scope Discipline | CtrfReport duplicates the same constants + broken Truncate |
MINOR |
| 19. Pattern Consistency | ✅ Follows existing SharedExtensionHelpers pattern |
MINOR |
| 20. Null Safety | ✅ | MAJOR |
| 21. Invariant Guards | ✅ | MAJOR |
| 22. Overarching Principles | META |
Blocking / Request-Changes finding
HtmlReport/TestResultCapture.ClassifyOutcome — dead code (lines 101–103). Both the early return inside if (state is CancelledTestNodeStateProperty) and the fallthrough below it call TestResultCaptureHelper.ClassifyOutcome(state) identically. Because CancelledTestNodeStateProperty is in WellKnownTestNodeTestRunOutcomeFailedProperties, the shared helper's Array.IndexOf arm already returns "failed" — the correct historic HTML behaviour — so the guard is never needed. The #pragma warning disable CS0618/MTP0001 it drags in suppresses a warning for a dead check. Please remove the if block (or collapse ClassifyOutcome to a single expression-body delegation).
Non-blocking findings
Test coverage (MAJOR): TestResultCaptureHelper.Truncate carries the surrogate-pair guard that was absent from the old JUnit one-liner — a real correctness fix — but it has no dedicated test. TrxTestResultExtractorTests already has Extract_HighSurrogateAtBoundary_NotSplitByTruncation as a model; the same scenario should be added for TestResultCaptureHelper.Truncate.
Scope (CtrfReport, MINOR): Microsoft.Testing.Extensions.CtrfReport/TestResultCapture.cs duplicates all five size constants and its own Truncate one-liner still lacks the surrogate-pair guard (line 137–141). It isn't directly refactorable to the new shared helper because GetClassAndMethodName there returns a 3-tuple, but the constants and Truncate could follow. Consider a follow-up issue if out of scope for this PR.
🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 435.5 AIC · ⌖ 20.3 AIC · ◷
Both branches of the ClassifyOutcome wrapper delegated to TestResultCaptureHelper.ClassifyOutcome with no behavioral difference, so the if/pragma block added control flow without changing the result. Collapse the wrapper to a single expression-bodied delegation and keep the rationale comment so it stays clear why HtmlReport doesn't override cancellation classification (contrast with JUnit which still returns its own "cancelled" string). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses self-review comment on PR #9044: the new shared helper had no direct test coverage. Adds 13 tests covering Truncate (incl. surrogate-pair boundary), ClassifyOutcome (all six outcome flavors plus Cancelled fall-through), and GetClassAndMethodName (with/without namespace, null identifier). Uses reflection (matching ReportFileNameSanitizationConsistencyTests) because the helper is linked into two extension assemblies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reviewer correctly pointed out that result[1] is 'b' so char.IsHighSurrogate trivially passed. Switch to exact-equality assertion against ab + suffix, which proves the high surrogate at original index 2 was dropped. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🧪 Test quality grade — PR #9044
This advisory comment was generated automatically. Grades are heuristic
|
Fixes #8986
Summary
TestResultCaptureHelperfor shared truncation limits, truncation, class/method projection, and common outcome classification.Validation
dotnet buildfor HtmlReport and JUnitReport passed.dotnet test test\UnitTests\Microsoft.Testing.Extensions.UnitTests\Microsoft.Testing.Extensions.UnitTests.csproj -f net8.0 -p:UsingDotNetTest=true --no-buildpassed: 483 total, 479 succeeded, 4 skipped.