Skip to content

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Add passive command-line option defaults by Evangelink · Pull Request #10895 · microsoft/testfx · GitHub
Skip to content

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

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

Add passive command-line option defaults - #10895

Open
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults
Open

Add passive command-line option defaults#10895
Amaury Levé (Evangelink) wants to merge 1 commit into
mainfrom
dev/amauryleve/testing-platform-option-defaults

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Summary

  • add validated, passive commandLineOptionDefaults support to testconfig.json
  • expose TryGetOptionArgumentListOrDefault so extensions can consume defaults without enabling their feature
  • add generic TestingPlatformCommandLineOptionDefault MSBuild items that are projected into the built module configuration
  • use defaults for TRX and shared report filenames while preserving explicit CLI precedence
  • document both authoring surfaces and update the JSON schema

Validation

  • packed the repository successfully
  • passed Microsoft.Testing.Platform, Microsoft.Testing.Platform.MSBuild, and Microsoft.Testing.Extensions unit suites
  • passed TRX default/precedence acceptance tests across net462, net8.0, and net10.0
  • passed existing build/publish/configuration-file acceptance coverage

Fixes#6648

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f86614b5-b40f-415d-8f94-a3290fbe7154
CopilotAI balanced review requested due to automatic review settings August 31, 2026 18:19
@github-actions

Copy link
Copy Markdown
Contributor

🧵 Parallel-safety audit — PR #10895

Parallelization — assemblies touched by this PR's changed test files:

Test assemblyScopeWorkersAnalyzer coverage
Microsoft.Testing.Platform.Acceptance.IntegrationTestsMethodLevel ([assembly: Parallelize] in Program.cs)CPU count (Workers = 0)coverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.MSBuild.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)
Microsoft.Testing.Platform.UnitTestsMethodLevelCPU countcoverable once parallel-safety analyzers ship (attribute-based)

No .runsettings / testconfig.json opt-in overrides found for these projects, and this PR does not touch any parallelization-state file (Program.cs, .runsettings, testconfig.json, Directory.Build.props/targets) — the assembly-level [Parallelize(Scope = MethodLevel)] attributes are pre-existing and unchanged.

Findings: A (global-state) 0 · B (paths) 0 · C (declaration) 0 · D (over-serialization) 0 — by severity: Critical 0 · High 0 · Warning 0 · Info 0.

I reviewed every test added/modified by this PR across the three changed test files:

  • MSBuildTests.ConfigurationFile.cs — new test ConfigFileGeneration_OptionDefaultsGenerateConfigurationWithoutSourceFile uses TestAsset.GenerateAssetAsync(nameof(...), ...), which derives a per-test asset directory from the test name (unique across the suite) and TestHost.LocateFrom against that unique path — no shared filesystem path, no CWD mutation, no env-var mutation.
  • TrxTests.cs — new test Trx_CommandLineOptionDefault_IsPassiveAndExplicitValueWins clones the shared AssetFixture test host into a fresh, test-owned TempDirectory clone before writing testconfig.json or executing, so concurrent siblings (including other [DynamicData] TFM variants of the same test) do not collide on the same config file or results directory.
  • MSBuildTests.cs — new tests exercise ConfigurationFileTask purely through InMemoryFileSystem/Mock<IBuildEngine> instances created fresh per test method (no static/shared dictionary); no real I/O, no process-global state touched.
  • InvokeTestingPlatformTaskTests.cs — one-line addition of a StubFileSystem.ReadAllText no-op member; not exercised by any test logic.
  • CommandLineHandlerTests.cs, JsonCommandLineOptionsTests.cs — new tests build CommandLineHandler / AggregatedConfiguration instances from local mocks/local JSON strings only; no shared mutable fixture state, no statics.

No process-global mutation (env vars, CWD, culture, console), no shared/relative filesystem paths, and no [ResourceLock]/[DoNotParallelize] declaration changes were introduced. Nothing to flag for parallel-safety in this PR.

Advisory only — heuristic, non-blocking. Re-run with /parallel-audit. This audit answers "is it parallel-safe?"; for testability, smells, or flakiness see the detect-static-dependencies / test-smell-detection / test-anti-patterns analyses.

🤖 Automated content by GitHub Copilot. Generated by the Parallel-safety audit on PR (on open / sync) workflow. · auto · 85.4 AIC · ⌖ 4.48 AIC · ⊞ 24.8K · [◷]( · )

@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
5Performance & Allocations🟡 1 NIT
15Code Structure & Simplification🟡 1 NIT

✅ 20/22 dimensions clean.

