mcpField
M
migrate-mstest-v1v2-to-v3

migrate-mstest-v1v2-to-v3

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

关于 migrate-mstest-v1v2-to-v3

用于将 MSTest v1 或 v2 测试项目迁移到 v3 的技能,涵盖项目检查、针对性修复及验证,并保留现有测试平台。

主要功能

  1. 01识别 MSTest v1、v2 和 v3 状态
  2. 02指导包与设置迁移
  3. 03将破坏性变更对应到修复方案
  4. 04提供构建与测试验证指导

适用场景

  1. 01将 v1 或 v2 测试项目升级到 v3
  2. 02解决升级包后的源码错误
  3. 03替换旧版测试设置
  4. 04检查 DataRow 与断言兼容性

安装

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

$npx skills add https://github.com/dotnet/skills --skill migrate-mstest-v1v2-to-v3

安装后在 Claude Code 中输入/migrate-mstest-v1v2-to-v3确认已加载。

详细介绍

MSTest v1/v2 -> v3 迁移

将测试项目从 MSTest v1(程序集引用)或 MSTest v2(NuGet 1.x-2.x)迁移到 MSTest v3。MSTest v3 与 v1/v2 不具备二进制兼容性——使用 v1/v2 编译的库必须重新编译。

首要操作

在作答前,检查所提供的工作区,并判断项目属于 v1、v2、部分迁移到 v3,还是已完成 v3 迁移。不要先搜索网页或凭记忆作答。对于编辑请求,继续完成所请求的源代码更改和验证;对于建议请求,分类后直接回答。

适用情况

  • 项目引用了 Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll(MSTest v1)
  • 项目使用 MSTest.TestFramework / MSTest.TestAdapter NuGet 1.x 或 2.x
  • 将 MSTest 包从 v1/v2 更新到 v3 后解决生成错误——包括包已显示为 3.x,但仍需修复源代码或设置的情况
  • 将 .testsettings 替换为 .runsettings
  • 采用 MSTest.Sdk 或程序集内并行执行

不适用情况

  • 项目已使用 MSTest v3,没有与迁移相关的生成错误,也没有遗留的 .testsettings / <LegacySettings>(迁移已完全完成)
  • 将 v3 升级到 v4——请使用 migrate-mstest-v3-to-v4
  • 在框架之间迁移(从 MSTest 迁移到 xUnit/NUnit)

边界检查

任何编辑之前先检查包版本。如果所有 MSTest 引用都已是 3.x,没有报告 v1/v2 到 v3 的错误,并且没有遗留 .testsettings 或 <LegacySettings>,则说明迁移已完成,不做任何更改。仅包版本为 3.x 并不代表迁移已完成——遗留的 v1/v2 时代设置文件或重大更改错误仍属于处理范围。不要将正常工作的 v3 包合并到元包中。只有在用户要求验证时才运行现有测试。此规则优先于以下所有步骤。

输入

输入必需说明
项目或解决方案路径否.csproj、.sln 或 .slnx 入口点。搜索工作目录以查找;仅在未找到或多个测试项目导致目标不明确时询问
生成命令否生成方式(例如 dotnet build、仓库生成脚本)。如未提供,则自动检测
测试命令否运行测试的方式(例如 dotnet test)。如未提供,则自动检测

切勿一开始就询问项目路径。 用户用文字描述其项目是在提问,并非隐瞒文件——请先检查磁盘。如果确实没有项目文件,则根据用户描述的配置作答,不要只回复一个问题。

严格按搜索结果中的路径打开文件。 如果 glob 返回 ./TestProject.csproj,说明文件相对于工作目录就在该路径下;请按该路径读取。不要将其拼成相对于此技能自身基础目录的绝对路径:该目录存放的是 SKILL.md,而非用户项目,因此会导致读取失败,并误以为项目不存在。如果刚找到的文件无法打开,说明你构造的路径有误——请使用搜索结果中的原始路径重试。只要搜索仍报告项目文件,就绝不能断定“磁盘上没有项目”;也绝不能为了应付文字描述而创建替代项目。

