Convert dotnet-format integration tests from pipeline YAML to MSTest/Helix#55399
Draft
MichaelSimons wants to merge 3 commits into
Draft
Convert dotnet-format integration tests from pipeline YAML to MSTest/Helix#55399MichaelSimons wants to merge 3 commits into
MichaelSimons wants to merge 3 commits into
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
MichaelSimons
force-pushed
the
format-timings
branch
3 times, most recently
from
July 21, 2026 22:49
7b94176 to
0c1956a
Compare
5 tasks
MichaelSimons
force-pushed
the
format-timings
branch
4 times, most recently
from
July 22, 2026 01:42
22500eb to
9a30324
Compare
…Helix Converts the dotnet-format integration test pipeline legs (YAML + PowerShell) into MSTest integration tests that run on Helix. This eliminates redundant SDK builds and reduces PR validation cost by ~92-127 agent-minutes per run. - New test project: test/dotnet-format.IntegrationTests/ using MSTest.Sdk - One test class per repo (SDK, Roslyn, MSBuild, ProjectSystem) - Dynamic Helix sharding via PartitionByClass metadata - Conditional test filtering via ConditionalTests.props DotnetFormat scope - Tests run only on Linux x64 (enforced at scheduling level) - Removed eng/dotnet-format/ (YAML template, PS1 verifier, CMD, RSP) - Fixed HelixTasks loop variable mutation bug in CreateHelixTestWorkItems.cs Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 14d64044-6feb-4ee6-a053-da4879c22885
MichaelSimons
force-pushed
the
format-timings
branch
from
July 22, 2026 01:49
9a30324 to
875dfd6
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ore trailing newline - FormatIntegrationTestBase: cache initialized repo paths in a static Dictionary<Type, string> so clone+Arcade restore+solution restore runs exactly once per concrete class per process. MSTest creates a new instance per test method, so without this setup ran twice per Helix work item. - UnitTests.proj: update stale comment on dotnet-format.UnitTests exclusion (was referencing the now-deleted DOTNET_FORMAT pipeline section). - ConditionalTests.props: restore missing trailing newline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Converts the dotnet-format integration test pipeline legs (YAML + PowerShell) into MSTest integration tests that run on Helix. This eliminates redundant SDK builds and reduces PR validation cost.
Compute Savings
Measured from build 1519902 (main, 2026-07-21):
Each old leg builds its own full SDK copy before running format. The new approach eliminates this by running as Helix work items on the existing Linux x64 build leg.
What changed
test/dotnet-format.IntegrationTests/using MSTest.Sdk with one test class per repo (SDK, Roslyn, MSBuild, ProjectSystem). Inherits from the MSTestSdkTestbase class for standard test infrastructure (logging, binlog arguments).FormatIntegrationTestBasehandles clone, Arcade restore, global.json manipulation, solution restore, and format execution with stdout validation. Adding or removing a repo requires only adding or deleting a ~15-line class.PartitionByClass=truemetadata causesAssemblySchedulerto discover test classes at scheduling time and create one Helix work item per class automatically.ConditionalTests.propsDotnetFormatscope with trigger paths. Tests run in PR validation only when relevant files change; they always run in CI.UnitTests.projscheduling level, not in test code).eng/dotnet-format/(YAML template, PowerShell verifier, CMD wrapper, RSP file) and removed pipeline references from.vsts-ci.yml/.vsts-pr.yml.Design
Each repo is a separate test class inheriting from
FormatIntegrationTestBase:This one-class-per-repo pattern enables:
Test lifecycle (mirrors the old
format-verifier.ps1)eng/Build.ps1 -restore(oreng/build.sh --restore) whileglobal.jsonis intact to install Arcade SDK toolingmsbuild-sdksfor NuGet SDK resolver but forces the SDK under test to be usednuget.configdotnet format <solution> --no-restore --verify-no-changes --verbosity detaileddotnet format whitespace <path> --folder --verify-no-changes --verbosity detailedRepos dropped
AspNetCore and EfCore: These repos are restore-intensive and not feasible to run on Helix. The ROI is questionable for a format validation check.
Bug fixes included
CreateHelixTestWorkItems.cs): Theargumentsvariable was being mutated inside the partition loop, causing"-- "prefix to accumulate on each iteration. Fixed by computingformattedArgumentsonce before the loop.EvaluateConditionalTestScopes.cs): TheValidatePatternBaseDirmethod extracted the base directory by taking the prefix before the first wildcard and trimming trailing slashes. For patterns liketest/dotnet-format.*/**, this producedtest/dotnet-format.as the base directory (which doesn't exist), causing validation to fail. Fixed by truncating to the last/before the first wildcard character, so the base directory istest(which exists). Added a unit test for this case.