Summary: This is a well-structured, thorough PR that adds passive commandLineOptionDefaults support to testconfig.json with clean separation between active options and defaults. The design is sound — defaults never activate features, explicit values take precedence, and the MSBuild integration via TestingPlatformCommandLineOptionDefault items is ergonomic.

Key positives:

  • Public API surface is minimal (one extension method + one internal interface)
  • PublicAPI.Unshipped.txt and InternalAPI.Unshipped.txt are both updated correctly
  • The #if NETCOREAPP / Jsonite split keeps the netstandard2.0 MSBuild task self-contained
  • Validation (unknown options, arity, bootstrap-only, per-arg) is consistently extended to the new section
  • Test coverage is comprehensive: unit tests for merge logic, defaults-don't-activate, explicit-wins, error cases; plus acceptance tests for both MSBuild generation and TRX runtime behavior
  • Localization resources and xlf files are properly updated
  • JSON schema updated to match

Minor observations (inline):

  • The MSBuild Inputs sentinels for option defaults may disable incremental build for this target — worth monitoring
  • CommandLineOptionsProxy delegates to the extension method which re-checks the interface cast (functionally correct, slightly indirect)

Comment on lines +19 to +21
bool ICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(string optionName, [NotNullWhen(true)] out string[]? arguments)
=> _commandLineOptions is null
? throw new InvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady)

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.

Dimension 15 – Code Structure (NIT):_commandLineOptions.TryGetOptionArgumentListOrDefault(...) resolves to the extension method on ICommandLineOptions, which will then check whether the target is ICommandLineOptionsWithDefaults again. It works correctly (the proxy delegates to the inner object which is typically CommandLineHandler), but the round-trip through the extension method is a small indirection. Calling the interface method directly would be slightly clearer:

boolICommandLineOptionsWithDefaults.TryGetOptionArgumentListOrDefault(stringoptionName,[NotNullWhen(true)]outstring[]?arguments)=>_commandLineOptionsisnull?thrownewInvalidOperationException(Resources.PlatformResources.CommandLineOptionsNotReady):_commandLineOptionsisICommandLineOptionsWithDefaultswithDefaults?withDefaults.TryGetOptionArgumentListOrDefault(optionName,outarguments):_commandLineOptions.TryGetOptionArgumentList(optionName,outarguments);

Not blocking — the current code is functionally correct.

Condition=" '$(GenerateTestingPlatformConfigurationFile)' == 'true' And (Exists('$(_TestingPlatformConfigurationFileSourcePath)') Or '@(TestingPlatformCommandLineOptionDefault)' != '') " >
<ConfigurationFileTask
MSBuildProjectDirectory="$(MSBuildProjectDirectory)"
AssemblyName="$(AssemblyName)"

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.

Dimension 5 – Performance (MODERATE): The sentinel Inputs items (__MTP_OPTION_DEFAULT__%(Identity)=%(Value)) are not real files, so MSBuild will always consider them non-existent and mark the target out-of-date on every build when any TestingPlatformCommandLineOptionDefault items are defined. This effectively disables incremental build for this target.

$(MSBuildAllProjects) already covers the case where a .props/.targets/.csproj file changes the item values, so the sentinels primarily address CLI-property overrides (/p:TrxFileName=x). One alternative to avoid the always-dirty state is to write a small stamp file alongside the output whose content is the hash/concatenation of the option default values, and use that as both Input and Output. Not blocking, but worth considering if build-perf feedback comes in.

Comment on lines +42 to +46
/// <see langword="true"/>. Extensions should use this method only after determining that the feature
/// which owns the option is enabled.
/// </remarks>
public static bool TryGetOptionArgumentListOrDefault(
this ICommandLineOptions commandLineOptions,

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.

Dimension 4 – Public API (NIT): The new CommandLineOptionsExtensions class is appropriately declared in PublicAPI.Unshipped.txt. One thing to note: the ArgumentNullException on commandLineOptions is good, but the optionName parameter is passed straight through without a null guard. The existing TryGetOptionArgumentList may or may not guard it internally. If consistency with the existing API is intentional (letting the downstream method throw), this is fine — just flagging for awareness.

Comment on lines +144 to +148
}

entry.Values.Add(item.GetMetadata("Value"));
valuesByOption[optionName] = entry;
}

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.

Dimension 6 – Cross-TFM Compatibility (NIT): The #if NETCOREAPP / #else split for System.Text.Json vs Jsonite is correctly applied. Good approach keeping the netstandard2.0 MSBuild task self-contained without a runtime JSON package dependency.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Expert test review — PR #10895