执行约定

  • 技能激活并不意味着任务结束。请在同一任务中继续探索工作区并完成请求的工作。
  • 技能目录包含指导信息,而不是已暂存的项目。请搜索当前工作目录,打开搜索返回的实际路径;如果某个工具拒绝有效路径,请改用其他可用的读取器或编辑器重试。
  • 只要可以通过 glob 或目录搜索找到路径,就不要询问路径。只有在穷尽当前工作区搜索后仍找不到项目,或存在多个项目导致目标确实不明确时,才询问。
  • 根据请求的交付内容分类,而非孤立的动词:“修改这些内容”“更新此项目”或“然后构建并运行”意味着执行;“我需要更改什么?”“我应该预期什么?”“步骤相同吗?”或“给我看看”意味着回答,即使提示中也提到升级或迁移。
  • 更改文件后,请说明检测到的 MSTest 版本和运行程序、所有已更改的文件,以及确切修复的调用/设置(例如,逐一列出更改为 AreEqual<object>、AreNotEqual<object> 或 AreSame<object> 的断言)。报告干净的测试计数。没有项目证据时,不要声称保留了 VSTest、执行了构建或测试通过。

重大变更摘要

MSTest v3 相较于 v1/v2 引入了以下重大变更。仅处理与项目相关的变更:

重大变更影响修复方法
已移除 Assert.AreEqual(object, object) 重载;仅保留 AreEqual<T>(T?, T?)CS0411(无法推断类型参数)或 CS1503——但仅当两个参数没有共同的推断类型时才会出现。两个 object 类型的参数仍会推断出 T = object,并且无需修改即可编译在编译失败的调用中添加显式类型参数:Assert.AreEqual<object>(expected, actual)。AreNotEqual、AreSame、AreNotSame 同理。已能编译的断言无需修改
DataRow 严格类型匹配不会导致编译错误。 构建时会出现分析器警告 MSTEST0014,并在运行时因“Test data doesn't match method parameters”而失败。扩大转换(int -> long)仍然适用;缩小转换或无关类型(1L -> int、1.0 -> float)则不适用将字面量改为与参数类型完全一致:int 使用 1,long 使用 1L,float 使用 1.0f。运行测试——构建成功并不能证明这里没有问题
DataRow 最多支持 16 个参数——仅限 3.0.1 和 3.0.2在这两个版本中会出现 CS1729;3.0.3 起已再次移除该限制在 3.0.3 及更高版本(所有当前 3.x 版本)中,较长的行有效——保持原样即可。不要将多余参数包装进数组、转换为 object 或拆分测试。只有固定使用 3.0.1/3.0.2 的项目需要采取措施:升级到 3.0.3 或更高版本
不再支持 .testsettings / <LegacySettings>设置会被静默忽略删除 .testsettings,并创建包含等效配置的 .runsettings
.NET Core / Framework 的超时行为已统一带有 [Timeout] 的测试可能会出现不同的行为验证超时值;必要时进行调整
已弃用的目标框架:.NET 5、.NET Fx < 4.6.2、netstandard1.0、UWP < 16299、WinUI < 18362构建错误更新 TFM:将 .NET 5 改为 net8.0(LTS)或 net6.0 及更高版本,将 netfx 改为 net462 及更高版本,将 netstandard1.0 改为 netstandard2.0。注意:net6.0、net8.0、net9.0 均受支持
与 v1/v2 不兼容二进制兼容针对 v1/v2 编译的库必须重新编译针对 v3 重新编译所有依赖项
测试 ID 生成方式已变更以测试 ID 为键的播放列表、筛选器或 CI 历史记录可能会重置重新建立 ID 基准,并验证受影响的筛选器
TargetInvocationException 不再包装内部异常依赖该包装异常的测试或基础设施会观察到内部异常更新异常处理逻辑,使其预期底层异常
初始化/清理消息现在会附加到测试结果第一个/最后一个测试的输出可能会新增此前不存在的生命周期消息更新日志处理逻辑,并检查第一个/最后一个测试结果
所有 TFM 的部署目录行为已统一使用硬编码部署路径的测试可能会失败使用 TestContext.DeploymentDirectory 或已部署项路径,不要依赖假设
已添加可空注释启用了可空性的项目可能会出现警告修复这些警告,不要抑制无关诊断

