[VS Code] Add a command to scaffold Aspire integration test projects - #19622
[VS Code] Add a command to scaffold Aspire integration test projects#19622Ella Hathaway (ellahathaway) wants to merge 1 commit into
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19622Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19622" |
There was a problem hiding this comment.
Pull request overview
Adds end-to-end scaffolding of Aspire integration-test projects through the VS Code extension and CLI.
Changes:
- Adds AppHost discovery, CLI capability gating, and the VS Code command.
- Adds transactional CLI scaffolding with solution updates and rollback.
- Updates MSTest, NUnit, and xUnit templates plus unit and E2E coverage.
Reviewed changes
Copilot reviewed 102 out of 103 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tests/Aspire.Templates.Tests/TemplateTestsBase.cs |
Verifies generated AppHost wiring. |
tests/Aspire.Templates.Tests/PerTestFrameworkTemplatesTests.cs |
Expects generated tests to pass. |
tests/Aspire.Templates.Tests/NewUpAndBuildSupportProjectTemplatesTests.cs |
Tests special-character paths. |
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs |
Updates CLI test dependencies. |
tests/Aspire.Cli.Tests/TestServices/TestDotNetCliRunner.cs |
Extends the CLI runner fake. |
tests/Aspire.Cli.Tests/Templating/DotNetTemplateFactoryTests.cs |
Updates template discovery tests. |
tests/Aspire.Cli.Tests/Commands/NewCommandTests.cs |
Covers scaffolding and rollback. |
tests/Aspire.Cli.Tests/Commands/ConfigCommandTests.cs |
Verifies capability advertisement. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/IntegrationTest1.cs |
Generates an active xUnit test. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/Aspire.Tests.1.csproj |
Adds the AppHost reference. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/template.json |
Defines AppHost template symbols. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.zh-Hant.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.zh-Hans.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.tr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.ru.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.pt-BR.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.pl.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.ko.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.ja.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.it.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.fr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.es.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.en.json |
Adds symbol descriptions. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.de.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-xunit/.template.config/localize/templatestrings.cs.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/IntegrationTest1.cs |
Generates an active NUnit test. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/Aspire.Tests.1.csproj |
Adds the AppHost reference. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/template.json |
Defines AppHost template symbols. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.zh-Hant.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.zh-Hans.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.tr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.ru.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.pt-BR.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.pl.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.ko.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.ja.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.it.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.fr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.es.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.en.json |
Adds symbol descriptions. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.de.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-nunit/.template.config/localize/templatestrings.cs.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/IntegrationTest1.cs |
Generates an active MSTest test. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/Aspire.Tests.1.csproj |
Adds the AppHost reference. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/template.json |
Defines AppHost template symbols. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.zh-Hant.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.zh-Hans.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.tr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.ru.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.pt-BR.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.pl.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.ko.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.ja.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.it.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.fr.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.es.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.en.json |
Adds symbol descriptions. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.de.json |
Adds localized symbol entries. |
src/Aspire.ProjectTemplates/templates/aspire-mstest/.template.config/localize/templatestrings.cs.json |
Adds localized symbol entries. |
src/Aspire.Cli/Utils/ExtensionHelper.cs |
Advertises scaffolding capability. |
src/Aspire.Cli/Templating/ITemplate.cs |
Adds template completion metadata. |
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs |
Implements transactional scaffolding. |
src/Aspire.Cli/Projects/SolutionLocator.cs |
Exposes multi-solution discovery. |
src/Aspire.Cli/DotNet/DotNetCliRunner.cs |
Supports solution rollback. |
src/Aspire.Cli/Commands/NewCommand.cs |
Handles integration-test results. |
src/Aspire.Cli/Resources/TemplatingStrings.resx |
Adds CLI messages. |
src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs |
Exposes generated resources. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.zh-Hant.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.zh-Hans.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.tr.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.ru.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.pt-BR.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.pl.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.ko.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.ja.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.it.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.fr.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.es.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.de.xlf |
Adds localization units. |
src/Aspire.Cli/Resources/xlf/TemplatingStrings.cs.xlf |
Adds localization units. |
extension/src/utils/appHostDiscovery.ts |
Exports C# compatibility filtering. |
extension/src/utils/appHostCandidateSelection.ts |
Filters compatible AppHosts. |
extension/src/types/configInfo.ts |
Defines the capability token. |
extension/src/commands/addIntegrationTestProject.ts |
Implements the extension command. |
extension/src/data/AppHostDataRepository.ts |
Publishes compatible candidates. |
extension/src/activation/registerCliCommands.ts |
Registers the new command. |
extension/src/activation/instrumentedCommand.ts |
Adds palette telemetry source. |
extension/src/extension.ts |
Wires command dependencies. |
extension/src/loc/strings.ts |
Adds localized runtime strings. |
extension/src/test/addIntegrationTestProject.test.ts |
Tests command behavior. |
extension/src/test/appHostDataRepository.test.ts |
Tests candidate snapshots. |
extension/src/test/registerCliCommands.test.ts |
Tests command registration. |
extension/src/test/packageManifest.test.ts |
Tests manifest gating. |
extension/src/test/e2eLaunchProfile.test.ts |
Updates E2E runner contracts. |
extension/src/test-e2e/integrationTestProject.e2e.test.ts |
Exercises full scaffolding. |
extension/src/test-e2e/commandPalette.e2e.test.ts |
Verifies palette invocation. |
extension/src/test-e2e/packageSurface.e2e.test.ts |
Tracks the command surface. |
extension/src/test-e2e/helpers/fixtures.ts |
Adds scaffolding fixtures. |
extension/scripts/run-e2e.js |
Opens E2E workspace by URI. |
extension/package.nls.json |
Localizes manifest strings. |
extension/package.json |
Contributes and gates the command. |
extension/loc/xlf/aspire-vscode.xlf |
Updates extension localization catalog. |
.github/workflows/extension-e2e-tests.yml |
Adds Linux and Windows E2E shards. |
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
| { | ||
| "command": "aspire-vscode.addIntegrationTestProject", | ||
| "title": "%command.addIntegrationTestProject%", | ||
| "category": "Aspire", | ||
| "enablement": "aspire.workspaceHasCompatibleCSharpAppHost" |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 102 out of 103 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
tests/Aspire.Templates.Tests/TemplateTestsBase.cs:72
- This helper now always enables
WithAppHostReference, and all integration-template tests route through it. That leaves the defaultfalsebranch untested even though directdotnet new aspire-mstest/NUnit/xUnit use is explicitly meant to remain backward compatible. Add focused generation/build coverage without the AppHost symbols for each framework.
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:522
- Platform-qualified AppHost TFMs are forwarded verbatim here, but each integration-test template defines
Frameworkas a choice limited tonet8.0throughnet11.0. A valid AppHost targeting, for example,net10.0-windowswill therefore makedotnet newreject the framework instead of scaffolding a reference-compatible test project. The templates need an unrestricted internal TFM input (or equivalent support for platform-qualified TFMs), with coverage for this case.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 101 out of 102 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
Suppressed comments (2)
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:839
- The project rollback does not roll back the solution file. If cancellation or a nonzero exit occurs after
dotnet sln addhas written the solution, this path deletes the published test project but leaves a dangling solution entry, so the scaffolding is not transactional and cancellation can leave partial workspace changes. Preserve and restore the solution update (or otherwise make publication and solution mutation atomic) on both failure and cancellation.
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:522 - Forwarding the AppHost TFM verbatim makes scaffolding fail for valid platform-qualified AppHosts (for example
net10.0-windows): each integration-test template declaresFrameworkas a choice limited tonet8.0–net11.0, sodotnet newrejects any other value before generation. The AppHost-targeted path needs to accept the resolved TFM (including platform qualifiers), rather than passing it through the existing closed choice set.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 95 out of 96 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
Suppressed comments (3)
extension/src/commands/addIntegrationTestProject.ts:19
getAppHostPath()is not restricted to the compatible C# candidates used to enable this command: it can return an active TypeScript/Rust AppHost, and with no active editor it searches only the first workspace folder. Consequently the command can be enabled yet pass an unsupported path to the CLI or report no AppHost even when another workspace folder contains a compatible C# AppHost. Resolve the target from compatible C# candidates while preserving the Run command's selection precedence.
const appHostPath = await editorCommandProvider.getAppHostPath();
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:839
- If
dotnet sln addwrites the solution and is then cancelled or returns a failure, this rollback removes only the published project files. The solution is left with a dangling project entry, so cancellation/publication failure is not transactional. Preserve and restore the solution change (or explicitly remove the added entry) on both failure and cancellation, and test a runner that mutates the solution before failing.
src/Aspire.ProjectTemplates/templates/aspire-xunit/IntegrationTest1.cs:16 - The xUnit v2 branch passes
CancellationToken.NonetoCreateAsync, so the generated test can hang indefinitely before reaching the 30-secondWaitAsyncaroundBuildAsync. Use aCancellationTokenSource(DefaultTimeout)for v2 so AppHost discovery/build setup is bounded like the NUnit template.
9158b1a to
8e20e0a
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 92 out of 93 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
Suppressed comments (3)
src/Aspire.ProjectTemplates/templates/aspire-xunit/IntegrationTest1.cs:14
- For xUnit v2 this token is never cancellable.
CreateAsyncis awaited before the 30-secondWaitAsync, so a stalled AppHost construction can hang indefinitely and ignore test-run cancellation. Use the same timeout-backed token as the starter template.
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:524 - This forwards the exact evaluated AppHost TFM into the templates'
Frameworkchoice, but those symbols only acceptnet8.0throughnet11.0. A valid C# AppHost targeting a platform TFM such asnet10.0-windowsis therefore rejected bydotnet newbefore generation. The AppHost-aware path needs an unrestricted internal TFM symbol (or equivalent template wiring) so it can preserve any compatible AppHost TFM.
extension/src/commands/addIntegrationTestProject.ts:174 - The new user-visible command is only covered with mocked unit tests; the E2E change merely checks that its command ID is packaged. Nothing exercises the terminal handoff through the real CLI or verifies that the generated project builds and runs, so regressions in CLI selection, prompting, backchannel editor opening, or template publication can ship undetected. Add the extension E2E scenario required by the linked issue to invoke this command and create/build/run the project.
await terminalProvider.sendAspireCommandToAspireTerminal(
['new', 'aspire-test', '--apphost', shellArg(appHostPath)],
true,
undefined,
{ cliPath, target });
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
8e20e0a to
6128717
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 89 out of 90 changed files in this pull request and generated 3 comments.
Files not reviewed (1)
- src/Aspire.Cli/Resources/TemplatingStrings.Designer.cs: Generated file
Suppressed comments (2)
src/Aspire.Cli/Templating/DotNetTemplateFactory.cs:830
- Cancellation during
dotnet sln addcan occur after the solution file has been written but before the runner returns. The cancellation handler then deletes the published test project without restoring the solution, leaving a dangling project entry. Back up or stage the solution update and restore it on failure/cancellation as part of the same transaction.
var exitCode = await runner.AddProjectToSolutionAsync(
context.SolutionFile,
projectFile,
new ProcessInvocationOptions(),
cancellationToken);
extension/src/commands/addIntegrationTestProject.ts:137
- This relies on
getAppHostPath(), which returns no target for multiple unselected AppHosts and defaults to the first workspace folder when no editor is active. Therefore multiple AppHosts/workspace folders do not produce the explicit target picker required by #19409; the command remains hidden or reports no AppHost instead. Add an invocation-time picker for ambiguous candidates while keeping availability probing non-interactive.
const appHostPath = await editorCommandProvider.getAppHostPath();
if (!appHostPath) {
await vscode.window.showErrorMessage(noAppHostInWorkspace);
return;
This comment has been minimized.
This comment has been minimized.
6128717 to
9590fc9
Compare
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Adds an AppHost-aware Aspire CLI test template workflow and exposes it through a capability-gated VS Code command. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3a7314ab-4780-4472-bee8-f265bab3de94
9590fc9 to
4701c2d
Compare
| const supported = await configInfoProvider.hasCapability( | ||
| aspireTestAppHostCapability, | ||
| { | ||
| cliPath, | ||
| target, |
| Assert.Equal(0, res.ExitCode); | ||
| Assert.Matches("Passed! * - Failed: *0, Passed: *1, Skipped: *0, Total: *1", res.Output); |
| if (path.extname(appHostPath).toLowerCase() !== '.csproj') { | ||
| await vscode.window.showErrorMessage(addIntegrationTestProjectRequiresCSharpAppHost); | ||
| return; |
| "--WithAppHostReference", | ||
| "true", | ||
| "--AppHostProjectPath", | ||
| EscapeMSBuildItemValue(Path.GetRelativePath(outputPath, appHostProject.FullName)), |
Tests selector (audit mode)The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement. 3 / 102 test projects · 5 jobs, from 28 changed files. Selected test projects (3 / 102)
Selected jobs (5)
How these were chosen — grouped by what changed📦 affected project 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
Selection computed for commit |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Description
Adds an Aspire: Add integration test project command to the VS Code extension. The command reuses the same AppHost target selection as Run AppHost, resolves the CLI for that AppHost's workspace, and invokes:
The command is hidden unless the active workspace CLI advertises
aspire-test-apphost.v1. Invocation checks the capability again for the selected AppHost's exact CLI, so stale UI state cannot send--apphostto an unsupported CLI. Non-C# AppHosts are rejected before invocation.The CLI change is intentionally thin: it makes the existing grouped
aspire-testtemplate available by default, accepts--apphost, keeps the existing MSTest/NUnit/xUnit selection flow, and forwards the selected AppHost path and name to the chosen project template. Normalaspire newoutput handling, bundle extraction, and agent initialization remain unchanged.The three integration-test templates now optionally emit:
ProjectReferenceto the selected AppHost.AppHostBuildstest using the generatedProjects.*type.Direct use of the individual templates without AppHost symbols preserves the existing commented sample. When invoked from VS Code, the generated
IntegrationTest1.csopens in the editor.Screenshots / Recordings
Validation
The full template matrix cannot run on this ARM64 machine because the repository's packaged SDK/workload test directories are not installed.
Fixes #19409
Checklist