Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457) - #9709

Merged
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous
Jul 8, 2026
Merged

Let explicit --minimum-expected-tests govern the zero-tests verdict (#7457)#9709
Amaury Levé (Evangelink) merged 4 commits into
mainfrom
dev/amauryleve/curly-couscous

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

testfx side of #7457. Makes an explicit --minimum-expected-tests N govern the "zero tests ran" (exit code 8) verdict so that a dotnet test --test-modules / global-filter orchestrator can control the zero-tests behavior for the whole run rather than failing once per module.

Scope note: an earlier iteration also allowed the literal value --minimum-expected-tests 0 (from the now-collapsed #9724). That has been reverted — see "Why --minimum-expected-tests 0 was dropped" below — so this PR is limited to the verdict-governance change plus a defensive parse guard.

Problem

In TestApplicationResult.GetProcessExitCode() the ZeroTests (8) verdict was computed before and independently of--minimum-expected-tests, so --minimum-expected-tests N with zero tests returned 8, not 9. An orchestrator that normalizes a per-module 8 (empty module) could not distinguish "empty because the global filter matched nothing here" from "empty but the user asked for a stricter local minimum".

Change

An explicit --minimum-expected-tests N now governs the count-based verdict and supersedes ZeroTests(8): a run of fewer than N tests yields MinimumExpectedTestsPolicyViolation (exit code 9), even when zero tests ran. When the option is not set, the existing ZeroTests / --zero-tests-policy behavior is unchanged. (The value parse is guarded with a single-argument pattern match + int.TryParse.)

This is exactly what the dotnet test orchestrator (dotnet/sdk#55167) relies on to normalize a per-module 8 to success without swallowing a stricter per-module minimum forwarded via -- --minimum-expected-tests N, which now surfaces as exit code 9. Both dotnet test --minimum-expected-tests 10 -- --minimum-expected-tests 2 verdicts remain independently observable.

Why --minimum-expected-tests 0 was dropped

Allowing an explicit 0 created a UX divergence (originally raised in review): the exit code was 0 (success) but the terminal reporter still rendered a failed "Zero tests ran" verdict, because GetMinimumExpectedTests() returns 0 for both "unset" and "explicitly 0" and the shared verdict helpers couldn't tell them apart. Fixing that cleanly needs a change to TerminalTestReporterOptions.MinimumExpectedTests, which is vendored to dotnet/sdk (a cross-repo contract change).

Since allowing 0 is not required by the orchestrator design (that relies only on the "explicit N → exit 9" behavior above) and #7457 item #2 ("--min 0 == --ignore-exit-code 8") is already served by the existing --ignore-exit-code 8, we reverted the 0 support. Keeping 0 invalid preserves the unambiguous meaning of GetMinimumExpectedTests() == 0 ("unset") and avoids the divergence entirely. Tracking issue #9744 is closed as obsolete.

Tests

  • TestApplicationResultTests: --minimum-expected-tests N + zero tests → exit code 9.
  • ExecutionTests (acceptance): --filter-uid matching nothing + --minimum-expected-tests 3 → exit code 9.

Unit tests pass locally (TestApplicationResultTests + PlatformCommandLineProviderTests: 103/103). Acceptance tests require -pack and run in CI.

Related

Co-authored-by: Copilot App 223556219+Copilot@users.noreply.github.com

CopilotAI review requested due to automatic review settings July 7, 2026 15:28
Amaury Levé (Evangelink) added a commit that referenced this pull request Jul 7, 2026
Co-authored-by: Copilot App <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 (testfx side of #7457) makes --minimum-expected-tests take precedence over the "zero tests ran" (exit code 8) verdict in TestApplicationResult.GetProcessExitCode(). Previously the ZeroTests verdict was computed independently and always won for empty runs, and --minimum-expected-tests 0 was rejected by validation. Now an explicitly-provided --minimum-expected-tests governs the count-based verdict: 0 accepts an empty run (like --ignore-exit-code 8), while N with zero tests reports a minimum-expected violation (exit code 9) instead of 8. This is the enabling precondition for a dotnet test --test-modules orchestrator (SDK-side follow-up) to control zero-tests behavior for a whole run rather than per module.

Changes:

  • Allow --minimum-expected-tests 0 (validation now rejects only negative / non-integer values) and update the validation message wording.
  • When --minimum-expected-tests is set, use it to decide the count-based verdict and skip the ZeroTests/--zero-tests-policy branch; otherwise the existing zero-tests behavior is unchanged.
  • Regenerate localization (resx + 13 xlf) and add unit + acceptance coverage.
Show a summary per file
FileDescription
src/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.csCore change: explicit --minimum-expected-tests governs the verdict via an if/else, superseding the ZeroTests branch.
src/Platform/Microsoft.Testing.Platform/CommandLine/PlatformCommandLineProvider.csValidation relaxed from value <= 0 to value < 0 so 0 is accepted.
src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resxUpdated error message to "non-negative integer".
src/Platform/.../Resources/xlf/PlatformResources.*.xlf (13 files)Regenerated via UpdateXlf; source updated, targets marked needs-review-translation.
test/UnitTests/.../Services/TestApplicationResultTests.csAdded tests for min 0 + zero tests → Success and min N + zero tests → violation.
test/UnitTests/.../CommandLine/PlatformCommandLineProviderTests.cs0 now valid; negatives/non-integers invalid; renamed/added test cases.
test/IntegrationTests/.../ExecutionTests.csAcceptance coverage for zero-test scenarios via --filter-uid 2; updated validation-message expectation.
docs/Changelog-Platform.mdChangelog entry for the behavior change.

I verified the branching logic, argument-parsing safety (arity + Length==1 validation guards argumentList[0]), the test asset (uids 0/1, so --filter-uid 2 yields zero tests), and that no stale references to the old validation message remain. I also confirmed the terminal-reporter verdict divergence for --minimum-expected-tests 0 matches the intended --ignore-exit-code 8 equivalence. No blocking issues were found, but the change alters a shipped CLI option's exit-code semantics (a public behavioral contract) and coordinates with a cross-repo dotnet/sdk change, which warrants human sign-off.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0
  • Review effort level: Medium

…7457)
In TestApplicationResult.GetProcessExitCode(), an explicitly-provided
--minimum-expected-tests now governs the count-based verdict and supersedes
the ZeroTests (exit code 8) verdict: a run of fewer than N tests yields
MinimumExpectedTestsPolicyViolation (exit code 9) even when zero tests ran.
This lets a 'dotnet test --test-modules' orchestrator tell a stricter
per-module minimum (forwarded via '-- --minimum-expected-tests N') apart from
a module that simply matched no tests, which is the precondition for deciding
the 'zero tests ran' verdict at the whole-run level instead of per module.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
Comment threaddocs/Changelog-Platform.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 11:54

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 1
  • Review effort level: Medium

@Evangelink
Amaury Levé (Evangelink) marked this pull request as ready for review July 8, 2026 14:16
@Evangelink
Amaury Levé (Evangelink) enabled auto-merge (squash) July 8, 2026 14:17
- Defensively guard the --minimum-expected-tests value extraction in
TestApplicationResult.GetProcessExitCode() with a single-argument pattern
match plus int.TryParse, instead of indexing argumentList[0] and int.Parse
(which could throw if the option ever reached here present-but-empty or
non-integer). Malformed values now fall back to the zero-tests verdict;
they are still rejected earlier by option validation in practice.
- Fix changelog grammar: 'no test ran' -> 'no tests ran'.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 8, 2026 14:21

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.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

@github-actionsgithub-actionsBot 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.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

#DimensionVerdict
1Algorithmic Correctness🟡 1 MODERATE
21Scope & PR Discipline⚪ 1 NIT

✅ 20/22 dimensions clean.

  • Algorithmic Correctness — Terminal reporter verdict ("Zero tests ran" / IsRunFailed=true) diverges from exit code (Success) when --minimum-expected-tests 0 is used with an empty run. GetMinimumExpectedTests() returns 0 for both "not set" and "explicitly set to 0", so the terminal reporter can't distinguish the two and always shows the failure-like verdict. Low-priority follow-up.
  • Scope — Changelog entry for PR #9724 is included in this PR (#9709), coupling merge ordering.

Overall: The core logic change is correct and well-tested. The if/else refactoring cleanly separates the --minimum-expected-tests path from the --zero-tests-policy path, and the boundary condition change (<= 0< 0) correctly enables the zero-minimum scenario. Tests cover the key edge cases (zero with no tests → success, N>0 with no tests → violation). The --zero-tests-policy is silently superseded when --minimum-expected-tests is explicitly set, which is the documented intent.

No blocking issues.

Comment threaddocs/Changelog-Platform.md Outdated
Comment threadsrc/Platform/Microsoft.Testing.Platform/Services/TestApplicationResult.cs Outdated
@github-actions

This comment has been minimized.

Reverts the #9724 change that allowed the literal value
'--minimum-expected-tests 0'. Keeping '0' invalid restores an unambiguous
meaning for GetMinimumExpectedTests() == 0 ('option not set'), which avoids the
terminal-reporter verdict divergence tracked in #9744: with '--min 0' the exit
code was 0 (success) while the terminal still rendered a failed 'Zero tests ran'
verdict, because the shared verdict helpers could not distinguish 'unset' from
'explicit 0' without a cross-repo change to the vendored TerminalTestReporterOptions.
Issue #7457 item #2 ('--min 0 == --ignore-exit-code 8') remains served by the
existing '--ignore-exit-code 8'. The load-bearing behavior for the
'dotnet test --test-modules' orchestrator -- an explicit '--minimum-expected-tests N'
governs the zero-tests verdict (exit code 9, not 8) -- is unaffected and stays.
Co-authored-by: Copilot App <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.

Review details

  • Files reviewed: 4/4 changed files
  • Comments generated: 1
  • Review effort level: Medium

* Re-print errored assemblies in dotnet test end-of-run recap by @Evangelink in [#9545](https://github.com/microsoft/testfx/pull/9545)
* Add server-initiated session cancellation to the dotnet test IPC protocol by @Evangelink in [#9549](https://github.com/microsoft/testfx/pull/9549)
* Emit `::warning` annotations for skipped tests in `Microsoft.Testing.Extensions.GitHubActionsReport` by @Evangelink in [#9641](https://github.com/microsoft/testfx/pull/9641)
* Let an explicit `--minimum-expected-tests N` govern the zero-tests verdict, so a run of fewer than N tests reports the minimum-expected violation (exit code 9) instead of "zero tests ran" (exit code 8) even when no tests ran. This lets a `dotnet test --test-modules` orchestrator tell a stricter local-minimum violation apart from an empty module (#7457) by @Copilot in [#9709](https://github.com/microsoft/testfx/pull/9709)
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Test quality grade — PR #9709

GradeTestNotes
B (80–89)new ExecutionTests.
Exec_
WhenMinimumExpectedTestsIsSpecifiedAndNoTestsRun_
ResultIsMinimumExpectedTestsPolicyViolation
Single exit-code assertion correctly pins the behavioral contract; adding an AssertOutputContains check would give extra end-to-end confidence that the right diagnostic message is emitted.
B (80–89)new TestApplicationResultTests.
GetProcessExitCodeAsync_
If_
MinimumExpectedTests_
Set_
And_
No_
Tests_
Ran_
Returns_
MinimumExpectedTestsPolicyViolation
Correct equality assertion on exit code 9; method name contains "Async" but return type is void — low-priority naming inconsistency with the async siblings in the same class, no behavior impact.

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. Generated by the Grade Tests on PR (on open / sync) workflow. · 62.3 AIC · ⌖ 7.62 AIC · ⊞ 9.5K · [◷]( · )

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