响应指南

  • 始终先确认当前版本:在推荐任何迁移步骤之前,明确说明在项目中检测到的当前 MSTest 版本(例如:“您的项目使用 MSTest v2(2.2.10)”或“这是一个使用 QualityTools 程序集引用的 MSTest v1 项目”)。这样可以让迁移建议有据可依,并确认你已读取项目文件。
  • 要求项目证据,但由你自行收集:不要仅凭措辞猜测项目使用 v1 还是 v2——读取项目文件或中央包文件,并将源版本归类为 QualityTools/v1、NuGet 1.x 或 NuGet 2.x。从工作目录中收集这些证据,而不是向用户索取。如果项目已经使用 v3+,且没有遗留的 v1/v2 内容,则停止操作并转到相应技能。
  • 保留测试平台:框架升级期间保持 VSTest 或 MTP 不变,除非用户另外要求迁移运行器。
  • 执行完整迁移:用户要求迁移或升级项目时,编辑文件、构建项目并运行测试。不要只列出重大变更就停止。只有用户询问预期变化时,才适合仅提供建议。
  • 针对性修复请求(用户升级后遇到特定编译错误):仅处理上表中相关的重大变更。简洁展示修复前后的代码。不要完整介绍迁移工作流。
  • DataRow 修复请求:将提供的每个 DataRow 与其方法签名进行比较。不匹配的内容可能只触发 MSTEST0014,但在测试执行期间失败。保留方法契约,并通常修正字面量(1L -> 1,用于 int),然后运行受影响的测试。仅修改确实有误的行。 在 3.0.3+ 中,参数数量本身不构成问题,因此除非编译器报错,否则不要改动长行。
  • 不要因猜测而修改——先确认错误:如果你认为某种结构不受支持,应先构建项目并查看实际诊断,再进行修改。如果能够编译,说明此版本支持该结构,无需修改。为了规避项目并未受到的限制而重写有效代码,是缺陷,不是谨慎。
  • 特定功能迁移(用户询问 .testsettings、DataRow 或断言等某个方面):仅处理该功能,但要覆盖所提供文件中的每个有效设置或受影响用法。对于 .testsettings,将所有 MSTest 设置放在同一个 <MSTest> 元素下,映射用户要求的部署、每个测试的超时、数据收集器及其他有效配置,不要添加整个会话的超时。不要介绍无关的重大变更。
  • “预期变化”问题(用户在升级前询问重大变更):先说明升级到 v3 所需的具体包更新,然后概述《重大变更摘要》中的每个类别,并标明哪些类别直接适用于当前可见项目。每项保持一行,不要展开介绍发行说明历史。
  • “预期变化”问题的必需格式:使用基于可见项目的 Applies / Watch / No change 表格,并涵盖《重大变更摘要》中的每一行。完整性正是此技能的价值;不要仅为了简洁而省略仅在运行时出现的问题类别。
  • 完整迁移请求(用户要求完整迁移):遵循下方的完整工作流。
  • 对比问题(用户询问 v1 与 v2 的区别):简洁说明——v1 使用程序集引用,必须先移除这些引用;v2 使用 NuGet,只需更新版本。二者最终都需要使用相同的 v3 包,并面临相同的重大变更。
  • 确保执行针对具体项目:修复和完整迁移只修改可见代码或配置中存在的模式。只有用户明确询问“我应该预期哪些变化?”时,才介绍更广泛的内容。

迁移路径

  • MSTest v1(程序集引用 QualityTools):移除程序集引用(步骤 2),添加 v3 NuGet 包(步骤 3),修复破坏性变更(步骤 5)。
  • MSTest v2(NuGet 包 1.x-2.x):将包版本更新到 3.x(步骤 3),修复破坏性变更(步骤 5)。无需移除程序集引用。

两条路径都在步骤 3 汇合——无论起始版本是什么,均适用相同的 v3 包和破坏性变更。

工作流

步骤 1:评估项目
  1. 先定位项目:在工作目录中对 *.csproj、*.sln、 *.slnx、Directory.Build.props、Directory.Packages.props 和 *.testsettings 执行 glob 搜索。先完成这一步,再询问用户任何问题,并严格按照返回的路径打开对应文件(参见 Inputs 下方的说明)。
  2. 在一次发现过程中,批量读取项目文件和中央配置文件,搜索受影响的 API/设置,并确定当前使用的 MSTest 版本:
    • 程序集引用:在项目引用中查找 Microsoft.VisualStudio.QualityTools.UnitTestFramework -> MSTest v1
    • NuGet 包:检查 MSTest.TestFramework 和 MSTest.TestAdapter 包版本 -> 1.x 为 v1,2.x 为 v2
  3. 检查目标框架是否在 v3 中停止支持(参见步骤 4)。
  4. 运行现有测试命令。记录发现、通过、失败和跳过的数量,作为一致性基线。
