migrate-nunit-to-mstest
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNUnit -> MSTest Migration
NUnit -> MSTest 迁移
Convert NUnit 3 or 4 tests to MSTest v4 without changing the target framework or test platform. A successful migration builds, discovers the same test cases, and preserves pass/fail, lifecycle, data, filtering, and concurrency semantics.
将 NUnit 3 或 4 测试转换为 MSTest v4,而不更改目标框架或测试平台。成功的迁移应能够构建、发现相同的测试用例,并保留通过/失败、生命周期、数据、筛选和并发语义。
Scope
范围
Use this skill only when the project contains NUnit packages or source and the user wants MSTest. If the project already uses MSTest and contains no NUnit tests, report that no framework migration is needed and make no changes.
Do not combine this framework conversion with a target-framework upgrade or VSTest/MTP migration. Complete and verify one migration before starting another.
仅当项目包含 NUnit 包或源代码且用户希望使用 MSTest 时使用此 skill。如果项目已使用 MSTest 且不包含 NUnit 测试,请报告无需进行框架迁移,并且不做任何更改。
不要将此框架转换与目标框架升级或 VSTest/MTP 迁移结合执行。完成并验证一次迁移后,再开始另一项。
Workspace Contract
Workspace Contract
- Search the current working directory for projects and source; never look for user files under this skill's directory.
- Classify the deliverable: "convert this project" means edit, build, and test; "give me a plan" means answer without editing.
- Preserve the user's requested project scope. Shared props may be changed only when they own NUnit package or runner configuration for that scope.
- The final response must state the source NUnit version, preserved runner, changed files, high-risk semantic mappings, and actual test counts.
- 在当前工作目录中搜索项目和源代码;绝不要在此 skill 的目录下查找用户文件。
- 确定交付物类型:“转换此项目”表示编辑、构建并测试;“给出计划”表示只回答,不进行编辑。
- 保留用户要求的项目范围。只有当 shared props 负责该范围内的 NUnit 包或 runner 配置时,才可以修改它们。
- 最终响应必须说明源 NUnit 版本、保留的 runner、更改的文件、高风险语义映射以及实际测试数量。
Response Mode
响应模式
- Full migration request: inspect, edit, build, and run tests. Do not stop after a plan.
- Focused compile error or API question: apply only the relevant mapping.
- Unsupported target framework: stop before changing packages. MSTest v4 requires .NET 8+ or .NET Framework 4.6.2+ for test applications; offer a separately approved TFM upgrade or MSTest v3.
- **完整迁移请求:**检查、编辑、构建并运行测试。不要在给出计划后停止。
- **聚焦的编译错误或 API 问题:**仅应用相关映射。
- **不支持的目标框架:**在更改包之前停止。MSTest v4 要求测试应用程序使用 .NET 8+ 或 .NET Framework 4.6.2+;可以提供单独批准的 TFM 升级方案或 MSTest v3。
Decisions That Change the Result
影响结果的决策
| Detected state | Required action |
|---|---|
| No NUnit package, namespace, attribute, or constraint remains | Stop, make no changes, and run the existing test command once to prove the already-MSTest project is healthy. |
| Source uses VSTest | Preserve VSTest. Retain and update an explicit |
| Source uses MTP | Replace NUnit-specific MTP configuration with MSTest MTP configuration. Prefer |
| NUnit uses its default fixture lifecycle | NUnit normally shares one fixture instance across all test cases; MSTest creates a new class instance per test. Move state that must remain class-shared behind static fields initialized by |
NUnit has no | Preserve serial execution. Do not add |
| NUnit explicitly enables parallel execution | Translate the effective scope and worker count. Never infer method-level parallelism from fixture-level settings. |
For detailed mappings, search for constructs present in the project and read only those sections.
references/mapping-cheatsheet.md| 检测到的状态 | 必需操作 |
|---|---|
| 未残留任何 NUnit 包、namespace、特性或 constraint | 停止,不做任何更改,并运行一次现有测试命令,以证明已使用 MSTest 的项目运行正常。 |
| 源代码使用 VSTest | 保留 VSTest。当仓库负责显式的 |
| 源代码使用 MTP | 将 NUnit 专用的 MTP 配置替换为 MSTest MTP 配置。优先使用 |
| NUnit 使用默认 fixture 生命周期 | NUnit 通常在所有测试用例之间共享一个 fixture 实例;MSTest 则为每个测试创建一个新的类实例。将必须由类共享的状态移到由 |
NUnit 没有 | 保留串行执行。不要添加 |
| NUnit 显式启用并行执行 | 转换生效范围和 worker 数量。绝不要根据 fixture 级设置推断方法级并行化。 |
有关详细映射,请在 中搜索项目中存在的构造,并只读取对应章节。
references/mapping-cheatsheet.mdFast Path
快速路径
For a routine migration, converge in four phases: one batched discovery pass, one edit pass, one , and one concise result.
dotnet test- Use an existing CI/test result as the baseline when available.
- Run a pre-edit baseline when counts are unavailable and the project contains parameterized tests, fixture state, namespace setup, retries, custom attributes, or explicit parallelization.
- Do not run separate restore, build, and test commands when is sufficient.
dotnet test - Do not delete NUnit runner configuration until its behavior has been translated.
对于常规迁移,分四个阶段完成:一次批量发现、一次编辑、一次 ,以及一次简洁的结果汇报。
dotnet test- 可用时,使用现有 CI/测试结果作为基线。
- 当无法获得测试数量,且项目包含参数化测试、fixture 状态、namespace setup、重试、自定义特性或显式并行化时,运行编辑前基线。
- 如果 已足够,不要分别运行 restore、build 和 test 命令。
dotnet test - 在 NUnit runner 配置的行为完成转换前,不要删除该配置。
Workflow
工作流
1. Establish the baseline
1. 建立基线
- Batch-read test projects, central package files, ,
global.json,.runsettings, and NUnit configuration.testconfig.json - Detect NUnit from ,
NUnit,NUnit3TestAdapter,NUnit.Analyzers,NUnit.Framework, andNUnit.Framework.Legacy.using NUnit.Framework - State whether the source is NUnit 3 or 4 from the resolved package version.
- Detect VSTest or MTP and preserve it. Use only when ambiguous.
platform-detection - Record target frameworks and stop if MSTest v4 does not support them.
- Inventory high-risk constructs:
- ,
[TestFixture(...)],[TestFixtureSource], constructors with parameters[FixtureLifeCycle] - ,
[TestCase],[TestCaseSource],TestCaseData,[Values],[Range],[Random],[Sequential], custom data attributes[Pairwise] - ,
[Theory],[Datapoint], automatic bool/enum datapoints,[DatapointSource]Assume.That - ,
[OneTimeSetUp],[OneTimeTearDown], inheritance-based setup[SetUpFixture] - ,
Assert.That,Assert.Multiple,Assert.Throws, collection constraintsAssert.Catch - ,
[Parallelizable],[NonParallelizable],[LevelOfParallelism],[Order][SingleThreaded] - ,
[Apartment],[RequiresThread],[CancelAfter][Timeout] - ,
[Culture],[Platform],[SetCulture][SetUICulture] - ,
[Explicit],[Repeat],[Retry], categories, properties,[MaxTime][TestOf] - ,
[DefaultFloatingPointTolerance], and deprecated fixture lifecycle aliases[NonTestAssembly]
- 批量读取测试项目、central package 文件、、
global.json、.runsettings和 NUnit 配置。testconfig.json - 从 、
NUnit、NUnit3TestAdapter、NUnit.Analyzers、NUnit.Framework和NUnit.Framework.Legacy检测 NUnit。using NUnit.Framework - 根据解析出的包版本说明源框架是 NUnit 3 还是 4。
- 检测 VSTest 或 MTP 并予以保留。仅在存在歧义时使用 。
platform-detection - 记录目标框架;如果 MSTest v4 不支持,则停止。
- 盘点高风险构造:
- 、
[TestFixture(...)]、[TestFixtureSource]、带参数的构造函数[FixtureLifeCycle] - 、
[TestCase]、[TestCaseSource]、TestCaseData、[Values]、[Range]、[Random]、[Sequential]、自定义数据特性[Pairwise] - 、
[Theory]、[Datapoint]、自动 bool/enum 数据点、[DatapointSource]Assume.That - 、
[OneTimeSetUp]、[OneTimeTearDown]、基于继承的 setup[SetUpFixture] - 、
Assert.That、Assert.Multiple、Assert.Throws、集合 constraintAssert.Catch - 、
[Parallelizable]、[NonParallelizable]、[LevelOfParallelism]、[Order][SingleThreaded] - 、
[Apartment]、[RequiresThread]、[CancelAfter][Timeout] - 、
[Culture]、[Platform]、[SetCulture][SetUICulture] - 、
[Explicit]、[Repeat]、[Retry]、categories、properties、[MaxTime][TestOf] - 、
[DefaultFloatingPointTolerance]和已弃用的 fixture 生命周期别名[NonTestAssembly]
2. Replace packages without switching runners
2. 替换包但不切换 runner
Remove NUnit-specific packages being replaced, including , , , NUnit console runner packages, and NUnit-specific MTP adapters.
NUnitNUnit3TestAdapterNUnit.AnalyzersDefault to the current stable MSTest v4 metapackage resolved from the configured package source:
xml
<PackageReference Include="MSTest" Version="4.4.0" />The pin is illustrative for the current release; during a real migration resolve and pin the current stable version. Preserve an explicit dependency for VSTest when the source project owns one. When preserving MTP, prefer ; otherwise use and .
Microsoft.NET.Test.SdkMSTest.SdkEnableMSTestRunner=trueOutputType=ExeDo not change . Remove NUnit adapter settings only after translating relevant behavior.
TargetFramework.runsettings移除正在被替换的 NUnit 专用包,包括 、、、NUnit console runner 包和 NUnit 专用 MTP adapter。
NUnitNUnit3TestAdapterNUnit.Analyzers默认使用从已配置包源解析出的当前稳定版 MSTest v4 metapackage:
xml
<PackageReference Include="MSTest" Version="4.4.0" />该固定版本仅用于示意当前发行版;实际迁移时,应解析并固定当前稳定版本。源项目负责显式的 依赖时,在保留 VSTest 的情况下保留该依赖。保留 MTP 时,优先使用 ;否则使用 和 。
Microsoft.NET.Test.SdkMSTest.SdkEnableMSTestRunner=trueOutputType=Exe不要更改 。只有在相关行为完成转换后,才能移除 NUnit adapter 设置。
TargetFramework.runsettings3. Perform the mechanical conversion
3. 执行机械转换
| NUnit | MSTest |
|---|---|
| |
| |
| |
| |
| |
| static |
| |
| |
| |
| |
| |
Remove and . Add when using the metapackage; supplies an implicit global using.
using NUnit.Framework;using NUnit.Framework.Legacy;using Microsoft.VisualStudio.TestTools.UnitTesting;MSTest.SdkDo not mechanically seal classes or flatten inherited setup methods.
| NUnit | MSTest |
|---|---|
| |
| |
| |
| |
| |
| static |
| |
| |
| |
| |
| 当 |
移除 和 。使用 metapackage 时,添加 ; 会提供隐式 global using。
using NUnit.Framework;using NUnit.Framework.Legacy;using Microsoft.VisualStudio.TestTools.UnitTesting;MSTest.Sdk不要机械地为类添加 ,也不要扁平化继承的 setup 方法。
sealed4. Resolve semantic mappings
4. 解决语义映射
Load the mapping cheatsheet for every high-risk construct found in Step 1. These rules are mandatory:
- NUnit's default differs from MSTest's per-test class instances. Preserve class-shared fields explicitly.
LifeCycle.SingleInstance - and
[OneTimeSetUp]become static MSTest methods. Move any instance state they use to a static holder rather than merely adding[OneTimeTearDown].static - NUnit and
Assert.Throws<T>require an exact exception type and map toThrows.TypeOf<T>. NUnitAssert.ThrowsExactly<T>andAssert.Catch<T>permit derived types and map toThrows.InstanceOf<T>.Assert.Throws<T> - NUnit maps to
Is.TypeOf<T>;Assert.IsExactInstanceOfType<T>maps toIs.InstanceOf<T>.Assert.IsInstanceOfType<T> - NUnit equality constraints compare sequences element-by-element. Use on MSTest 4.3+ or
Assert.AreSequenceEqualwith materialized lists; never use reference-basedCollectionAssert.AreEqualfor sequences.Assert.AreEqual - and
TestCase(ExpectedResult=...)require rewriting the target test to assert the expected result.TestCaseData.Returns(...) - Preserve per-row names, categories, and ignores by returning from
TestDataRow<T>when needed. NUnit row properties have no directDynamicDataequivalent and require a custom data source or an explicit metadata decision.TestDataRow<T> - MSTest 4.4 combinatorial attributes can map NUnit ,
[Combinatorial],[Values], and[Range]; add[Random]. Constructor semantics differ, so translate NUnit ranges and random bounds explicitly.using Microsoft.VisualStudio.TestTools.UnitTesting.Combinatorial;still requires explicit rows or a custom data source.[Sequential] - NUnit has no MSTest built-in. Preserve the exact generated rows in
[Pairwise]or use a verified pairwiseDynamicData; full Cartesian combinations change test counts and execution cost.ITestDataSource - Convert ,
[Theory], and[Datapoint]into explicit[DatapointSource]or combinatorial sources. Preserve automatic bool/enum values and the rule that a theory fails when every row violates its assumptions.DynamicData - ,
[Explicit], parameterized fixtures, fixture sources, and[Repeat]have no behavior-identical mechanical mapping. Rewrite deliberately or report manual follow-up; never approximate silently.Assert.Multiple - NUnit counts the initial attempt, while MSTest
[Retry(n)]counts retries after the initial attempt. Subtract one and review NUnit[Retry(n)]filters separately.RetryExceptions - maps to
[CancelAfter(ms)]. Under VSTest, remove NUnit's injected[Timeout(ms, CooperativeCancellation = true)]parameter and use an injected or property-basedCancellationToken; VSTest otherwise treats it as missing data. Retain a method token only when the preserved runner is proven to support injection. Expand fixture-level defaults to every affected test and lifecycle method.TestContext.CancellationToken - maps to
[Apartment(ApartmentState.STA)]or[STATestClass]. Set[STATestMethod]when async continuations must remain on the STA thread. MTA is the MSTest default.UseSTASynchronizationContext = trueand[RequiresThread]guarantee thread identity that MSTest attributes do not generally preserve; use a custom executor or report manual follow-up.[SingleThreaded] - Map NUnit platform and culture gates to ,
OSCondition, or aArchitectureConditionhelper. MapMemberConditionandSetCultureto setup/cleanup that saves and restores the original culture.SetUICulture - Expand into explicit deltas on every affected assertion. Preserve method-over-fixture-over-assembly precedence.
[DefaultFloatingPointTolerance]
针对第 1 步发现的每个高风险构造,加载 mapping cheatsheet。以下规则是强制要求:
- NUnit 默认的 与 MSTest 的每测试类实例不同。显式保留类共享字段。
LifeCycle.SingleInstance - 和
[OneTimeSetUp]转换为静态 MSTest 方法。将它们使用的任何实例状态移动到静态 holder 中,而不是仅仅添加[OneTimeTearDown]。static - NUnit 的 和
Assert.Throws<T>要求异常类型完全匹配,因此映射为Throws.TypeOf<T>。NUnit 的Assert.ThrowsExactly<T>和Assert.Catch<T>允许派生类型,因此映射为Throws.InstanceOf<T>。Assert.Throws<T> - NUnit 的 映射为
Is.TypeOf<T>;Assert.IsExactInstanceOfType<T>映射为Is.InstanceOf<T>。Assert.IsInstanceOfType<T> - NUnit equality constraint 会逐元素比较序列。在 MSTest 4.3+ 上使用 ,或者对已物化的列表使用
Assert.AreSequenceEqual;绝不要对序列使用基于引用的CollectionAssert.AreEqual。Assert.AreEqual - 和
TestCase(ExpectedResult=...)要求重写目标测试,使其断言预期结果。TestCaseData.Returns(...) - 需要时,通过从 返回
DynamicData来保留逐行名称、categories 和 ignores。NUnit 的行 properties 没有直接的TestDataRow<T>等价项,需要使用自定义数据源或作出明确的元数据决策。TestDataRow<T> - MSTest 4.4 combinatorial 特性可以映射 NUnit 、
[Combinatorial]、[Values]和[Range];添加[Random]。构造函数语义不同,因此要显式转换 NUnit ranges 和 random 边界。using Microsoft.VisualStudio.TestTools.UnitTesting.Combinatorial;仍需要显式行或自定义数据源。[Sequential] - NUnit 没有 MSTest 内置等价项。通过
[Pairwise]保留生成的精确行,或者使用经过验证的 pairwiseDynamicData;完整的笛卡尔积会改变测试数量和执行成本。ITestDataSource - 将 、
[Theory]和[Datapoint]转换为显式[DatapointSource]或 combinatorial 数据源。保留自动 bool/enum 值,以及当所有行都不满足假设时 theory 失败的规则。DynamicData - 、
[Explicit]、参数化 fixture、fixture source 和[Repeat]没有行为完全一致的机械映射。应有意重写或报告需要人工跟进;绝不要静默近似处理。Assert.Multiple - NUnit 将初始尝试计入次数,而 MSTest
[Retry(n)]统计的是初始尝试之后的重试次数。减一,并单独审查 NUnit 的[Retry(n)]筛选器。RetryExceptions - 映射为
[CancelAfter(ms)]。在 VSTest 下,移除 NUnit 注入的[Timeout(ms, CooperativeCancellation = true)]参数,改用注入式或基于属性的CancellationToken;否则 VSTest 会将其视为缺少数据。仅当已证明保留的 runner 支持注入时,才保留方法 token。将 fixture 级默认值扩展到每个受影响的测试和生命周期方法。TestContext.CancellationToken - 映射为
[Apartment(ApartmentState.STA)]或[STATestClass]。当 async continuation 必须保留在 STA 线程上时,设置[STATestMethod]。MTA 是 MSTest 默认值。UseSTASynchronizationContext = true和[RequiresThread]保证线程身份,而 MSTest 特性通常无法保留这一点;请使用自定义 executor 或报告需要人工跟进。[SingleThreaded] - 将 NUnit 平台和 culture 门控映射到 、
OSCondition或ArchitectureConditionhelper。将MemberCondition和SetCulture映射到保存并恢复原 culture 的 setup/cleanup。SetUICulture - 将 展开为每个受影响断言上的显式 delta。保留 method-over-fixture-over-assembly 优先级。
[DefaultFloatingPointTolerance]
5. Preserve lifecycle and namespace setup
5. 保留生命周期和 namespace setup
- and
[SetUp]remain per-test lifecycle methods.[TearDown] - For NUnit's default single fixture instance, audit every mutable instance field. If tests depend on sharing, use static state created by and released by
[ClassInitialize].[ClassCleanup] - already matches MSTest class instantiation; remove the attribute and keep per-test instance state.
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)] - is namespace-scoped in NUnit. MSTest assembly initialization is assembly-wide. Use
[SetUpFixture]only when the NUnit setup already covers the whole assembly; otherwise move setup into the affected classes or a shared helper without widening scope.[AssemblyInitialize] - Preserve setup/cleanup inheritance order. Do not merge base and derived methods unless the resulting order is proven equivalent.
- Map NUnit to an injected or property-based MSTest
TestContext.WriteLine. Translate directory, test-name, and attachment APIs individually.TestContext.WriteLine
- 和
[SetUp]继续作为每测试生命周期方法。[TearDown] - 对于 NUnit 默认的单一 fixture 实例,审查每个可变实例字段。如果测试依赖共享状态,则使用由 创建、由
[ClassInitialize]释放的静态状态。[ClassCleanup] - 已与 MSTest 类实例化方式一致;移除该特性并保留每测试实例状态。
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)] - 在 NUnit 中作用于 namespace,而 MSTest 的程序集初始化作用于整个程序集。仅当 NUnit setup 已覆盖整个程序集时,才使用
[SetUpFixture];否则将 setup 移入受影响的类或共享 helper,而不扩大范围。[AssemblyInitialize] - 保留 setup/cleanup 的继承顺序。除非能够证明结果顺序等价,否则不要合并基类和派生类方法。
- 将 NUnit 映射到注入式或基于属性的 MSTest
TestContext.WriteLine。分别转换 directory、test-name 和 attachment API。TestContext.WriteLine
6. Preserve parallelization and ordering
6. 保留并行化和顺序
NUnit and MSTest both run serially by default. Do not add parallelization for an unconfigured NUnit project.
When NUnit explicitly opts in:
- assembly ->
[Parallelizable(ParallelScope.Fixtures)][assembly: Parallelize(Workers = N, Scope = ExecutionScope.ClassLevel)] - fixture or method-level parallelism -> method-level MSTest parallelization only after confirming shared instance state is safe
[Parallelizable(ParallelScope.Children)] - ->
[NonParallelizable]when parallelization is enabled[DoNotParallelize] - ->
[LevelOfParallelism(N)]Workers = N - resource-specific serialization can use MSTest 4.4 when it preserves a narrower lock than
[ResourceLock("key")][DoNotParallelize]
NUnit is not general dependency semantics. Use MSTest 4.4 only when the source truly expresses a prerequisite; otherwise remove ordering by making tests independent or report manual follow-up.
[Order][DependsOn]NUnit 和 MSTest 默认均以串行方式运行。不要为未配置并行化的 NUnit 项目添加并行化。
当 NUnit 显式选择并行化时:
- 程序集级 ->
[Parallelizable(ParallelScope.Fixtures)][assembly: Parallelize(Workers = N, Scope = ExecutionScope.ClassLevel)] - fixture 级 或方法级并行化 -> 仅在确认共享实例状态安全后,转换为 MSTest 方法级并行化
[Parallelizable(ParallelScope.Children)] - -> 启用并行化时转换为
[NonParallelizable][DoNotParallelize] - ->
[LevelOfParallelism(N)]Workers = N - 如果 MSTest 4.4 的 能保留比
[ResourceLock("key")]更窄的锁范围,可以使用它实现特定资源的串行化[DoNotParallelize]
NUnit 不表示通用的依赖关系。仅当源代码确实表达了前置依赖时,才使用 MSTest 4.4 ;否则应通过让测试彼此独立来移除顺序要求,或者报告需要人工跟进。
[Order][DependsOn]7. Verify parity
7. 验证一致性
- Run tests with the same platform, filter, and configuration used for the baseline.
- Compare discovered, passed, failed, and skipped counts.
- Investigate every difference:
- missing rows -> ,
DataRow, combinatorial, or row metadata conversionDynamicData - changed exceptions/types -> exact-vs-derived mapping
- state failures -> NUnit single-instance fixture semantics or setup order
- concurrency failures -> ,
Parallelize, worker count, or resource locksDoNotParallelize - changed skips -> ,
Ignore, row-level ignore, or retry behaviorExplicit
- missing rows ->
- Confirm no NUnit package, namespace, attribute, constraint, adapter setting, or custom NUnit extension remains unless documented for follow-up.
- Read back high-risk changed files and name the exact target APIs in the result.
Use this final response shape:
- Changed: files and exact high-risk mappings.
- Verified: final command and discovered/passed/failed/skipped counts.
- Preserved: target framework, test platform, fixture scope, and concurrency choice.
- Remaining: manual follow-up, or none.
- 使用与基线相同的平台、筛选条件和配置运行测试。
- 比较发现、通过、失败和跳过的测试数量。
- 调查每一个差异:
- 缺少行 -> 检查 、
DataRow、combinatorial 或行元数据转换DynamicData - 异常或类型发生变化 -> 检查精确类型与派生类型映射
- 状态失败 -> 检查 NUnit 单一实例 fixture 语义或 setup 顺序
- 并发失败 -> 检查 、
Parallelize、worker 数量或 resource lockDoNotParallelize - 跳过状态发生变化 -> 检查 、
Ignore、行级 ignore 或 retry 行为Explicit
- 缺少行 -> 检查
- 确认没有残留任何 NUnit 包、namespace、特性、constraint、adapter 设置或自定义 NUnit extension,除非已记录为后续跟进事项。
- 回读高风险修改文件,并在结果中指出准确的目标 API。
使用以下最终响应结构:
- **变更(Changed):**文件和准确的高风险映射。
- **验证(Verified):**最终命令以及发现、通过、失败和跳过的测试数量。
- **保留(Preserved):**目标框架、测试平台、fixture 范围和并发选项。
- **剩余事项(Remaining):**需要人工跟进的事项,或无。
Completion Criteria
完成标准
- NUnit version and test platform were identified
- NUnit packages and source constructs were converted
- Target framework and test platform stayed unchanged
- Default single-instance fixture semantics were audited and preserved where observable
- Data-row metadata and assertion semantics were preserved
- Namespace setup and parallelization scope were not silently widened
- Every attribute on NUnit's official attribute index was classified as direct, rewritten, removed, or manual
- Build succeeds and test results match the baseline
- Unsupported custom extensions or behavior are called out
- 已识别 NUnit 版本和测试平台
- 已转换 NUnit 包和源代码构造
- 目标框架和测试平台保持不变
- 已审查默认的单一实例 fixture 语义,并在可观察范围内予以保留
- 已保留数据行元数据和断言语义
- 未静默扩大 namespace setup 和并行化范围
- 已将 NUnit 官方特性索引中的每个特性分类为直接转换、重写、移除或需要人工处理
- 构建成功,且测试结果与基线一致
- 已指出不受支持的自定义 extension 或行为
Follow-up
后续处理
Run separately if the user also wants MTP. Use only after parity is established.
migrate-vstest-to-mtpwriting-mstest-tests如果用户还希望迁移到 MTP,请单独运行 。仅在验证一致性完成后,才使用 。
migrate-vstest-to-mtpwriting-mstest-tests