
Aspire CLI 端到端测试指南基于 Hex1b 终端自动化的 E2E 测试体系与 CI 并行矩阵【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire本文档围绕 Aspire 仓库中的 CLI 端到端测试项目展开系统讲解如何利用 Hex1b 终端自动化库模拟真实用户与aspire命令行的交互、如何按测试类拆分 CI 任务实现并行执行、如何编写与运行这类 E2E 测试以及如何在不修改任何 CI 配置的情况下自动纳入新的测试类。读完本文你将掌握该测试项目的完整架构、测试类模板、交互辅助方法与本地/CI 运行全流程。项目定位与测试目标tests/Aspire.Cli.EndToEnd.Tests是 Aspire 仓库中专门针对 Aspire CLI 的端到端End-to-End简称 E2E测试项目。与普通单元测试不同这类测试不 mock 终端或命令层而是通过 Hex1b 终端自动化库真正地打开一个伪终端PTY在 shell 中逐字键入aspire ...命令、观察终端输出、响应交互式提示从而模拟用户操作 CLI 的完整链路。从仓库中 80 多个测试类可以看出其覆盖面aspire new/init模板脚手架CSharpInitTests.cs、TypeScriptStarterTemplateTests.cs、aspire run/stop生命周期StartStopTests.cs、部署到 Kubernetes/Docker/Podman/RadiusKubernetesDeployWithPostgresTests.cs、DockerDeploymentTests.cs、资源命令ResourceCommandTests.cs、doctor/logs/ps等诊断命令以及配置迁移、遥测、横幅展示等行为。这些测试的目标是验证 CLI 在真实终端环境下的完整行为包括交互提示、退出码、文件系统副作用与进程生命周期。测试架构测试基础设施整个测试项目建立在三个关键组件之上CliEndToEndTestBase所有 E2E 测试类的基类提供 Hex1b 终端初始化、工作目录管理与通用辅助方法。虽然该类在仓库中位于共享代码Hex1bTestHelpers.cs 中对应Hex1bTestHelpers静态辅助类提供终端创建与提示符检测其核心职责是一致的为每个测试准备一个独立的、可复现的终端会话。HeadlessPresentationAdapter无显示环境下的终端渲染适配器使测试可以在没有图形界面的 CI 容器中运行并用 asciinema 格式录制终端会话。TestEnumerationRunsheetBuilder统一的 MSBuild targets见 TestEnumerationRunsheetBuilder.targets在SplitTestsOnCItrue的项目中提取测试类并生成每个类对应的 runsheet测试运行清单。终端会话的底层创建方式共享辅助类Hex1bTestHelpers.CreateTestTerminal展示了终端会话的具体配置Hex1bTestHelpers.cs以headless模式创建终端默认尺寸 160 列 × 48 行开启asciinema 录制.cast文件CI 中录制文件写入$GITHUB_WORKSPACE/testresults/recordings/并作为工件上传本地则写入TestResults/recordings/目录通过WithPtyProcess(/bin/bash, [--norc])启动真实的 bash 伪终端进程不加载 rc 文件以保证环境干净。录制文件按 xUnit 报告的测试方法名命名[CallerMemberName]回退机制见 ResolveTestMethodName确保.cast文件能与 TRX 测试结果按名称关联供 CI 上的录制评论工作流使用。提示符同步机制终端自动化最大的难点是何时可以执行下一条命令。共享辅助类通过SequenceCounter与 bash 提示符模式匹配解决这一问题Hex1bTestHelpers.csWaitForSuccessPrompt等待形如[N OK] $的成功提示符N 为递增的序列号命令成功后继续WaitForErrorPrompt等待[N ERR:{exitCode}] $的错误提示符用于验证命令以指定非零退出码失败WaitForAnyPrompt同时接受成功或错误提示用于不关心退出码的场景。默认等待超时为 500 秒足以覆盖aspire new创建项目dotnet new还原与构建在慢速 CI 环境下的耗时。CI 流水线与并行矩阵README 明确指出每个测试类在 CI 中作为独立的 job 运行从而在 GitHub Actions runner 上实现并行执行。这与一个测试类 一个 CI job的设计直接对应测试项目 csproj 中的SplitTestsOnCItrueAspire.Cli.EndToEnd.Tests.csproj。整个流水线分三个阶段发现阶段Discovery PhaseTestEnumerationRunsheetBuilder构建测试项目并调用GenerateTestPartitionsForCItarget 发现所有测试类。该 builder 默认跳过tests/Shared、tests/testproject等非测试项目目录且仅当IncludeCliE2ETeststrue时才包含本项目见 TestEnumerationRunsheetBuilder.targets矩阵生成Matrix Generation为每个唯一测试类创建一个矩阵条目并按目标平台展开并行执行Parallel ExecutionGitHub Actions 为每个测试类创建独立 job在不同 agent 上并行运行。架构示意如下┌─────────────────────────────────────────────────────────────────┐ │ generate_cli_e2e_matrix │ │ Discovers test classes and generates runsheet │ └─────────────────────────────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ build_packages │ │ Builds NuGet packages needed for tests │ └─────────────────────────────────────────────────────────────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ Job 1 │ │ Job 2 │ │ Job N │ │ NewCmd │ │ RunCmd │ │ ... │ │ Tests │ │ Tests │ │ │ └───────────┘ └───────────┘ └───────────┘从测试项目 csproj 可以进一步确认 CI 相关的平台策略Aspire.Cli.EndToEnd.Tests.csproj仅在 GitHub Actions Linux 上运行RunOnGithubActionsLinuxtrueWindows 与 macOS 均关闭不在 Helix 与 AzDO CI agent 上运行RunOnAzdoHelixWindows/Linux、RunOnAzdoCIWindows/Linux均为 falseTestClassNamePrefixForCI设置为Aspire.Cli.EndToEnd.Tests用于 CI 矩阵中按命名空间过滤测试类测试会话超时 30 分钟、挂起超时 15 分钟TestSessionTimeout30m、TestHangTimeout15m项目需要已构建的 NuGet 包RequiresNugetstrue、CLI 归档RequiresCliArchivetrue与 GitHub TokenRequiresGitHubTokentrue。编写 E2E 测试测试类结构每个测试类必须遵循以下约定README 原文要求继承自CliEndToEndTestBase实现IAsyncLifetime以支持正确的 setup/teardown在InitializeAsync中调用await base.InitializeAsync()在DisposeAsync中调用await base.DisposeAsync()。标准模板如下public sealed class MyCommandTests : CliEndToEndTestBase, IAsyncLifetime { public async Task InitializeAsync() { await base.InitializeAsync(); } async Task IAsyncLifetime.DisposeAsync() { await base.DisposeAsync(); } [Fact] public async Task MyCommand_DoesExpectedThing() { // Use the helper methods to interact with the CLI await RunAspireAsync(my-command --option value); await WaitAsync(2000); // Assert on file system changes, process output, etc. } }可用辅助方法方法作用RunAspireAsync(string arguments)在终端中运行aspire argumentsTypeAndEnterAsync(string text)键入文本并按下回车WaitAsync(int milliseconds)等待指定时长CreateSequence()创建Hex1bTerminalInputSequenceBuilder用于复杂交互WorkDirectory当前测试独有的临时目录复杂交互对于交互式提示与复杂的终端操作使用CreateSequence()构造输入序列var sequence CreateSequence() .SlowType(aspire new) .Enter() .Wait(2000) .Key(Hex1bKey.DownArrow) // Navigate menu .Enter() // Select option .SlowType(myproject) // Enter project name .Enter() .Build(); await sequence.ApplyAsync(Terminal);更贴近源码的交互方式Automator 与序列构建器在实际测试中交互被进一步封装。以 SmokeTests.cs 的CreateAndRunAspireStarterProject为例一个完整的创建并运行 Starter 项目流程为获取仓库根目录CliE2ETestHelpers.GetRepoRoot()检测 CLI 安装策略CliInstallStrategy.Detect支持本地/归档/Docker 多种安装方式创建临时工作区TemporaryWorkspace.Create创建 Docker 测试终端CreateDockerTestTerminal可挂载 Docker socket通过Hex1bTerminalAutomator依次执行PrepareDockerEnvironmentAsync→InstallAspireCliAsync→AspireNewAsync(AspireStarterApp, counter)→ 运行aspire run等待 Press CTRLC to stop the AppHost and exit. 出现确认应用启动成功发送 CtrlC 停止 AppHost等待成功提示符。共享辅助类还提供了针对aspire new完整交互流程的封装AspireNewHex1bTestHelpers.cs它按步骤等待模板列表、选择模板Starter / JsReact / ExpressReact / PythonReact / EmptyAppHost / TypeScriptEmptyAppHost / JavaEmptyAppHost、输入项目名、接受默认输出路径、处理*.dev.localhostURL 询问、Redis 缓存询问与测试项目询问最后拒绝 agent init 确认提示。AspireInit则封装了aspire init --language csharp及 NuGet.config 提示的处理。这意味着当aspire new的提示发生变化时只需修改这一处共享封装而不必逐个改动测试。CellPatternSearcher是核心的终端屏幕匹配工具通过Find(text)/FindPattern(...)/RightText(...)组合匹配终端快照中的单元格模式WaitUntil则轮询快照直到匹配成功或超时。运行测试npm 测试依赖的版本管理README 特别强调项目级package.jsonpackage.json对 npm 工具的版本固定作用ViteTestHelpers.GetCreateCommand从该清单读取create-vite版本当前固定为9.2.0而不是使用vitelatest该清单以嵌入式资源方式编译进测试程序集见 csproj 中的EmbeddedResource Includepackage.jsonAspire.Cli.EndToEnd.Tests.csproj因此本地运行与 CI 测试归档使用同一版本本地无需为清单执行npm installDependabot 每周检查该目录并在提出新版本前等待七天冷却期避免采纳刚发布、其依赖可能被 Deno 最低依赖年龄策略拒绝的 Vite 模板清单中的工具版本必须保持精确exact且应使用共享辅助方法而不是在单个测试中内嵌版本号。构建与运行命令# Build the test project ./build.sh -restore -build -projects tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj # Run all tests dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj # Run a specific test class dotnet test tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj -- --filter-class Aspire.Cli.EndToEnd.Tests.AspireNewCommandTests注意--filter-class过滤器用于精确指定某个测试类若要按特性或其它条件筛选可使用 xUnit v3 的标准--filter语法。运行环境要求README 列出的硬性要求如下这与 csproj 中的平台开关完全一致仅限 LinuxHex1b 需要 Linux 终端环境测试在 Windows 和 macOS 上跳过csproj 中RunOnGithubActionsWindows/RunOnGithubActionsMacOS均为 false且 Helix 与 AzDO 均不运行Aspire CLI 已安装aspire命令必须位于 PATH 中已构建 NuGet 包测试运行前需要先构建 Aspire 相关包csproj 中RequiresNugetstrue、TestUsingWorkloadstrue。此外从源码可以补充两点实现细节测试会话超时TestSessionTimeout30m与挂起超时TestHangTimeout15m防止 CI 任务无限挂起由于 Hex1b 包未签名csproj 显式设置了SignAssemblyfalse以禁用强名称签名Aspire.Cli.EndToEnd.Tests.csproj。添加新的测试类添加新测试类非常轻量只需三步创建新文件命名遵循Aspire*Tests.cs或*CommandTests.cs模式仓库中现有如BannerTests.cs、DescribeCommandTests.cs、DoctorCommandTests.cs、KubernetesPublishTests.cs等遵循上文测试类结构一节的标准模板继承基类、实现IAsyncLifetime、调用 base 的初始化与释放CI 会自动发现并以独立 job 运行新测试——无需修改任何 CI 配置。其自动化的原理在于TestEnumerationRunsheetBuilder会自动发现所有设置了SplitTestsOnCItrue的项目中的测试类TestEnumerationRunsheetBuilder.targets。该 builder 属于 class-mode 项目按类枚举会针对程序集构建后逐一提取测试类生成 runsheet再交由build-test-matrix.ps1展开为矩阵。完整机制可参考仓库内的 TestingOnCI.md 文档。从TestEnumerationRunsheetBuilder.targets的实现可以进一步确认对于Aspire.Cli.EndToEnd.Tests这类 class-mode 项目构建器会走Build class discovery路径而对于使用[Trait(Partition,n)]分区特性的项目则优先通过源码扫描无需编译整个闭包直接提取分区值并始终追加uncollected:*条目兜底保证任何未被扫描到的类都不会被遗漏。测试样例参考以下仓库内现成的测试类可作为编写新测试的最佳参照SmokeTests.cs创建并运行 Starter 项目、SSH 重定向输出等冒烟场景BannerTests.cs验证首次运行横幅与--banner显式标志通过删除~/.aspire/cli/cli.firstUseSentinel哨兵文件模拟首次运行并断言RootCommandStrings.BannerWelcomeText与 Telemetry 文案出现DotnetToolSmokeTests.cs验证以dotnet tool方式安装的 CLI各KubernetesDeploy*Tests.cs部署类测试通常包含CaptureWorkspaceOnFailure特性——测试失败时自动捕获工作区状态以辅助排查。小结Aspire CLI E2E 测试项目通过 Hex1b 终端自动化实现了对 CLI 真实交互行为的全面验证其一个测试类 一个 CI job的矩阵设计保证了大规模并行执行效率而TestEnumerationRunsheetBuilder的自动发现机制让新增测试几乎零配置。对于想要为该测试套件贡献新用例的开发者只需遵循本文的类结构模板、复用共享辅助方法终端创建、提示符同步、AspireNew/AspireInit交互封装即可快速编写出稳定、可维护、可并行执行的端到端测试。【免费下载链接】aspireAspire is the tool for code-first, extensible, observable dev and deploy.项目地址: https://gitcode.com/GitHub_Trending/as/aspire创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考