mcpField
P
platform-detection

platform-detection

github.com/dotnet测试与质量5.8k3.6k 次安装1 天前更新
代码仓库

关于 platform-detection

platform-detection 是面向 .NET 测试项目的技能,用于识别实际执行测试的平台及测试框架。它根据项目配置和属性的求值结果判断,避免仅凭单一包或配置文件推断。

主要功能

  1. 01识别 VSTest 与 MTP 执行平台
  2. 02识别 MSTest、xUnit、NUnit 和 TUnit
  3. 03解析 MSBuild 属性及导入顺序
  4. 04区分测试执行平台与命令模式
  5. 05检查多目标框架的条件配置

适用场景

  1. 01排查测试运行平台的判定
  2. 02确认项目使用的测试框架
  3. 03诊断测试配置冲突或缺失
  4. 04比较不同目标框架的测试平台

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill platform-detection

安装后在 Claude Code 中输入/platform-detection确认已加载。

附带文件references/command-mode.md

详细介绍

测试平台和框架检测

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

回复规范

严格遵循用户要求的标签和顺序,并将每个占位符替换为实际分类结果。先给出结论:前面不得添加标题、分析草稿、工具语法或复述模板。接着用一句简洁的证据说明,指出足以证明每项所请求分类的仓库事实。如果请求了 Framework,请写明能识别该框架的包或项目 SDK。仅在存在冲突、配置不完整或不同目标框架配置不同时,才使用第二句话。

Platform 指实际执行测试的平台:VSTest 或 MTP。如果配置冲突或不完整导致无法执行,请报告平台不可用,不要凭空推断平台可成功执行。

绝不能仅根据 global.json 中的 test.runner 对已执行的平台进行分类。 该设置用于选择 dotnet test 命令模式;即使显式设置为 VSTest,也可能桥接到可执行的 MTP 应用。撰写 Platform: 前,还要检查项目运行器、桥接设置和输出形态等信号。

撰写证据前,先应用以下范围规则:

用户要求应包含的证据应省略
平台和框架最终运行器选择器及其生效来源;用于识别框架的包或项目 SDK;必要时,说明使其可执行的属性命令模式;常见 SDK 事实;除非缺失或存在冲突,否则不提 OutputType
唯一决定性信号该运行器选择属性、其来源为何生效,以及竞争包为何不会选择或暗示 VSTest;如用户还要求框架,则仍须写明用于识别框架的包或项目 SDK配置完整时,省略桥接、OutputType、SDK 模式及无关前提
各目标框架对应的平台仅列出存在差异的条件最终值共同属性和项目级 SDK 说明
显式选择退出最终的 UseVSTest 值及其生效来源已被取代的默认值,除非它们造成冲突
dotnet test 模式分别说明命令模式和实际执行平台不省略任何所请求的类别

如果用户要求的标签中不包含 dotnet test mode,则回复中不得提及或解释命令模式。精确的桥接属性仍可作为决定性平台证据,但不要将其延伸为 SDK 或 CLI 模式说明。 如果用户询问在显式运行器属性和 Microsoft.NET.Test.Sdk 之间,哪个单一信号起决定作用,证据句必须同时说明:运行器属性选择了 MTP,且 Microsoft.NET.Test.Sdk 不会选择或暗示 VSTest。

如果某项属性由导入优先级决定,请说明生效来源为何优先(例如,它导入得更晚,或其条件适用),而不只是说它包含最终值或覆盖了其他赋值。

说明应围绕用户要求的类别展开:

  • global.json 中的 SDK 版本固定值属于背景信息,不是平台选择器。只有当 global.json 的 test.runner 设置确实作出选择时,才能说它选择了 VSTest 或原生 MTP。
  • 如果决定性设置为 UseVSTest=true,请直接说明。不要臆测未出现的 test.runner,也不要把 SDK 版本固定描述为另一项平台选择。
  • 如果用户未询问命令模式,即使内部判断已执行平台时用到了它,也不要在回复中添加命令模式。
  • 如果有关传统项目的请求还询问命令系列,请直接写一行,例如 Command family: MSBuild + vstest.console.exe;不要将其说成可选方案,也不要添加不必要的构建限定说明。 对于基于文件的请求,请先列出以下配置名称,然后通过一次批量操作读取所有相关且存在的文件: global.json、.csproj、packages.config、Directory.Build.props、 Directory.Build.targets、Directory.Packages.props,以及显式导入的 .props / .targets。项目文件中缺少的设置可能由导入文件定义,因此切勿仅凭 .csproj 推断其最终值。如果仓库配置已足够,请勿搜索网络或检查无关文件。

