platform-detection

platform-detection

热门

识别 .NET 项目的测试平台、框架、命令模式以及 SDK 风格与经典项目系统。仅用于“哪个测试平台/框架?”、“VSTest 还是 MTP?”或“此项目使用哪个运行器?”,包括桥接设置、UseVSTest 退出选项以及不兼容或冲突的 VSTest/MTP 配置。解析 global.json、项目、packages.config、Directory.Build.props 和 Directory.Packages.props 对 MSTest/xUnit/NUnit/TUnit 的优先级。对于运行/筛选测试、确切命令或标志、TRX/转储以及测试命令/筛选错误,请使用 run-tests。不要用于热重载或迁移。

5293Star
402Fork
更新于 2026/8/29
SKILL.md
只读
名称
platform-detection
描述

识别 .NET 项目的测试平台、框架、命令模式以及 SDK 风格与经典项目系统。仅用于“哪个测试平台/框架?”、“VSTest 还是 MTP?”或“此项目使用哪个运行器?”,包括桥接设置、UseVSTest 退出选项以及不兼容或冲突的 VSTest/MTP 配置。解析 global.json、项目、packages.config、Directory.Build.props 和 Directory.Packages.props 对 MSTest/xUnit/NUnit/TUnit 的优先级。对于运行/筛选测试、确切命令或标志、TRX/转储以及测试命令/筛选错误,请使用 run-tests。不要用于热重载或迁移。

测试平台和框架检测

确定项目使用哪个测试平台(VSTest 或 Microsoft.Testing.Platform)以及哪个测试框架(MSTest、xUnit、NUnit、TUnit)。

响应契约

尊重用户请求的标签和顺序,用实际分类替换每个占位符。以结论开头:绝不要在结论之前放置标题、草稿分析、工具语法或回显的模板。随后用一句简洁的证据句,说明证明每个请求分类所需的仓库事实。当请求 Framework 时,指明标识它的包或项目 SDK。仅在存在冲突、配置不完整或目标框架特定差异时使用第二句。

Platform 指实际执行测试的平台:VSTestMTP。如果冲突或不完整的配置阻止执行,则报告为不可用,而不是虚构一个成功的平台。

在起草证据之前应用此范围门:

用户请求 包含的证据 省略
平台和框架 最终运行器选择器及其获胜来源;标识框架的包或项目 SDK;必要时,使其可执行的属性 命令模式;常见 SDK 事实;OutputType 除非缺失或冲突
单个决定性信号 该运行器选择属性、其来源为何获胜,以及竞争包为何不选择或暗示 VSTest;仍指明标识请求框架的包或项目 SDK 桥接、OutputType、SDK 模式以及配置完整时无关的先决条件
每个目标框架的平台 仅按目标不同的条件最终值 常见属性和项目级 SDK 评论
显式退出 最终 UseVSTest 值及其获胜来源 被取代的默认值,除非它们造成冲突
dotnet test 模式 单独的命令模式和已执行平台分类 请求的轴之外的内容

如果请求的标签省略了 dotnet test mode,则不要在响应中的任何地方说明或解释命令模式。确切的桥接属性可能仍然是决定性的平台证据,但不要将其变成 SDK 或 CLI 模式评论。

当导入优先级决定属性时,说明获胜来源为何获胜(例如,它被稍后导入或其条件适用),而不仅仅是它包含最终值或覆盖另一个赋值。

将解释保持在请求的轴上:

  • global.json 中的 SDK 版本固定是上下文,不是平台选择器。仅当 global.jsontest.runner 设置实际选择 VSTest 或原生 MTP 时,才声称 global.json 选择 VSTest 或原生 MTP。
  • 如果 UseVSTest=true 是决定性的,直接说明。不要推测缺失的 test.runner 或将 SDK 固定描述为额外的平台选择。
  • 如果未请求命令模式,不要添加它,即使内部需要它来确定已执行平台。