步骤 2:移除 v1 程序集引用(如适用)

如果项目通过程序集引用使用 MSTest v1:

  1. 移除对 Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll 的引用
    • 对于 SDK 样式项目,从 .csproj 中移除 <Reference> 元素
    • 对于非 SDK 样式项目,在 Visual Studio 的解决方案资源管理器中依次选择 References -> 右键单击 -> Remove
  2. 保存项目文件
步骤 3:将包更新到 MSTest v3

使用一种包模型;不要保留重复的框架/适配器引用。

默认方案——安装 MSTest 元包:

移除单独的 MSTest.TestFramework 和 MSTest.TestAdapter 包引用,并替换为统一的 MSTest 元包:

<PackageReference Include="MSTest" Version="3.8.0" />

如果项目仍使用 VSTest,请保留 Microsoft.NET.Test.Sdk,但将其更新到与所选 MSTest 版本兼容的版本。例如,MSTest 3.8.0 要求 Microsoft.NET.Test.Sdk 版本为 17.13.0 或更高;保留较旧的显式版本会导致 NU1605。如果由中央配置管理包版本,请更新 Directory.Packages.props,而不是添加内联版本。

仅在用户要求或存储库已统一使用 MSTest.Sdk 时使用(仅适用于 SDK 样式项目):

将 <Project Sdk="Microsoft.NET.Sdk"> 更改为 <Project Sdk="MSTest.Sdk/3.8.0">。MSTest.Sdk 会自动提供 MSTest 框架、适配器和分析器。

重要:MSTest.Sdk 默认使用 Microsoft.Testing.Platform(MTP)。如果项目本身必须继续使用 VSTest,请设置 <UseVSTest>true</UseVSTest>。MSTest.Sdk v3 在 MTP 模式下也会提供 Microsoft.NET.Test.Sdk,因此,仅仅存在独立的 vstest.console 调用并不意味着必须更改主要测试运行程序。 不要仅仅因为升级框架而切换测试运行程序。

切换到 MSTest.Sdk 时,移除以下内容(SDK 会自动提供):

  • 包:MSTest、MSTest.TestFramework、MSTest.TestAdapter、MSTest.Analyzers、Microsoft.NET.Test.Sdk
  • 属性:<EnableMSTestRunner>、<OutputType>Exe</OutputType>、<IsPackable>false</IsPackable>、<IsTestProject>true</IsTestProject>
第 4 步:按需更新目标框架

MSTest v3 支持 .NET 6+、.NET Core 3.1、.NET Framework 4.6.2+、.NET Standard 2.0、UWP 16299+ 和 WinUI 18362+。.NET Core 3.1 已结束生命周期,但 MSTest v3 仍支持它;在这次仅涉及框架的迁移中请保留它,并建议另行升级运行时。如果项目的目标框架版本已不受 MSTest v3 支持,请更新为受支持的版本:

不再支持建议替代版本
.NET 5.NET 8.0(当前 LTS)或 .NET 6+
.NET Framework < 4.6.2.NET Framework 4.6.2
.NET Standard 1.0.NET Standard 2.0
UWP < 16299UWP 16299
WinUI < 18362WinUI 18362

注意:MSTest v3 支持 .NET 6、.NET 8 和 .NET 9。不要更改已受支持的 TFM。

第 5 步:解决构建错误和破坏性变更

先搜索提供的文件,只修复其中实际存在的破坏性变更。 构建成功并不能证明兼容性;有些问题只会以分析器警告的形式出现,或在测试执行期间暴露。

断言重载 -- MSTest v3 将 Assert.AreEqual(object, object) 和 AreNotEqual(object, object) 替换为泛型 AreEqual<T>(T?, T?)。这仅在无法再推断 T 时会导致问题,编译器会报告 CS0411(或在参数类型不相关时报告 CS1503):

// Breaks -- string and int have no common inferred type:
Assert.AreEqual(referenceCode, numericId);   // CS0411
// Fix -- name the type argument explicitly:
Assert.AreEqual<object>(referenceCode, numericId);

两个类型为 object 的参数仍会推断出 T = object 并正常编译,无需改动;普通的类型化断言(如 Assert.AreEqual("A-3", order.Reference))也一样。只修复编译器拒绝的调用点。 将文件中的所有断言都扩大为 <object> 也能编译,因此不会触发任何提示,但这会丢弃 v3 新增的类型检查,而这正是此项变更的全部目的。