应按照实际的 MSBuild 导入顺序解析属性,而不是采用固定的“项目文件优先于 props”规则。对于每个适用的目标框架:

  1. 遵循导入关系图和条件。最后一个适用的赋值生效。 Directory.Build.props 通常在项目主体之前导入,因此,无条件的项目赋值通常会覆盖它;后续的 .targets 则可能再次覆盖项目中的赋值。
  2. 记录 UseVSTest、框架运行器选择器、TestingPlatformDotnetTestSupport 和 OutputType 的最终值及其生效来源。
  3. 将 Directory.Packages.props 视为版本依据,除非其中也包含相关属性。应用依赖版本的默认值之前,先解析程序包/SDK 版本。
  4. 切勿根据程序包是否存在来推断属性。只有当已解析的版本确实提供该属性,且后续没有赋值覆盖时,程序包或 SDK 默认值才有效。

检测项目系统

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

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

经典项目仍可使用与 VSTest 兼容的适配器,但 dotnet test 并非自动适用的调用方式。保留仓库中的脚本/CI 命令,通常是先运行 MSBuild,再运行 vstest.console.exe。只有在仓库配置或文档明确说明使用旧版运行器时,才提及 MSTest.exe。

检测测试框架

读取 .csproj、相邻的 packages.config 和 Directory.Build.props / Directory.Packages.props,并查找以下内容:

程序包或 SDK 引用框架
MSTest 元程序包、<Project Sdk="MSTest.Sdk[/version]"> 或 <Sdk Name="MSTest.Sdk">MSTest
MSTest.TestFramework + MSTest.TestAdapterMSTest(v3/v4 也适用)
xunit、xunit.v3、xunit.v3.mtp-v1、xunit.v3.mtp-v2、xunit.v3.core.mtp-v1、xunit.v3.core.mtp-v2xUnit
NUnit + NUnit3TestAdapterNUnit
TUnitTUnit(仅限 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 后,最终 OutputType=Exe 的兼容 MTP 应用会在 MTP 上执行。仅支持 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. 运行器和桥接均已启用,但输出类型不可执行,说明配置不完整,项目不可用。如果选定的 SDK 路径无法访问仅支持 MTP 的框架,该项目同样不可用,而不是使用 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..."> 且没有 UseVSTestMTP 应用;检查解析后的 SDK 版本和求值后的桥接属性
MSTest 元包 + <EnableMSTestRunner>true>已启用 MTP 运行器;不代表存在 VSTest 到 MTP 的桥接
<UseMicrosoftTestingPlatformRunner>true用于选择 xUnit 运行器的决定性信号
<EnableMSTestRunner>true> / <EnableNUnitRunner>true>用于选择 MSTest/NUnit 运行器的决定性信号
TestingPlatformDotnetTestSupport=trueVSTest 到 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 是桥接的前提条件,而不是运行器选择信号;切勿说仅靠此属性就能启用桥接。如果用户询问哪个单一信号起决定作用,请到此为止。配置完整时,省略桥接或宿主形式的前提条件;仅在需要解释所选运行器为何无法执行时,才补充这些条件。 同样,如果启用的运行器被覆盖或无法访问,应从因果关系上说明这两个方面:运行器属性使项目具备 MTP 能力,但最终的 UseVSTest/桥接/输出设置决定实际执行的平台。先指出运行器选择器,再使用包引用仅用于识别框架。 使用因果证据,而不是堆砌信号。例如:

Platform: MTP
Framework: NUnit

Directory.Build.props supplies final EnableNUnitRunner=true and
TestingPlatformDotnetTestSupport=true, so NUnit executes on MTP.

如果配置不兼容,请在给出判定后提供一种最简对齐方案,不修改文件:要么全局选择项目已配置的平台,要么移除项目级退出设置,以使用全局选定的平台。

条件属性和按目标框架设置的属性

针对每个目标框架评估运行器和桥接属性。如果条件导致实际执行的平台不同,请明确报告每个目标(例如,net8.0: VSTest、net9.0: MTP),不要将整个项目归为同一个全局平台。

评论

支持 Markdown