Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Share terminal per-assembly counts + port SDK oracle test (2/n) - #9265

Merged
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts
Jun 20, 2026
Merged

Share terminal per-assembly counts + port SDK oracle test (2/n)#9265
Amaury Levé (Evangelink) merged 7 commits into
mainfrom
copilot/share-terminal-per-assembly-counts

Conversation

@Evangelink

Copy link
Copy Markdown
Member

What

Slice 2/n of unifying the shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork, continuing the test-first approach: port the SDK's reporter test as the expected-UI oracle, then implement the feature to make it pass.

Stacked on #9263 (slice 1, handshake surface), which this extends.

Added (additive — gated on the new ShowAssembly options that default off, so the in-process host is unaffected and its output stays byte-identical)

  • ShowAssembly + ShowAssemblyStartAndComplete options.
  • The rich AssemblyRunCompleted (from Share terminal handshake-failure surface + port SDK oracle test (1/n) #9263) now prints the per-assembly summary line (link + result + compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
  • AppendAssemblySummary / AppendAssemblyResult / AppendAssemblyTestCounts / AppendGlyphCount — the compact [+P/xF/?S] (ASCII) / [✓P/xF/↓S] (full-ANSI) counts block, with the /r{N} retry segment wired to TestProgressState.RetriedFailedTests.
  • An orchestrator TestCompleted(assembly, tfm, arch, executionId, instanceId, …) overload that updates per-assembly counts (delegates to the shared per-execution-id path; instanceId-based retry attribution lands in the retry slice).
  • New TerminalResources.FailedWithErrors (resx + 13 xlf via UpdateXlf + hand-maintained !IS_CORE_MTP accessor).

Oracle test ported

AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts — ported from the SDK's TerminalTestReporterTests (regression for dotnet/sdk#52128) to MSTest + the testfx StringBuilderConsole harness, asserting the rendered [+3/x0/?1] counts block. (NoAnsi is used so the assertion is plain text; it exercises the same ASCII glyph set the SDK asserts via its SimpleTerminal path — both SimpleAnsiTerminal and NonAnsiTerminal derive from SimpleTerminal, not AnsiTerminal.)

Remaining slices

3/n = per-assembly counts in the final summary for N>1 (TestExecutionCompleted_WithMultipleAssemblies_…); 4/n (high-risk) = the instanceId retry model /r{N} + unified TestCompleted/TestInProgress/TestDiscovered signatures (…_WhenTestsWereRetried_…). After those, the SDK consumes the package and deletes its fork.

Verification

  • Platform clean on net8.0 / net9.0 / netstandard2.0 (0 warnings incl. IDE/SA).
  • Full Microsoft.Testing.Platform.UnitTests suite green: 1200 total, 0 failed (byte-exact in-process tests unchanged).
  • Standalone TerminalReporterContract consumer compiles in isolation.

Note: review/merge #9263 first — this branch is stacked on it.

First slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's own reporter test as the
expected-UI oracle.
Adds the orchestrator handshake surface to the shared reporter (additive; the
in-process host never reports handshake failures, so output stays byte-identical):
- HandshakeFailure(assemblyPath, tfm, exitCode, output, error, reportEvenWhenHelp)
+ HasHandshakeFailure + end-of-run AppendHandshakeFailureRecap.
- Rich AssemblyRunCompleted(executionId, exitCode, outputData, errorData) overload
that surfaces an unknown execution id as a handshake failure (no throw) and prints
the executable summary (exit code + stdout/stderr) on non-zero exit.
- TerminalTestReporter(IConsole, options) ctor overload for orchestrator callers that
drive cancellation out-of-band via StartCancelling.
- TestProgressState.Success; string-based AppendAssemblyLinkTargetFrameworkAndArchitecture
overload; AppendExecutableSummary; new TerminalResources HandshakeFailuresHeader/ExitCode
(resx + xlf regenerated via UpdateXlf, hand-maintained !IS_CORE_MTP accessors updated).
Ports the SDK's AssemblyRunCompleted_WhenExecutionIdUnknown test (dotnet/sdk#51608) to
MSTest, asserting both HasHandshakeFailure and the rendered failure context.
Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings incl. IDE/SA);
full Microsoft.Testing.Platform.UnitTests suite green (1199, 0 failed); standalone
TerminalReporterContract consumer still compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Second slice of unifying the shared MTP terminal reporter with the dotnet/sdk
orchestrator fork, validated by porting the SDK's per-assembly-counts test.
Adds the orchestrator per-assembly summary rendering (additive; gated on the new
ShowAssembly options which default off, so the in-process host is unaffected and
its output stays byte-identical):
- ShowAssembly + ShowAssemblyStartAndComplete options.
- Rich AssemblyRunCompleted now prints the per-assembly summary line (link + result
+ compact counts + duration) when ShowAssembly && ShowAssemblyStartAndComplete.
- AppendAssemblySummary/AppendAssemblyResult/AppendAssemblyTestCounts/AppendGlyphCount
porting the compact '[+P/xF/?S]' (ASCII) / '[checkP/xF/downS]' (ANSI) counts block,
with the '/rN' retry segment wired to TestProgressState.RetriedFailedTests.
- Orchestrator TestCompleted overload (assembly, tfm, arch, executionId, instanceId,
...) that updates per-assembly counts (delegates to the shared per-execution-id
path; instanceId-based retry attribution arrives in the retry slice).
- New TerminalResources.FailedWithErrors (resx + xlf + !IS_CORE_MTP accessor).
Ports the SDK's AssemblyRunCompleted_WithShowAssemblyStartAndComplete_PrintsPerAssemblyCounts
test (dotnet/sdk#52128) to MSTest, asserting the rendered '[+3/x0/?1]' counts block.
Stacked on #9263. Verified: platform clean net8.0/net9.0/netstandard2.0 (0 warnings);
full unit suite green (1200, 0 failed); standalone contract consumer compiles.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
MemberAuthor

🧪 Test quality grade — PR #9265

ΔTestGradeBandNotes
newTerminalTestReporterTests.
AssemblyRunCompleted_
WithShowAssemblyStartAndComplete_
PrintsPerAssemblyCounts
A90–100Clear AAA structure; assertion directly verifies the compact counts format [+3/x0/?1] against the arranged test outcomes.

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. · 250.2 AIC · ⌖ 13.1 AIC · ⊞ 43.7K · [◷]( · )

Copy link
Copy Markdown
MemberAuthor

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 Summary

Clean slice-by-slice implementation. The additive gating (ShowAssembly defaults off) correctly keeps the in-process host byte-identical. No blocking issues found. Two minor items and one informational note are left as inline comments.

Key correctness observations

  • TestProgressState is internal sealedRetriedFailedTests with public int / internal set does not widen the public API surface. No PublicAPI.Unshipped.txt entry needed. ✅
  • AssemblyRunCompleted orderingassemblyRun.Success is assigned beforeAppendAssemblySummary is called, so AppendAssemblyResult always sees the final success flag. ✅
  • Impossible switch arm(FailedTests > 0, TotalTests == 0) = (true, true) can never occur because every FailedTests++ is coupled with TotalTests++ in the TestCompleted switch. The (true, _) arm safely absorbs it. ✅
  • exceptions ?? [] — C# 12 collection-expression syntax; compiles correctly against all TFMs (compiler generates Array.Empty<T>() for older targets). ✅
  • XLF hygiene — PR description confirms files were regenerated via UpdateXlf, not hand-edited. Consistent with the repo's localization guidelines. ✅
  • Failure + ShowAssemblyStartAndComplete — On a non-zero exit code, both AppendAssemblySummary (counts line) and AppendExecutableSummary (full stdout/stderr) are printed. This is intentional and complementary (compact summary + verbose diagnostics). ✅

Verdict Table

#DimensionStatus
1Algorithmic Correctness✅ Pass
2Threading & Concurrency✅ Pass
3Security & IPC Contract Safety✅ Pass
4Public API & Binary Compatibility✅ Pass — all changed types are internal sealed; no PublicAPI.Unshipped.txt change needed
5Performance & Allocations✅ Pass
6Cross-TFM Compatibility✅ Pass
7Resource & IDisposable Management✅ Pass
8Defensive Coding at Boundaries✅ Pass
9Localization & Resources✅ Pass — FailedWithErrors added to .resx; XLF regenerated via UpdateXlf; hand-maintained TerminalResources.cs accessor present
10Test Isolation✅ Pass
11Assertion Quality✅ Pass — Assert.Contains is the correct MSTest assertion here
12Naming & Style✅ Pass
13XML Documentation⚠️ Minor — RetriedFailedTests summary says "Gets or sets" but the setter is internal (see inline)
14Error Handling✅ Pass
15Architecture & Designi️ Informational — four parameters in the orchestrator TestCompleted overload are intentionally dropped; documented but worth a call-site comment (see inline)
16MSBuild & Project File QualityN/A
17Logging QualityN/A
18Nullability Annotations✅ Pass
19Test Coverage⚠️ Major — AppendAssemblyResult's three failure branches and the /rN retry-count path have no test coverage (see inline)
20Dependency Management✅ Pass
21TelemetryN/A
22PowerShell & Script QualityN/A

Overall: COMMENT — no merge-blocking issues. The test-coverage gap (Dimension 19) is the most substantive finding; addressing it in the next slice or as a follow-up is recommended.

- Add tests for the three red AppendAssemblyResult branches (failed-with-errors,
zero-tests-ran, and process-failed-but-tests-passed) of the per-assembly summary line.
(The /r retried-count segment is exercised in the retry-counting slice, where
RetriedFailedTests is actually populated.)
- Fix the RetriedFailedTests XML doc ('Gets' - the setter is internal).
- Add a code comment at the orchestrator TestCompleted delegation noting the four
parameters reserved for the retry-attribution follow-up are intentionally not forwarded.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Base automatically changed from copilot/share-terminal-handshake-surface to mainJune 20, 2026 07:59
…l-per-assembly-counts
# Conflicts:
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Handshake.cs
#	src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.cs
#	test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.cs
CopilotAI review requested due to automatic review settings June 20, 2026 08:15
Remove the XML doc summary on TestProgressState.RetriedFailedTests: its 'internal set'
makes it read-only to any out-of-assembly consumer, and the sibling internal-set
counters (SkippedTests/TotalTests) carry no doc. (Keeping a 'Gets the number...' summary
would also violate SA1623, which requires 'Gets or sets' for a property with a setter.)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI 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 is slice 2/n of aligning testfx’s shared Microsoft.Testing.Platform terminal reporter with the dotnet/sdk orchestrator fork by (1) porting the SDK’s per-assembly counts oracle test and (2) implementing per-assembly completion summary rendering gated behind new ShowAssembly* options (default off).

Changes:

  • Added per-assembly completion summary line rendering (link + result + compact [+P/xF/?S] counts + duration) behind ShowAssembly && ShowAssemblyStartAndComplete.
  • Added an orchestrator-specific TestCompleted(...) overload plus state required for future retry attribution (RetriedFailedTests).
  • Added TerminalResources.FailedWithErrors across .resx + regenerated .xlf files and added new unit tests validating the new output.
Show a summary per file
FileDescription
test/UnitTests/Microsoft.Testing.Platform.UnitTests/OutputDevice/Terminal/TerminalTestReporterTests.csPorts the SDK oracle test for per-assembly counts and adds additional branch-coverage tests for per-assembly result strings.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TestProgressState.csAdds RetriedFailedTests state (used for future /r{N} rendering).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporterOptions.csIntroduces ShowAssembly and ShowAssemblyStartAndComplete flags to gate orchestrator-only behavior.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.TestCompletion.csAdds orchestrator TestCompleted(...) overload (currently delegates to execution-id path).
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Lifecycle.csEmits per-assembly completion summary line when the new options are enabled.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalTestReporter.Formatting.csImplements per-assembly summary line formatting, including compact counts block and result text selection.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.resxAdds FailedWithErrors resource string.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/TerminalResources.csAdds accessor for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.cs.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.de.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.es.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.fr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.it.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ja.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ko.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pl.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.pt-BR.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.ru.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.tr.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hans.xlfRegenerated localization entry for FailedWithErrors.
src/Platform/Microsoft.Testing.Platform/OutputDevice/Terminal/xlf/TerminalResources.zh-Hant.xlfRegenerated localization entry for FailedWithErrors.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 5

- Per-assembly count assertions now build the expected '[+P/xF/?S]' bracket via an
ExpectedCounts helper that formats with CultureInfo.CurrentCulture (matching the
reporter), so they stay correct under cultures with non-Latin digit shapes.
- Correct the ShowAssembly / ShowAssemblyStartAndComplete XML docs to describe only
the behavior implemented here (the mid-stream per-assembly summary line); drop the
references to the not-yet-implemented 'Running tests from' banner and the
final-summary per-assembly entries (which land in a later slice).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings June 20, 2026 08:32

CopilotAI 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: 21/21 changed files
  • Comments generated: 1

…le expression
Replace the manual foreach/return/throw in the GetAssemblySummaryLine test helper with
Array.Find(...) ?? throw, expressing the lookup as one expression.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink
Amaury Levé (Evangelink) merged commit 6b57fed into mainJun 20, 2026
20 of 23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the copilot/share-terminal-per-assembly-counts branch June 20, 2026 08:45
Sign up for freeto 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

@Evangelink