GradeTestMutationNotesHow to improve
A (90–100)new MSBuildTests.
ConfigurationFileTask_
MergesOptionDefaultsAndPreservesJsonOverrides
4/4 killedVerifies both the JSON-wins-over-MSBuild precedence and multi-value array merging via TryCreateMergedConfiguration.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
GeneratesConfigurationFromOptionDefaults
2/2 killedConfirms a config file is generated purely from MSBuild-supplied defaults with no source file present.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
RejectsOptionNameWithLeadingHyphens
2/2 killedAsserts both the failure result and the specific error message content for the guard clause.
A (90–100)new MSBuildTests.
ConfigurationFileTask_
ReportsDuplicateJsonKeys
2/2 killedExercises the case-insensitive duplicate-key detection path with a real malformed JSON fixture.
A (90–100)new MSBuildTests.
SelfRegisteredExtensions_
Fails_For_Duplicate_
BuilderHook_Ids_With_
Different_Metadata
3/3 killedChecks failure result, absence of output file, and exact conflicting-metadata error message.
A (90–100)new MSBuildTests.ConfigFileGeneration_
OptionDefaultsGenerateConfigurationWithoutSourceFile
3/3 killedEnd-to-end acceptance test proves defaults survive an actual build and a rebuild with an MSBuild property override.
A (90–100)new TrxTests.
Trx_CommandLineOptionDefault_
IsPassiveAndExplicitValueWins
3/3 killedVerifies passivity (no unwanted file), the configured default applying, and CLI override precedence in one flow.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
DefaultDoesNotActivateOption
2/2 killedDistinguishes IsOptionSet/TryGetOptionArgumentList staying false from the default-aware accessor returning the fallback.
A (90–100)new CommandLineHandlerTests.
GetOptionValueOrDefault_
ExplicitValueWins
2/2 killedConfirms explicit CLI configuration wins over a configured default, matching the production precedence.
A (90–100)new JsonCommandLineOptionsTests.
EnumerateCommandLineOptionDefaults_
ScalarsAndArrays_AreArguments
4/4 killedCovers scalar, boolean, and array default entries plus the providers-facing lookup helpers in one assertion set.
A (90–100)new JsonCommandLineOptionsTests.
ExplicitJsonDisable_
SuppressesConfiguredDefault
2/2 killedTargets the specific case of an explicit false override suppressing a configured default.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultPerArgValidatorFailure_
FailsWithDefaultsPrefix
3/3 killedConfirms the per-arg validator error message is prefixed distinctly for commandLineOptionDefaults vs plain JSON options.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultForZeroArityOption_Fails
2/2 killedVerifies zero-arity options reject a default value with the option name surfaced in the error.
A (90–100)new JsonCommandLineOptionsTests.
Validator_UnknownJsonDefault_Fails
2/2 killedUses a deliberate typo ("timoeut") to prove unknown default options are rejected by name.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonDefaultBootstrapOnlyOption_Fails
2/2 killedChecks bootstrap-only options are rejected as defaults with both the option name and "bootstrap" in the message.
A (90–100)new JsonCommandLineOptionsTests.
Validator_JsonBootstrapOnlyOption_
DisabledEntry_StillFails
2/2 killedExtends bootstrap-only coverage to the disabled-entry case with a clear rationale comment.

All reviewed tests directly exercise the passive command-line option defaults feature added in this PR (MSBuild TestingPlatformCommandLineOptionDefault items, JSON commandLineOptionDefaults, and the IsOptionSet/TryGetOptionArgumentListOrDefault precedence chain) against the actual production code paths, use specific expected values instead of generic truthy checks, and assert both success/failure results and diagnostic error message content. No high-confidence actionable findings were identified, so no inline suggestions were posted.

This advisory comment was generated automatically. Grades are heuristic and informational — they do not block merging. Suggestions on the Files changed tab can be applied with one click. Re-run with /review-tests.

🤖 Automated content by GitHub Copilot. Generated by the Test Reviewer on PR (on open / sync) workflow. · auto · 134.2 AIC · ⌖ 2.74 AIC · ⊞ 16.9K · [◷]( · )

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 3 Medium severity

New issues introduced by this change (3)
SeverityFinding
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targets — These transformed values are not real files, so MSBuild cannot use their timestamps as stable…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.cs — This shipped fallback is not as strict as the System.Text.Json branch. The package always loads the…
Medium severitysrc/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.cs — Reusing this enumerator also reuses its permissive empty-container behavior: empty arrays are…
What changed in this PR

Adds passive command-line option defaults across MTP configuration, MSBuild integration, and report filename handling, addressing #6648.

