Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Changelog-Platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ See full log [of v4.2.3...v4.3.0](https://github.com/microsoft/testfx/compare/v4
* 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 test 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)
* Allow `--minimum-expected-tests 0` so an explicit zero minimum accepts an empty run (same outcome as `--ignore-exit-code 8`), giving a per-module "zero tests is acceptable" opt-in (#7457) by @Copilot in [#9724](https://github.com/microsoft/testfx/pull/9724)

### Fixed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public static bool IsListTestsJsonOutput(ICommandLineOptions commandLineOptions)

private static Task<ValidationResult> IsMinimumExpectedTestsOptionValidAsync(CommandLineOption option, string[] arguments)
=> option.Name == MinimumExpectedTestsOptionKey
&& (arguments.Length != 1 || !int.TryParse(arguments[0], out int value) || value <= 0)
&& (arguments.Length != 1 || !int.TryParse(arguments[0], out int value) || value < 0)
? ValidationResult.InvalidTask(PlatformResources.PlatformCommandLineMinimumExpectedTestsOptionSingleArgument)
: ValidationResult.ValidTask;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<comment>{Locked="--list-tests"}{Locked="--minimum-expected-tests"}</comment>
</data>
<data name="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument" xml:space="preserve">
<value>'--minimum-expected-tests' expects a single non-zero positive integer value
<value>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</value>
<comment>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</comment>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Volitelně přijímá hodnotu „text“ (výchozí výstup čitelný pro člov
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">--minimum-expected-tests očekává jednu kladnou nenulovou celočíselnou hodnotu
<target state="needs-review-translation">--minimum-expected-tests očekává jednu kladnou nenulovou celočíselnou hodnotu
(např. --minimum-expected-tests 10).</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Akzeptiert optional „text“ (die standardmäsige lesbare Ausgabe) oder „jso
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">"--minimum-expected-tests" erwartet einen einzelnen positiven ganzzahligen Wert ungleich Null
<target state="needs-review-translation">"--minimum-expected-tests" erwartet einen einzelnen positiven ganzzahligen Wert ungleich Null
(Beispiel: "--minimum-expected-tests 10")</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Opcionalmente, acepta "text" (la salida legible por el usuario predeterminada) o
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests' espera un único valor entero positivo distinto de cero
<target state="needs-review-translation">'--minimum-expected-tests' espera un único valor entero positivo distinto de cero
(por ejemplo, '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Accepte éventuellement « text » (sortie lisible par l’humain par défaut)
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">« --minimum-expected-tests » attend une seule valeur entière positive différente de zéro
<target state="needs-review-translation">« --minimum-expected-tests » attend une seule valeur entière positive différente de zéro
(par exemple, « --minimum-expected-tests 10 »)</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Facoltativamente accetta ''text'' (output leggibile predefinito) o ''json'' per
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests' prevede un singolo valore intero positivo diverso da zero
<target state="needs-review-translation">'--minimum-expected-tests' prevede un singolo valore intero positivo diverso da zero
(ad esempio '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -592,9 +592,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests' には、0 以外の正の整数値が 1 つ必要です
<target state="needs-review-translation">'--minimum-expected-tests' には、0 以外の正の整数値が 1 つ必要です
(例: '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests'에는 0이 아닌 단일 양의 정수 값이 필요합니다.
<target state="needs-review-translation">'--minimum-expected-tests'에는 0이 아닌 단일 양의 정수 값이 필요합니다.
(예: '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Opcjonalnie akceptuje „text” (domyślne dane wyjściowe czytelne dla człowi
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">Opcja „--minimum-expected-tests” oczekuje pojedynczej niezerowej dodatniej liczby całkowitej
<target state="needs-review-translation">Opcja „--minimum-expected-tests” oczekuje pojedynczej niezerowej dodatniej liczby całkowitej
(np. „--minimum-expected-tests 10”)</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Opcionalmente, aceita 'text' (a saída legível por humanos padrão) ou 'json' p
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests' espera um único valor inteiro positivo diferente de zero
<target state="needs-review-translation">'--minimum-expected-tests' espera um único valor inteiro positivo diferente de zero
(por exemplo, '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">"--minimum-expected-tests" ожидает единственное ненулевое положительное целое значение
<target state="needs-review-translation">"--minimum-expected-tests" ожидает единственное ненулевое положительное целое значение
(например, "--minimum-expected-tests 10")</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests', sıfır olmayan tek bir pozitif tamsayı değeri bekler
<target state="needs-review-translation">'--minimum-expected-tests', sıfır olmayan tek bir pozitif tamsayı değeri bekler
(ör. '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">"--minimum-expected-tests" 应有单个非零正整数值
<target state="needs-review-translation">"--minimum-expected-tests" 应有单个非零正整数值
(例如 "--minimum-expected-tests 10")</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,9 +591,9 @@ Optionally accepts 'text' (the default human-readable output) or 'json' to print
<note />
</trans-unit>
<trans-unit id="PlatformCommandLineMinimumExpectedTestsOptionSingleArgument">
<source>'--minimum-expected-tests' expects a single non-zero positive integer value
<source>'--minimum-expected-tests' expects a single non-negative integer value
(e.g. '--minimum-expected-tests 10')</source>
<target state="translated">'--minimum-expected-tests' 需要單一非零的正整數值
<target state="needs-review-translation">'--minimum-expected-tests' 需要單一非零的正整數值
(例如 '--minimum-expected-tests 10')</target>
<note>{Locked="--minimum-expected-tests"}{Locked="--minimum-expected-tests 10"}</note>
</trans-unit>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,19 @@ public async Task Exec_WhenMinimumExpectedTestsIsNegative_ResultIsNotOk(string t
TestHostResult testHostResult = await testHost.ExecuteAsync("--minimum-expected-tests=-1", cancellationToken: TestContext.CancellationToken);

testHostResult.AssertExitCodeIs(ExitCode.InvalidCommandLine);
testHostResult.AssertOutputContains("Option '--minimum-expected-tests' has invalid arguments: '--minimum-expected-tests' expects a single non-zero positive integer value");
testHostResult.AssertOutputContains("Option '--minimum-expected-tests' has invalid arguments: '--minimum-expected-tests' expects a single non-negative integer value");
}

[DynamicData(nameof(TargetFrameworks.AllForDynamicData), typeof(TargetFrameworks))]
[TestMethod]
public async Task Exec_WhenMinimumExpectedTestsIsZeroAndNoTestsRun_ResultIsOk(string tfm)
{
var testHost = TestInfrastructure.TestHost.LocateFrom(AssetFixture.TargetAssetPath, AssetName, tfm);
// The uid filter matches no test, so zero tests run. An explicit '--minimum-expected-tests 0'
// accepts that empty run and supersedes the "zero tests ran" (exit code 8) verdict. See issue #7457.
TestHostResult testHostResult = await testHost.ExecuteAsync("--filter-uid 2 --minimum-expected-tests 0", cancellationToken: TestContext.CancellationToken);

testHostResult.AssertExitCodeIs(ExitCode.Success);
}

[DynamicData(nameof(TargetFrameworks.AllForDynamicData), typeof(TargetFrameworks))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,12 @@ public async Task IsInvalid_When_Both_FilterUid_And_TreenodeFilter_Provided()
}

[TestMethod]
[DataRow("0")]
[DataRow("-1")]
public async Task IsInvalid_When_MinimumExpectedTests_Is_Not_Positive(string minimumExpectedTests)
[DataRow("-5")]
[DataRow("abc")]
[DataRow("")]
[DataRow("1.5")]
public async Task IsInvalid_When_MinimumExpectedTests_Is_Negative_Or_Not_An_Integer(string minimumExpectedTests)
{
var provider = new PlatformCommandLineProvider();
CommandLineOption option = provider.GetCommandLineOptions().First(x => x.Name == PlatformCommandLineProvider.MinimumExpectedTestsOptionKey);
Expand All @@ -227,6 +230,19 @@ public async Task IsInvalid_When_MinimumExpectedTests_Is_Not_Positive(string min
Assert.AreEqual(PlatformResources.PlatformCommandLineMinimumExpectedTestsOptionSingleArgument, validateOptionsResult.ErrorMessage);
}

[TestMethod]
[DataRow("0")]
[DataRow("1")]
[DataRow("10")]
public async Task IsValid_When_MinimumExpectedTests_Is_NonNegative_Integer(string minimumExpectedTests)
{
var provider = new PlatformCommandLineProvider();
CommandLineOption option = provider.GetCommandLineOptions().First(x => x.Name == PlatformCommandLineProvider.MinimumExpectedTestsOptionKey);

ValidationResult validateOptionsResult = await provider.ValidateOptionArgumentsAsync(option, [minimumExpectedTests]).ConfigureAwait(false);
Assert.IsTrue(validateOptionsResult.IsValid);
}

[TestMethod]
public async Task IsValid_When_DiscoverTests_HasNoArgument()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,23 @@ TestApplicationResult testApplicationResult
Assert.AreEqual((int)ExitCode.MinimumExpectedTestsPolicyViolation, testApplicationResult.GetProcessExitCode());
}

[TestMethod]
public void GetProcessExitCodeAsync_If_MinimumExpectedTests_Zero_And_No_Tests_Ran_Returns_Success()
{
// An explicit `--minimum-expected-tests 0` accepts an empty run, superseding the ZeroTests (8)
// verdict. This is how a `dotnet test --test-modules` orchestrator flows "zero is acceptable for
// this module" down to each module. See issue #7457.
TestApplicationResult testApplicationResult
= new(
new Mock<IOutputDevice>().Object,
new CommandLineOption(PlatformCommandLineProvider.MinimumExpectedTestsOptionKey, ["0"]),
new Mock<IEnvironment>().Object,
new Mock<IStopPoliciesService>().Object,
null);

Assert.AreEqual((int)ExitCode.Success, testApplicationResult.GetProcessExitCode());
}

[TestMethod]
public void GetProcessExitCodeAsync_If_MinimumExpectedTests_Set_And_No_Tests_Ran_Returns_MinimumExpectedTestsPolicyViolation()
{
Expand Down
Loading