This file contains project-specific knowledge for AI agents working on the VSTest test platform.
VSTest is the test platform that powers dotnet test, Visual Studio Test Explorer, and Azure DevOps test tasks. It discovers and executes tests written with MSTest, xUnit, NUnit, and other frameworks.
vstest.console (entry point)
├── TestRequestManager (orchestration)
│ ├── ProxyDiscoveryManager ──IPC──► testhost (discovery)
│ ├── ProxyExecutionManager ──IPC──► testhost (execution)
│ └── ProxyOperationManager (shared IPC logic)
├── Translation Layer (bridges old/new handler interfaces for VS/AzDO)
└── Data Collectors (code coverage, blame, etc.)
Key IPC boundary: vstest.console and testhost communicate via JSON-RPC over stdin/stdout. Wire format changes must be backward-compatible.
| Directory | Purpose | Sensitivity |
|---|---|---|
src/Microsoft.TestPlatform.ObjectModel/ |
Public API surface (NuGet-shipped) | Binary compat critical |
src/Microsoft.TestPlatform.CommunicationUtilities/ |
JSON-RPC protocol, serialization | Wire compat critical |
src/Microsoft.TestPlatform.CrossPlatEngine/ |
Execution engine, parallel scheduling | Thread safety critical |
src/Microsoft.TestPlatform.CoreUtilities/ |
Shared utilities | Hot-path perf critical |
src/vstest.console/ |
CLI entry point, arg parsing, app.config | Binding redirects |
src/testhost*/ |
Test host processes | Assembly loading |
src/datacollector/ |
Data collector host | Binding redirects |
src/Microsoft.TestPlatform.Client/ |
Client-side test management | |
src/Microsoft.TestPlatform.Common/ |
Shared platform logic | |
src/Microsoft.TestPlatform.Extensions.*/ |
Loggers (HTML, TRX, blame) |
| Action | Windows | Linux / macOS |
|---|---|---|
| Restore + Build | ./build.cmd |
./build.sh |
| Build + Pack | ./build.cmd -pack |
./build.sh --pack |
| Release config | ./build.cmd -c Release -pack |
./build.sh -c Release --pack |
| Unit tests | ./test.cmd |
./test.sh |
| Specific tests | ./test.cmd -projects <pattern> |
./test.sh -p <pattern> |
| Smoke tests | ./test.cmd -projects smoke |
./test.sh -p smoke |
| Single test by name | ./test.cmd -bl -c release /p:TestRunnerAdditionalArguments="'--filter TestName'" |
Similar |
CI builds use -c Release. Always build with Release config before submitting PRs.
Test projects mirror source projects under test/:
src/Microsoft.TestPlatform.ObjectModel/ → test/Microsoft.TestPlatform.ObjectModel.UnitTests/
src/Microsoft.TestPlatform.CrossPlatEngine/ → test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/
src/vstest.console/ → test/vstest.console.UnitTests/
Test categories: Unit (fast, default), Smoke (P0 e2e), Acceptance (full e2e with --integrationTest).
Bumping a netstandard2.0 package cascades: transitive deps need binding redirects in ALL three app.configs (vstest.console/app.config, testhost.x86/app.config, datacollector/app.config). Miss one and you get FileLoadException in net462 DTA hosts.
After packaging changes, regenerate eng/expected-nupkg-file-counts.json and eng/expected-dll-frameworks.json from a clean Release build. Never hand-edit these files.
Assert.Contains(expected, actual) — first param is the needle. This is the opposite of old StringAssert. This has been a recurring mistake.
*.xlf files must be manually edited to match .resx changes. They are NOT auto-generated by the build.
- CI runs on Azure DevOps, not GitHub Actions
DOTNET_ROLL_FORWARD=LatestMajormasks version mismatches — don't rely on it- Doc-only PRs skip CI builds
- Windows builds finish first (~15 min), macOS/Ubuntu take longer
- Never commit to
main - Never force-push PR branches — squash-merge at the end
- Push to fork remote, PR against
microsoft/vstest - Don't create draft PRs — undrafting forces a rebuild
- Use
gh aw secrets setto manage secrets, NOTgh secret set. Plaingh secret setcreates the repo secret but gh-aw can't see it. - Two secrets needed:
COPILOT_GITHUB_TOKEN(Copilot API access) andGH_AW_GITHUB_TOKEN(repo interactions). - Workflow source files are
.mdin.github/workflows/. Compiled.lock.ymlfiles are generated — don't hand-edit them. - To recompile after editing a workflow:
gh aw compilefrom the repo root. .github/*andAGENTS.mdare excluded from CI path triggers — editing workflows won't trigger a full build.