当经典项目请求还要求命令系列时,添加一行直接说明,如 Command family: MSBuild + vstest.console.exe;不要将其变成可选替代方案或添加不必要的构建限定符。

对于文件支持的请求,枚举以下配置名称一次,然后批量读取存在的每个相关文件:global.json.csprojpackages.configDirectory.Build.propsDirectory.Build.targetsDirectory.Packages.props 以及显式导入的 .props / .targets。项目文件中缺失的设置可能由导入定义,因此绝不要仅从 .csproj 推断其最终值。当仓库配置足够时,不要搜索网络或检查无关文件。

按实际的 MSBuild 导入顺序解析属性,而不是使用固定的“项目胜过 props”规则。对于每个适用的目标框架:

  1. 遵循导入图和条件。稍后的适用赋值获胜。Directory.Build.props 通常在项目主体之前导入,因此无条件的项目赋值通常覆盖它;稍后的 .targets 可以再次覆盖项目。
  2. 记录 UseVSTest、框架运行器选择器、TestingPlatformDotnetTestSupportOutputType 的最终值及其获胜来源。
  3. Directory.Packages.props 视为版本证据,除非它还包含相关属性。在应用版本相关默认值之前解析包/SDK 版本。
  4. 绝不要从包存在推断属性。仅当解析的版本实际提供该默认值且没有后续赋值覆盖它时,包或 SDK 默认值才有效。

检测项目系统

在选择 CLI 之前对项目进行分类:

  • Sdk 属性或 <Sdk> 声明:SDK 风格。
  • ToolsVersionMicrosoft.Common.props / Microsoft.CSharp.targets 导入、显式 <Reference><Compile Include> 项:经典非 SDK。
  • packages.config:经典 NuGet 依赖管理。

经典项目仍可使用 VSTest 兼容适配器,但 dotnet test 不自动是有效的调用。保留仓库脚本/CI 命令,通常是 MSBuild 后跟 vstest.console.exe。仅当仓库配置或文档确定该旧运行器时,才提及 MSTest.exe

检测测试框架

读取 .csproj、相邻的 packages.configDirectory.Build.props / Directory.Packages.props,查找:

包或 SDK 引用 框架
MSTest 元包、<Project Sdk="MSTest.Sdk[/version]"><Sdk Name="MSTest.Sdk"> MSTest
MSTest.TestFramework + MSTest.TestAdapter MSTest(也适用于 v3/v4)
xunitxunit.v3xunit.v3.mtp-v1xunit.v3.mtp-v2xunit.v3.core.mtp-v1xunit.v3.core.mtp-v2 xUnit
NUnit + NUnit3TestAdapter NUnit
TUnit TUnit(仅 MTP)

在经典项目中,包 ID 和版本可能仅出现在 packages.config 中,而项目包含带有 HintPath 值的程序集 <Reference> 元素。使用这两个来源。

检测已执行的测试平台

如果用户明确请求 dotnet test 模式,在回答之前阅读 references/command-mode.md。不要为仅平台/框架的请求加载该参考或提及命令模式。

对于明确询问命令模式且没有有效桥接的 SDK 8/9 请求,在一个因果句中说明所有三个事实:运行器使项目具备 MTP 能力,dotnet test 仍处于 VSTest 模式,缺失的桥接意味着 VSTest 实际执行测试。仅当有助于解释该结果时,才提及原生 MTP 命令模式从 SDK 10 开始。

当允许执行且提示或 global.json 未标识 SDK 时,运行一次 dotnet --version。对于禁止执行的只读识别请求,不要探测已安装的 SDK;使用仓库事实并说明任何必要的 SDK 假设。

