Skip to content

Extract shared TestResultCapture helpers to SharedExtensionHelpers#9044

Merged
Evangelink merged 4 commits into
mainfrom
dev/copilot/issue-8986-shared-testresult-helpers
Jun 11, 2026
Merged

Extract shared TestResultCapture helpers to SharedExtensionHelpers#9044
Evangelink merged 4 commits into
mainfrom
dev/copilot/issue-8986-shared-testresult-helpers

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Fixes #8986

Summary

  • Added a linked SharedExtensionHelpers TestResultCaptureHelper for shared truncation limits, truncation, class/method projection, and common outcome classification.
  • Kept HtmlReport and JUnitReport capture DTOs and format-specific cancellation wrappers in their own packages to preserve existing report behavior.

Validation

  • dotnet build for HtmlReport and JUnitReport passed.
  • dotnet test test\UnitTests\Microsoft.Testing.Extensions.UnitTests\Microsoft.Testing.Extensions.UnitTests.csproj -f net8.0 -p:UsingDotNetTest=true --no-build passed: 483 total, 479 succeeded, 4 skipped.

…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>
Copilot AI review requested due to automatic review settings June 11, 2026 13:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 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 TestResultCaptureHelper to centralize truncation limits, safe truncation, class/method projection, and common outcome classification.
  • Updated HtmlReport and JUnitReport TestResultCapture to delegate to the shared helper and link the helper via Compile 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

Comment thread src/Platform/Microsoft.Testing.Extensions.HtmlReport/TestResultCapture.cs Outdated

@Evangelink Evangelink left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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 ⚠️ Dead code in HTML wrapper distorts the intent 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 ⚠️ No tests for shared helper MAJOR
10. Performance MAJOR
11. Security BLOCKING
12. Localization MINOR
13. Documentation MINOR
14. Unused Code ⚠️ Dead 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 ⚠️ See findings below 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 ·

Comment thread src/Platform/SharedExtensionHelpers/TestResultCaptureHelper.cs
Comment thread src/Platform/Microsoft.Testing.Extensions.HtmlReport/TestResultCapture.cs Outdated
Amaury Levé and others added 2 commits June 11, 2026 16:48
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>
Copilot AI review requested due to automatic review settings June 11, 2026 19:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 6/6 changed files
  • Comments generated: 1

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>
@Evangelink Evangelink merged commit 4b39821 into main Jun 11, 2026
31 of 38 checks passed
@Evangelink Evangelink deleted the dev/copilot/issue-8986-shared-testresult-helpers branch June 11, 2026 20:03
@Evangelink

Copy link
Copy Markdown
Member Author

🧪 Test quality grade — PR #9044

ΔTestGradeBandNotes
mod TestResultCaptureHelperTests.
Truncate_
DoesNotSplitSurrogatePair_
DropsHighSurrogate
C 70–79 Non-public reflection caps anti-pattern to C; exact equality is a clear improvement over the prior four partial checks.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

🤖 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 Grade Tests on PR (on open / sync) workflow. · 419.2 AIC · ⌖ 13.6 AIC · [◷]( · )

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.

[duplicate-code] Duplicate Code: TestResultCapture and CapturedTestResult Duplicated in HtmlReport and JUnitReport

2 participants