DataRow 严格类型匹配 -- 参数类型必须与形参类型完全一致。这不是编译错误:该行可以构建(并出现 MSTEST0014),但会在运行时因 "Test data doesn't match method parameters" 而失败。

// Fails at run time: 1L (long) does not bind to an int parameter -> use 1
// Fails at run time: 1.0 (double) does not bind to a float parameter -> use 1.0f
// Still binds: 1 (int) to a long parameter -- widening conversions are accepted

除非形参类型本身有误,否则请保留不变。dotnet build 可能会在出现 MSTEST0014 的情况下成功;请运行测试,确认每一行都能绑定并执行。

参数超过 16 个的行 -- 除非编译器确实发出 CS1729,否则不要修改。这项上限只存在于 3.0.1/3.0.2 中(已在 3.0.3 中移除),因此将额外参数包装在 object[] 中、强制转换为 object 或拆分方法,只会改写原本正确的测试。

超时行为 -- .NET Core 和 .NET Framework 已统一超时行为。请确认 [Timeout] 值仍然有效。

第 6 步:将 .testsettings 替换为 .runsettings

MSTest v3 不再支持 .testsettings 文件和 <LegacySettings>。删除 .testsettings 文件并创建 .runsettings 文件——不要同时保留两者。将所有 MSTest 配置合并到一个 <MSTest> 元素下;不要创建 <MSTestV2> 节。

关键映射:

.testsettings对应的 .runsettings 配置
TestTimeout 属性<MSTest><TestTimeout>30000</TestTimeout></MSTest>
部署配置<MSTest><DeploymentEnabled>true</DeploymentEnabled></MSTest> 或移除
程序集解析设置移除——现代 .NET 不需要
数据收集器<DataCollectionRunSettings><DataCollectors> 节

重要:请将超时映射到 <MSTest><TestTimeout>(针对每个测试),而不是 <TestSessionTimeout>(针对整个会话)。请彻底移除 <LegacySettings>。

更新所有明确指定旧 .testsettings 路径的项目、CI 命令或 IDE 设置,使其改为指定新的 .runsettings 路径。如果 VSTest 项目必须保留原有行为,但此前从未选中旧文件,请通过 RunSettingsFilePath 使新文件生效。对于 MTP,请使用框架支持的 --settings 路径或现有的 MTP 配置,不要假定 VSTest 的 MSBuild 属性会生效。

步骤 7:验证
  1. 使用基线测试时相同的测试命令、筛选条件和配置。dotnet test 默认会生成项目;只有在需要单独定位编译失败时,才单独运行生成命令。
  2. 将发现、通过、失败和跳过的数量与迁移前的基线进行比较。
  3. 调查每一项数量差异;不要默默接受测试或数据行被丢弃。
  4. 确认不再存在 QualityTools 引用、1.x/2.x MSTest 包、.testsettings 或 <LegacySettings>。

验证

  • 正确引用 MSTest v3 包(或 MSTest.Sdk);已移除 v1/v2 引用
  • 项目生成成功,错误数为 0
  • 所有测试均通过(dotnet test)——将通过/失败数量与迁移前的基线进行比较
  • 已将 .testsettings 替换为 .runsettings(如适用)

下一步

完成 v3 迁移后,使用 migrate-mstest-v3-to-v4 迁移到 MSTest v4。

常见问题

问题解决方案
工作区中已有项目,却回复“哪个项目?”搜索 *.csproj/*.sln/*.slnx,并读取找到的文件
搜索已列出项目文件,却称“磁盘上没有项目”路径是在技能的基目录下重新拼接的。使用搜索结果中的原始路径重新打开;切勿创建替代项目
重写含有超过 16 个参数的 DataRow3.0.3+ 中有效,当前所有 3.x 版本都支持。只有 3.0.1/3.0.2 曾拒绝此类写法
非 MSTest.Sdk 的 VSTest 项目缺少 Microsoft.NET.Test.Sdk添加该包引用以支持 VSTest 发现测试
MSTest.Sdk v3 项目必须使用 VSTest 作为主运行器设置 <UseVSTest>true</UseVSTest>;不要仅因为还存在过渡期的 vstest.console 作业就切换运行器

评论

支持 Markdown