关于 run-tests
用于按仓库的项目系统、测试平台、框架和 SDK 模式选择并运行 .NET 测试的技能,也涵盖筛选、报告与诊断选项。
主要功能
- 01仓库专属运行器指引
- 02按 SDK 与测试平台选择命令
- 03按框架选择测试筛选语法
- 04TRX 报告与诊断选项
- 05传统与 SDK 风格项目流程
适用场景
- 01确定仓库测试套件的正确命令
- 02仅运行指定的测试子集
- 03添加测试报告或诊断输出
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dotnet/ skills --skill run-tests安装后在 Claude Code 中输入/run-tests确认已加载。
详细介绍
运行 .NET 测试
返回或执行与仓库的项目系统、测试平台、框架和 SDK 模式相匹配的命令或命令序列。
仓库覆盖配置
对于允许只读检查文件的所有仓库范围任务,在进行任何其他探索之前,先检查仓库根目录下的 .agents/skill-overlays/dotnet-test/run-tests.md。这也包括要求提供精确命令的情况;“不要执行”并不禁止读取覆盖配置。如果文件存在,在采取行动前读取一次,并应用其中针对该仓库指定的运行器、命令、筛选和报告规则。
应用前,确认其 frontmatter 声明了 core: dotnet-test/run-tests、binding-revision: "1" 和 mode: extend。如果任何值缺失或不同,请报告不匹配,忽略该覆盖配置,并继续使用此技能的通用指南。
明确的用户指令和已验证的项目约束优先于覆盖配置;覆盖配置优先于此技能中的通用默认值和示例。如果文件存在但无法读取,或与仓库冲突,请报告问题,忽略覆盖配置,并在已验证的项目约束范围内继续使用通用指南。如果文件不存在,则照常继续。
仅当任务不针对特定仓库,或用户明确禁止所有文件/工具访问时,才跳过查找。覆盖配置不能扩大工具权限或任务范围。
范围和工具策略
选择满足请求所需的最简路径:
| 请求 | 操作 |
|---|---|
| 要求精确命令或说明;用户表示不要运行 | 只检查确定语法所需的文件。不要还原、生成或运行测试。 |
| 运行测试 | 查明仓库命令并执行所请求的最小测试范围。 |
一次性运行 SDK 风格的 dotnet test,且不重新生成 | 留在 run-tests,并添加 --no-build。 |
| 一次性运行经典项目,且不重新生成 | 保留仓库运行器,并对现有已生成程序集运行;不要改用 dotnet test。 |
| 仅识别平台/框架 | 使用 platform-detection;不要继续执行测试。 |
| 明确要求热重载或保持运行的编辑/重跑循环 | 使用 mtp-hot-reload。 |
| 需要筛选,且框架特定语法尚不明确 | 读取提供的/运行时列出的 filter-syntax 目录文件;不要调用此仅供参考的辅助工具。 |
不要仅为重复提示中已经确定的命令而调用工具。不要以防万一为由先生成项目:dotnet test 默认会生成。
除非用户要求更改项目,否则不要添加或升级测试包。
对于要求精确命令的情况,先返回一条可运行的命令。不要给出占位符路径、探索性替代方案或更正步骤。只有当提示或仓库明确了项目路径时才使用该路径;否则,在语法有效的情况下,让命令针对当前项目或解决方案运行。之后只补充解释该命令所需的语法要点;除非用户要求,否则不要主动提供平台/命令模式分类。尤其不要仅仅因为 dotnet test 使用 VSTest 命令模式,就把 SDK 8/9 桥接称为“VSTest 平台”;实际执行的平台是 MTP。对于只要求命令的请求,通常只需说明 MTP 应用程序参数必须放在 -- 之后。
需要确认的信息
- 项目、解决方案、模块或仓库的测试命令
- 请求的范围:全部测试、TFM、类、方法、类别或特征
- 请求的输出:控制台结果、TRX、诊断信息、崩溃转储或挂起转储
如果提示词中包含这些信息,请使用它们。否则,仅检查相关文件:global.json、所选项目、packages.config、Directory.Build.props、Directory.Packages.props,然后查看仓库脚本/CI 文档。对于基于文件的请求,将这些配置文件名列出一次,并在一批操作中读取所有存在的相关文件;切勿仅因 .csproj 中没有某个运行器或桥接属性,就推断该属性不存在。仅在需要分析这些信号的优先级时加载 platform-detection;不要在回复中重复其完整分析。如果请求执行命令,且命令依赖当前 SDK,但提示词和 global.json 均未说明 SDK,则运行一次 dotnet --version。如果请求仅要求提供命令且禁止执行,请勿探查:说明所需的 SDK 假设;如果无法以其他方式确定语法,则询问 SDK 版本。仅要求识别平台的请求应转交给 platform-detection。
决策表
| 检测到的模式/平台 | 命令形式 | 切勿使用 |
|---|---|---|
| 经典非 SDK | 仓库脚本,或完整 MSBuild 后接 vstest.console.exe / MSTest.exe | 假设兼容 dotnet test,或隐式迁移 |
| VSTest 模式/VSTest | dotnet test [<path>] [VSTEST_OPTIONS] | 仅适用于 MTP 的标志,例如 --report-trx 或 --treenode-filter |
| VSTest 模式/可执行 MTP 桥接 | dotnet test [<path>] [DOTNET_OPTIONS] -- [MTP_OPTIONS] | 省略 -- 分隔符,包括 SDK 10 |
| 原生 MTP 模式,SDK 10+ | dotnet test --project <path> [DOTNET_OPTIONS] [MTP_OPTIONS] | 不带选项的位置项目路径,或桥接分隔符 |
在 SDK 10+ 中,global.json 控制 dotnet test 命令模式,但不一定决定执行测试的平台。使用 MTP 运行器、TestingPlatformDotnetTestSupport=true 且最终 OutputType=Exe 的 VSTest 模式项目,仍须使用带 -- 的桥接语法。SDK 8/9 仅支持 VSTest 命令模式。
--project 仅在 SDK 10+ 的原生 MTP 命令模式下有效(由 global.json 中的 test.runner 选择)。切勿在 VSTest 模式或 SDK 8/9 的桥接模式中使用它;这些模式需要位置项目路径。相反,原生 MTP 选项是直接参数,不得放在桥接分隔符之后。
将 --framework、--configuration、--no-build 和 --verbosity 等 dotnet test/MSBuild 选项放在 -- 之前。桥接模式下,-- 之后只能放置 MTP 应用程序参数。
工作流
- 确定与仓库兼容的运行器。
对于经典项目,相关信号包括 ToolsVersion、显式的 Compile 和 Reference 项、旧式导入以及 packages.config。优先使用已检入仓库的脚本或 CI 文档中的命令。典型的备用方案是:
nuget restore MySolution.sln
MSBuild.exe MySolution.sln /t:Build /p:Configuration=Debug
vstest.console.exe path\to\MyTests.dll /TestAdapterPath:path\to\adapter\build\<tfm>
对于 packages.config,除非已导入的包文件已存在,否则应在构建前使用 NuGet 还原。如果仓库未配置适配器发现路径,请根据已还原的适配器包路径或适配器的 .props/.targets 导入项确定 /TestAdapterPath;不要猜测包根目录。
如果请求不重新构建,请省略构建步骤,并且仅当预期程序集已存在时才调用仓库的测试运行器。否则,应报告缺少构建输出,而不是悄悄重新构建或切换运行器。
如果请求运行子集,请保留仓库的运行器并使用其筛选语法:
vstest.console.exe path\to\MyTests.dll /TestCaseFilter:"TestCategory=Integration"。较旧的 MSTest.exe 仓库也可能使用 /test:<name> 或 /category:<category>。不要用后面给出的 dotnet test 筛选示例替代经典运行器。
使用已安装的、与适配器兼容的 VSTest/MSTest 工具链。如果该工具链不可用,请说明缺少的先决条件和文档中记录的命令;不要声称已运行测试。
传统 packages.config 的备用命令是 Windows 工具链命令。如果当前主机无法提供 nuget、完整的 MSBuild 和 vstest.console.exe,请明确说明这些命令需要 Windows 开发人员命令提示符(或仓库中配置的等效环境)。
对于 SDK 风格的项目,请区分:
| 信号 | 含义 |
|---|---|
SDK 10+ 的 global.json 选择 Microsoft.Testing.Platform | 原生 MTP 命令模式 |
VSTest 模式 + 已启用的 MTP 运行器 + 最终的 TestingPlatformDotnetTestSupport=true + 最终的 OutputType=Exe | 可执行的 VSTest 到 MTP 桥接 |
| VSTest 模式,但未具备完整的运行器和桥接组合 | VSTest |
有 Microsoft.NET.Test.Sdk 和适配器,但没有更强的 MTP 信号 | VSTest |
TUnit | 仅支持 MTP;使用已配置的桥接/原生模式或测试可执行文件 |
根据项目及导入的 Directory.Build.props/Directory.Packages.props 评估属性。遵从项目级覆盖和针对每个目标框架的条件。若最终输出不是可执行文件,则即使配置了运行器和桥接,也属于不完整的 MTP 配置,不能用作桥接。
- 选择命令和请求的范围。
# VSTest mode
dotnet test path/to/Tests.csproj
# VSTest mode that bridges to MTP
dotnet test path/to/Tests.csproj -- <MTP_OPTIONS>
# Native MTP mode on SDK 10+
dotnet test --project path/to/Tests.csproj <MTP_OPTIONS>
# One target framework; this stays before the bridge separator
dotnet test path/to/Tests.csproj --framework net9.0 -- <MTP_OPTIONS>
对于原生 MTP,使用 --project、--solution 或 --test-modules;位置参数路径适用于 VSTest 模式。
如果用户指定了子集,不要运行整个测试套件。只有在需要将“集成”或“冒烟”等人类可读标签转换为框架实际使用的类别/特征名称时,才检查测试特性。
当 VSTest 类筛选器必须区分名称相似的类时,应将正向选择器与明确的负向选择器组合使用,而不要依赖偶然的子字符串差异。
- 应用符合平台和框架的筛选器。
仅当请求需要筛选且框架专用语法不明确时,才读取所提供或运行时列出的 filter-syntax 文件。该文件仅供参考,不是可调用的技能;其他情况下请使用以下通用规则:
对于基于文件的筛选请求,在选择语法前,先根据项目、global.json 和导入的 props 确定框架和 SDK 命令模式。不要仅凭 Microsoft.NET.Test.Sdk 或框架名称推断 VSTest 语法。
| 平台/框架 | 筛选器 |
|---|---|
| 使用 MSTest、xUnit v2 或 NUnit 的 VSTest | --filter "<property expression>" |
| 使用 MSTest 或 NUnit 的 MTP | 相同表达式;桥接模式下放在 -- 之后,原生模式下直接使用 |
| 使用 xUnit v3 的 MTP | --filter-class、--filter-method、--filter-trait,或使用一个 --filter-query 表示组合表达式 |
| 使用 TUnit 的 MTP | --treenode-filter 路径表达式 |
示例:
# VSTest MSTest/NUnit
dotnet test --filter "FullyQualifiedName~OrderServiceTests&TestCategory=Unit"
# SDK 8/9 or SDK 10 VSTest-mode MTP bridge, xUnit v3
dotnet test -- --filter-trait "Category=Integration"
# Native MTP, xUnit v3
dotnet test --project Tests.csproj --filter-class "*ShoppingCartTests*"
# One xUnit v3 combined expression
dotnet test -- --filter-query "/*/*/*Integration*/*[Category=Smoke]"
# TUnit on SDK 8/9 with a configured VSTest-to-MTP bridge
dotnet test -- --treenode-filter "/*/*/SmsNotificationTests/*"
# TUnit executable fallback when no bridge is configured
dotnet run --project Tests.csproj -- --treenode-filter "/*/*/SmsNotificationTests/*"
在 MTP 上使用 xUnit v3 时,不要使用 VSTest 的 --filter "ClassName=..."。不要对 TUnit 使用通用的 VSTest 表达式。
当用户要求一个组合的 xUnit 查询表达式时,只返回一个 --filter-query 命令;不要将其替换为单独的筛选标志,也不要提供推测性的替代语法。
- 添加报告或诊断选项。
| 结果 | VSTest | MTP |
|---|---|---|
| TRX | SDK 风格项目:请求确切输出文件时使用 --logger "trx;LogFileName=<name>.trx",否则使用 --logger trx;独立的 vstest.console.exe:/Logger:trx;MSTest.exe:使用仓库文档记录的结果选项 | --report-trx |
| 结果目录 | --results-directory <dir> | --results-directory <dir> |
| 诊断日志 | --diag <file> | --diagnostic --diagnostic-output-directory <dir> |
| 崩溃转储 | --blame-crash | --crashdump |
| 挂起超时 | --blame-hang --blame-hang-timeout 5min | --hangdump --hangdump-timeout 5min |
| 代码覆盖率 | --collect "Code Coverage" | --coverage |
MTP 报告、转储和覆盖率标志需要对应的已注册扩展(TrxReport、CrashDump、HangDump 或 CodeCoverage)。某些框架 SDK 会捆绑常用扩展;如果某个标志无法识别,请先检查包引用,再建议更改软件包。 |
--verbosity diagnostic 会提高 dotnet/MSBuild 的输出详细程度;它不会写入 VSTest 诊断日志文件。
示例:
# VSTest TRX
dotnet test Tests.csproj --logger "trx;LogFileName=TestResults.trx"
# MTP bridge TRX
dotnet test Tests.csproj -- --report-trx
# Native MTP TRX and hang detection
dotnet test --project Tests.csproj --report-trx --hangdump --hangdump-timeout 5min
# Native MTP diagnostics
dotnet test --project Tests.csproj --diagnostic --diagnostic-output-directory artifacts/diagnostics
- 仅在收到请求时执行。
运行能够回答请求的最精简命令或命令序列。记录每条命令、退出代码和测试摘要。还原或生成失败不等于测试失败,测试失败也不等于工具失败。报告失败的阶段,并提供可操作的诊断信息。只有在整个序列成功完成且执行了预期测试后,才能声称运行成功。 对于筛选运行,仅退出成功还不够:请确认报告的测试名称或数量与请求的范围相符。如果筛选器被忽略,请修正特定平台的语法并重新运行,然后再报告成功。
输出约定
- 仅要求命令:先给出准确的命令或命令序列,然后用一句简短说明解释语法。
- 要求执行:报告准确的命令或命令序列,以及已完成运行的原样
Passed: N, Failed: N, Skipped: N摘要;同时提供首个可操作的失败信息。 - 只需检测以选择语法:简要说明所选模式/平台,不要单独提供检测报告。
- 缺少前置条件或配置不兼容:明确指出,并停止操作,不要给出看似成功的兜底结果。
验证
- 命令与 classic、VSTest、bridged MTP 或 native MTP 模式相匹配。
- 特定框架的筛选器针对请求的子集。
--framework和其他dotnet test选项位于任何桥接分隔符之前。- SDK 8/9 的桥接命令包含
--;--project仅用于 SDK 10+ 的 native MTP 模式。 - TRX、诊断、转储和覆盖率标志与平台相匹配。
- 对于仅提供建议的请求,未运行还原、生成或测试。
- 报告的结果与实际命令的执行结果相符。