Changes:

  • Adds validated defaults with explicit-option precedence.
  • Projects MSBuild items into generated testconfig.json.
  • Applies defaults to report filenames and adds documentation/tests.
FileDescription
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​Configuration/​JsonCommandLineOptionsTests.csTests parsing and validation.
test/​UnitTests/​Microsoft.Testing.Platform.UnitTests/​CommandLine/​CommandLineHandlerTests.csTests passive lookup and precedence.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​MSBuildTests.csTests configuration merging.
test/​UnitTests/​Microsoft.Testing.Platform.MSBuild.UnitTests/​InvokeTestingPlatformTaskTests.csUpdates filesystem stub.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​TrxTests.csTests TRX defaults and precedence.
test/​IntegrationTests/​Microsoft.Testing.Platform.Acceptance.IntegrationTests/​MSBuildTests.ConfigurationFile.csTests MSBuild-generated defaults.
src/​Platform/​SharedExtensionHelpers/​ReportEngineBase.csApplies defaults to shared reporters.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hant.xlfUpdates Traditional Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.zh-Hans.xlfUpdates Simplified Chinese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.tr.xlfUpdates Turkish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ru.xlfUpdates Russian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pt-BR.xlfUpdates Portuguese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.pl.xlfUpdates Polish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ko.xlfUpdates Korean resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.ja.xlfUpdates Japanese resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.it.xlfUpdates Italian resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.fr.xlfUpdates French resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.es.xlfUpdates Spanish resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.de.xlfUpdates German resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​xlf/​PlatformResources.cs.xlfUpdates Czech resources.
src/​Platform/​Microsoft.Testing.Platform/​Resources/​PlatformResources.resxAdds defaults-specific diagnostics.
src/​Platform/​Microsoft.Testing.Platform/​PublicAPI/​PublicAPI.Unshipped.txtTracks the new public extension.
src/​Platform/​Microsoft.Testing.Platform/​InternalAPI/​InternalAPI.Unshipped.txtTracks internal API changes.
src/​Platform/​Microsoft.Testing.Platform/​Hosts/​TestHostBuilder.CommonServices.csLoads and validates defaults.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​PlatformConfigurationConstants.csDefines the defaults section name.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonConfigurationProvider.CommandLineOptions.csParses default entries.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​JsonCommandLineOptionEntry.csGeneralizes entry documentation.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​ConfigurationExtensions.csImplements default lookup and precedence.
src/​Platform/​Microsoft.Testing.Platform/​Configurations/​AggregatedConfiguration.csResolves defaults across providers.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​ICommandLineOptions.csExposes passive default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.UnknownAndBootstrapValidation.csValidates unknown/bootstrap defaults.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.csIntegrates default validation.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArityValidation.csValidates default arity.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsValidator.ArgumentAndConfigurationValidation.csValidates default arguments.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineOptionsProxy.csForwards default lookup.
src/​Platform/​Microsoft.Testing.Platform/​CommandLine/​CommandLineHandler.csImplements runtime default lookup.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Tasks/​ConfigurationFileTask.csMerges defaults into JSON.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​PACKAGE.mdDocuments authoring surfaces.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​Microsoft.Testing.Platform.MSBuild.csprojEmbeds Jsonite for down-level tasks.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​IFileSystem.csAdds configuration-file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​FileSystem.csImplements file reading.
src/​Platform/​Microsoft.Testing.Platform.MSBuild/​buildMultiTargeting/​Microsoft.Testing.Platform.MSBuild.targetsPasses defaults into generation.
src/​Platform/​Microsoft.Testing.Extensions.TrxReport/​TrxReportEngine.csApplies passive TRX filename defaults.
docs/​testconfig.schema.mdDocuments schema coverage.
docs/​testconfig.schema.jsonDefines defaults schema.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


<Target Name="_GenerateTestingPlatformConfigurationFileCore"
Inputs="$(_TestingPlatformConfigurationFileSourcePath)"
Inputs="@(_TestingPlatformConfigurationFileInput);@(TestingPlatformCommandLineOptionDefault->'__MTP_OPTION_DEFAULT__%(Identity)=%(Value)')"
Comment on lines +309 to +313
else if (Json.Deserialize(
source,
new JsonSettings
{
AllowComments = true,
Comment on lines +47 to +48
internal IReadOnlyList<JsonCommandLineOptionEntry> EnumerateCommandLineOptionDefaults()
=> EnumerateCommandLineOptionEntries(PlatformConfigurationConstants.CommandLineOptionDefaultsSectionName, allowBooleanMarkers: false);
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.

Microsoft.Testing.Extensions.TrxReport should allow customizing trx file name via dedicated MSBuild property

2 participants

@Evangelink