Analysis of commit fa9bbfa
Assignee: @copilot
Summary
Commit fa9bbfa introduced three new MSTest-native RunSettings provider classes that are near-identical copies of their counterparts in Microsoft.Testing.Extensions.VSTestBridge. The duplication was intentional (to avoid a VSTestBridge assembly dependency) but represents ~180 lines of structural duplication across 3 file pairs, each differing only in namespace, class name, and resource string references.
Duplication Details
Pattern: Mirrored RunSettings Provider Trio
- Severity: Medium
- Occurrences: 3 file pairs (~360 lines total, ~180 lines structurally duplicated)
- Locations:
| MSTest-native (new) |
VSTestBridge original |
src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsCommandLineOptionsProvider.cs (47 lines) |
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/CommandLine/RunSettingsCommandLineOptionsProvider.cs (52 lines) |
src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsConfigurationProvider.cs (74 lines) |
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Configurations/RunSettingsConfigurationProvider.cs (67 lines) |
src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsEnvironmentVariableProvider.cs (65 lines) |
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/TestHostControllers/RunSettingsEnvironmentVariableProvider.cs (55 lines) |
Code Sample (CommandLineOptionsProvider pair — nearly identical):
// VSTestBridge version
internal sealed class RunSettingsCommandLineOptionsProvider : CommandLineOptionsProviderBase
{
public const string RunSettingsOptionName = "settings";
private readonly IFileSystem _fileSystem;
public RunSettingsCommandLineOptionsProvider(IExtension extension)
: this(extension, new SystemFileSystem()) { }
internal RunSettingsCommandLineOptionsProvider(IExtension extension, IFileSystem fileSystem)
: base(extension, [new CommandLineOption(RunSettingsOptionName, ExtensionResources.RunSettingsOptionDescription, ArgumentArity.ExactlyOne, false)])
=> _fileSystem = fileSystem;
public override Task<ValidationResult> ValidateOptionArgumentsAsync(CommandLineOption commandOption, string[] arguments)
{
string filePath = arguments[0];
if (!_fileSystem.ExistFile(filePath))
return ValidationResult.InvalidTask(string.Format(..., ExtensionResources.RunsettingsFileDoesNotExist, filePath));
if (!RunSettingsProviderHelper.CanReadFile(_fileSystem, filePath))
return ValidationResult.InvalidTask(string.Format(..., ExtensionResources.RunsettingsFileCannotBeRead, filePath));
return ValidationResult.ValidTask;
}
}
// MSTest-native version — structurally identical, different class name and resource strings
internal sealed class MSTestRunSettingsCommandLineOptionsProvider : CommandLineOptionsProviderBase
{
// ... identical structure, uses PlatformAdapterResources instead of ExtensionResources
}
The same pattern repeats for ConfigurationProvider and EnvironmentVariableProvider.
Impact Analysis
- Maintainability: Any bug fix or enhancement to the VSTestBridge providers (e.g., new validation logic, new XPath query in
TryGet) must also be manually applied to the three MSTest-native copies.
- Bug Risk: High — divergence is already visible:
ConfigurationProvider uses string.IsNullOrEmpty while the bridge uses RoslynString.IsNullOrEmpty; constructor signatures differ slightly.
- Code Bloat: ~180 lines of logic duplicated across two assemblies.
Refactoring Recommendations
-
Extract to SharedExtensionHelpers (preferred)
- The project
src/Platform/SharedExtensionHelpers/ already hosts RunSettingsProviderHelper.cs shared between VSTestBridge and MSTest.
- Move the base/core logic for
CommandLineOptionsProvider, ConfigurationProvider, and EnvironmentVariableProvider into abstract or static helper classes in SharedExtensionHelpers.
- Both the VSTestBridge and MSTest assemblies can then derive/call these shared helpers.
- Estimated effort: Medium (2–4 hours).
- Benefits: Single place to fix bugs, consistent behavior, smaller binary size.
-
Make VSTestBridge providers internal protected / expose via shared contract
- If the VSTestBridge assembly is already referenced (or can be referenced) by MSTest.TestAdapter at build time only, expose the providers as
internal with InternalsVisibleTo.
- Estimated effort: Low (1 hour) — but requires verifying no circular dependency.
-
Accept duplication with a sync test (lowest risk)
- Add a Roslyn analyzer or a unit test that asserts the two sets of providers remain in sync (same validation logic).
- Estimated effort: Low (1–2 hours).
- Benefits: Catches divergence early without requiring a risky refactor.
Implementation Checklist
Analysis Metadata
- Analyzed Files: 6 source files
- Detection Method: Semantic code analysis + structural diff
- Commit: fa9bbfa
- Analysis Date: 2026-07-13
🤖 Automated content by GitHub Copilot. Generated by the Duplicate Code Detector workflow. · 50.3 AIC · ⌖ 5.35 AIC · ⊞ 8K · [◷]( · ◷)
Add this agentic workflow to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
Analysis of commit fa9bbfa
Assignee:
@copilotSummary
Commit
fa9bbfaintroduced three new MSTest-native RunSettings provider classes that are near-identical copies of their counterparts inMicrosoft.Testing.Extensions.VSTestBridge. The duplication was intentional (to avoid a VSTestBridge assembly dependency) but represents ~180 lines of structural duplication across 3 file pairs, each differing only in namespace, class name, and resource string references.Duplication Details
Pattern: Mirrored RunSettings Provider Trio
src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsCommandLineOptionsProvider.cs(47 lines)src/Platform/Microsoft.Testing.Extensions.VSTestBridge/CommandLine/RunSettingsCommandLineOptionsProvider.cs(52 lines)src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsConfigurationProvider.cs(74 lines)src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Configurations/RunSettingsConfigurationProvider.cs(67 lines)src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/MSTestRunSettingsEnvironmentVariableProvider.cs(65 lines)src/Platform/Microsoft.Testing.Extensions.VSTestBridge/TestHostControllers/RunSettingsEnvironmentVariableProvider.cs(55 lines)Code Sample (CommandLineOptionsProvider pair — nearly identical):
The same pattern repeats for
ConfigurationProviderandEnvironmentVariableProvider.Impact Analysis
TryGet) must also be manually applied to the three MSTest-native copies.ConfigurationProviderusesstring.IsNullOrEmptywhile the bridge usesRoslynString.IsNullOrEmpty; constructor signatures differ slightly.Refactoring Recommendations
Extract to
SharedExtensionHelpers(preferred)src/Platform/SharedExtensionHelpers/already hostsRunSettingsProviderHelper.csshared between VSTestBridge and MSTest.CommandLineOptionsProvider,ConfigurationProvider, andEnvironmentVariableProviderinto abstract or static helper classes inSharedExtensionHelpers.Make VSTestBridge providers
internal protected/ expose via shared contractinternalwithInternalsVisibleTo.Accept duplication with a sync test (lowest risk)
Implementation Checklist
Analysis Metadata
Add this agentic workflow to your repo
To install this agentic workflow, run