解析最终属性值后,按此顺序分类:

  1. 最终 UseVSTest=true 选择 VSTest。如果 global.json 同时选择原生 MTP 命令模式,报告 Platform: unavailable,因为命令模式和项目退出冲突。
  2. global.json 中的原生 MTP 选择在 MTP 上执行兼容的 MTP 应用程序,最终 OutputType=Exe。仅 VSTest、库输出或退出的项目不可用。
  3. 在 SDK 8/9 上,启用的 MTP 运行器加上最终 TestingPlatformDotnetTestSupport=true 加上最终 OutputType=Exe 在 MTP 上执行。
  4. 如果运行器已启用但桥接缺失或为 false,则双能力的 MSTest、NUnit 或 xUnit 项目仍停留在 VSTest:运行器建立 MTP 能力,但 SDK 8/9 dotnet test 无法到达它,VSTest 适配器反而执行测试。如果桥接为 true 但未启用运行器,项目也停留在 VSTest。
  5. 运行器和桥接但输出不可执行是不完整的且不可用。仅 MTP 的框架无法被所选 SDK 路径到达也是不可用,而不是 VSTest。

保持每个信号的角色精确:

  • 运行器属性选择测试应用程序。
  • TestingPlatformDotnetTestSupport=true 允许 SDK 8/9 dotnet test 到达该应用程序。
  • OutputType=Exe 提供可执行主机形状。它选择或启用 MTP。

不要混淆 MSTest 元包与 MSTest.Sdk 项目 SDK。PackageReference Include="MSTest" 加上 EnableMSTestRunner=true 启用 MSTest MTP 运行器,但隐式设置 TestingPlatformDotnetTestSupport

MSTest.Sdk 默认启用 MTP 运行器。检查其解析版本和评估属性以了解桥接行为:版本 3.8 提供 TestingPlatformDotnetTestSupport,除非后续赋值覆盖它,而 .NET 10 上的较新 SDK 可能期望原生 MTP 模式。<UseVSTest>true</UseVSTest> 选择回到 VSTest。

信号 含义
<Project Sdk="MSTest.Sdk..."> 且无 UseVSTest MTP 应用程序;检查解析的 SDK 版本和评估的桥接属性
MSTest 元包 + <EnableMSTestRunner>true> MTP 运行器已启用;不暗示 VSTest 到 MTP 的桥接
<UseMicrosoftTestingPlatformRunner>true 决定 xUnit 运行器选择的信号
<EnableMSTestRunner>true> / <EnableNUnitRunner>true> 决定 MSTest/NUnit 运行器选择的信号
TestingPlatformDotnetTestSupport=true VSTest 到 MTP 桥接的执行先决条件,不是运行器选择信号
Microsoft.Testing.Platform 具备 MTP 能力的应用程序;本身不具决定性
TUnit 仅 MTP 框架
最终评估的 <OutputType>Exe</OutputType> 基于包的 MTP 应用程序所需的可执行主机形状

Microsoft.NET.Test.Sdk 本身不具决定性;它可以在启用 MTP 的项目中保留以兼容。当显式覆盖决定结果时,指明最终覆盖及其来源,而不是被取代的默认值。当运行器选择属性与 Microsoft.NET.Test.Sdk 竞争时,说明运行器属性选择 MTP,而 Microsoft.NET.Test.Sdk 选择或暗示 VSTest。它可能保留为兼容支持,但这是次要的。TestingPlatformDotnetTestSupport=true 是桥接先决条件,不是运行器选择信号;绝不要说此属性单独启用桥接。对于询问哪个单一信号决定的请求,到此为止。当配置完整时省略桥接或主机形状先决条件,仅在需要解释所选运行器为何无法执行时添加它们。

使用因果证据,而不是信号包。例如:

Platform: MTP
Framework: NUnit

Directory.Build.props 提供最终 EnableNUnitRunner=true 和
TestingPlatformDotnetTestSupport=true,因此 NUnit 在 MTP 上执行。

对于不兼容的配置,在结论后给出一个最小的对齐选择,而不修改文件:要么全局选择项目配置的平台,要么移除项目退出以使用全局选择的平台。

条件和每目标框架属性

为每个目标框架评估运行器和桥接属性。如果条件产生不同的已执行平台,显式报告每个目标(例如,net8.0: VSTestnet9.0: MTP),而不是将项目折叠为一个全局平台。