migrate-xunit-to-xunit-v3

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

xunit.v3 Migration

xunit.v3 迁移指南

Migrate .NET test projects from xUnit.net v2 to xUnit.net v3. The outcome is a solution where all test projects reference
xunit.v3.*
packages, compiles cleanly, and all tests pass with the same results as before migration.
将.NET测试项目从xUnit.net v2迁移至xUnit.net v3。迁移完成后,解决方案中的所有测试项目将引用
xunit.v3.*
包,可正常编译,且所有测试的运行结果与迁移前一致。

When to Use

适用场景

  • Upgrading test projects from
    xunit
    (v2) packages to
    xunit.v3
  • Resolving compilation errors after updating xunit package references to v3
  • 将测试项目从
    xunit
    (v2)包升级至
    xunit.v3
  • 更新xUnit包引用至v3后解决编译错误

When Not to Use

不适用场景

  • Migrating between test frameworks (e.g., MSTest or NUnit to xUnit.net) — different effort entirely
  • Migrating from VSTest to Microsoft.Testing.Platform — use
    migrate-vstest-to-mtp
  • The projects already reference
    xunit.v3
    — migration is done
  • 跨测试框架迁移(例如从MSTest或NUnit迁移到xUnit.net)——这完全是不同的工作内容
  • 从VSTest迁移到Microsoft.Testing.Platform——请使用
    migrate-vstest-to-mtp
    工具
  • 项目已引用
    xunit.v3
    ——迁移已完成

Inputs

输入项

InputRequiredDescription
Test project or solutionYesThe .NET project or solution containing xUnit.net v2 test projects
输入项是否必填描述
测试项目或解决方案包含xUnit.net v2测试项目的.NET项目或解决方案

Workflow

工作流程

Commit strategy: Commit after each major step so the migration is reviewable and bisectable. Separate project file changes from code changes.
Prioritization: Steps 1-5 are required for every migration. Steps 6-12 are conditional — only apply the ones relevant to the project's code patterns. Skip steps that don't apply.
提交策略: 完成每个主要步骤后进行提交,确保迁移过程可审核、可二分排查。将项目文件变更与代码变更分开提交。
优先级说明: 步骤1-5是所有迁移都必须执行的。步骤6-12为可选步骤——仅应用与项目代码模式相关的步骤,跳过不适用的步骤。

Step 1: Identify xUnit.net projects and verify compatibility

步骤1:识别xUnit.net项目并验证兼容性

Search for test projects referencing xUnit.net v2 packages:
  • xunit
  • xunit.abstractions
  • xunit.assert
  • xunit.core
  • xunit.extensibility.core
  • xunit.extensibility.execution
  • xunit.runner.visualstudio
Make sure to check the package references in project files, MSBuild props and targets files, like
Directory.Build.props
,
Directory.Build.targets
, and
Directory.Packages.props
.
Verify target framework compatibility: xUnit.net v3 requires .NET 8+ or .NET Framework 4.7.2+. For test library projects, .NET Standard 2.0 is also supported. If any test projects have non-compatible target frameworks, STOP here — tell the user to upgrade the target framework first. Also verify the project uses SDK-style format.
搜索引用xUnit.net v2包的测试项目:
  • xunit
  • xunit.abstractions
  • xunit.assert
  • xunit.core
  • xunit.extensibility.core
  • xunit.extensibility.execution
  • xunit.runner.visualstudio
请务必检查项目文件、MSBuild属性和目标文件中的包引用,例如
Directory.Build.props
Directory.Build.targets
Directory.Packages.props
验证目标框架兼容性:xUnit.net v3要求** .NET 8+ .NET Framework 4.7.2+ **。对于测试库项目,也支持.NET Standard 2.0。如果任何测试项目使用不兼容的目标框架,请在此处停止——告知用户先升级目标框架。同时验证项目是否采用SDK风格格式。

Step 2: Update package references

步骤2:更新包引用

  1. Update any
    PackageReference
    or
    PackageVersion
    items for the new package names, based on the following mapping:
    • xunit
      xunit.v3
    • xunit.abstractions
      → Remove entirely
    • xunit.assert
      xunit.v3.assert
    • xunit.core
      xunit.v3.core
    • xunit.extensibility.core
      and
      xunit.extensibility.execution
      xunit.v3.extensibility.core
      (if both are referenced in a project consolidate to only a single entry as the two packages are merged)
  2. Update all
    xunit.v3.*
    packages to the latest correct version available on NuGet. Also update
    xunit.runner.visualstudio
    to the latest version.
  1. 根据以下映射关系,更新所有
    PackageReference
    PackageVersion
    项至新包名:
    • xunit
      xunit.v3
    • xunit.abstractions
      → 完全移除
    • xunit.assert
      xunit.v3.assert
    • xunit.core
      xunit.v3.core
    • xunit.extensibility.core
      xunit.extensibility.execution
      xunit.v3.extensibility.core
      (如果项目同时引用了这两个包,合并为单个引用即可,因为这两个包已合并)
  2. 将所有
    xunit.v3.*
    包更新至NuGet上可用的最新正确版本。同时将
    xunit.runner.visualstudio
    更新至最新版本。

Step 3: Set
OutputType
to
Exe

步骤3:设置
OutputType
Exe

In each test project (excluding test library projects), set
OutputType
to
Exe
in the project file:
xml
<PropertyGroup>
  <OutputType>Exe</OutputType>
</PropertyGroup>
Depending on the solution in hand, there might be a centralized place where this can be added. For example:
  • If all test projects share (or can share) a common
    Directory.Build.props
    , add the
    <OutputType>Exe</OutputType>
    property there. Note that the OutputType should not be added to
    Directory.Build.targets
    .
  • If all test projects share a name pattern (e.g.,
    *.Tests.csproj
    ), add a conditional property group in
    Directory.Build.props
    that applies only to those projects, like
    <OutputType Condition="$(MSBuildProjectName.EndsWith('.Tests'))">Exe</OutputType>
    . Adjust the condition as needed to target only test projects.
  • Otherwise, add the
    <OutputType>Exe</OutputType>
    property to each test project file individually.
在每个测试项目(测试库项目除外)的项目文件中,将
OutputType
设置为
Exe
xml
<PropertyGroup>
  <OutputType>Exe</OutputType>
</PropertyGroup>
根据手头的解决方案,可能存在可集中添加该配置的位置。例如:
  • 如果所有测试项目共享(或可共享)一个通用的
    Directory.Build.props
    ,则在其中的无条件
    PropertyGroup
    下添加
    <OutputType>Exe</OutputType>
    属性。注意不要将OutputType添加到
    Directory.Build.targets
    中。
  • 如果所有测试项目都有统一的命名模式(例如
    *.Tests.csproj
    ),则在
    Directory.Build.props
    中添加一个条件属性组,仅应用于这些项目,例如
    <OutputType Condition="$(MSBuildProjectName.EndsWith('.Tests'))">Exe</OutputType>
    。根据需要调整条件以仅针对测试项目。
  • 否则,将
    <OutputType>Exe</OutputType>
    属性单独添加到每个测试项目文件中。

Step 4: Configure test platform

步骤4:配置测试平台

Preserve the same test platform that was used with xUnit.net v2. xUnit.net v2 always uses VSTest except if the project used
YTest.MTP.XUnit2
.
  • If the project had a reference to
    YTest.MTP.XUnit2
    :
    • Remove the reference to
      YTest.MTP.XUnit2
      completely.
    • Add
      <UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
      to
      Directory.Build.props
      under an unconditional
      PropertyGroup
      .
  • If the project did NOT reference
    YTest.MTP.XUnit2
    (the common case):
    • Add
      <IsTestingPlatformApplication>false</IsTestingPlatformApplication>
      to
      Directory.Build.props
      under an unconditional
      PropertyGroup
      . If
      Directory.Build.props
      doesn't exist, create it. This keeps the project on VSTest.
保留与xUnit.net v2相同的测试平台。xUnit.net v2始终使用VSTest,除非项目使用了
YTest.MTP.XUnit2
  • 如果项目引用了
    YTest.MTP.XUnit2
    • 完全移除对
      YTest.MTP.XUnit2
      的引用。
    • Directory.Build.props
      的无条件
      PropertyGroup
      下添加
      <UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
  • 如果项目引用
    YTest.MTP.XUnit2
    (常见情况):
    • Directory.Build.props
      的无条件
      PropertyGroup
      下添加
      <IsTestingPlatformApplication>false</IsTestingPlatformApplication>
      。如果
      Directory.Build.props
      不存在,请创建它。这将使项目继续使用VSTest。

Step 5: Remove
Xunit.Abstractions
usings

步骤5:移除
Xunit.Abstractions
引用

Find any
using Xunit.Abstractions;
directives in C# files and remove them completely.
查找C#文件中所有
using Xunit.Abstractions;
指令并完全移除。

Step 6: Address
async void
breaking change (if applicable)

步骤6:处理
async void
破坏性变更(如适用)

In xUnit.net v3,
async void
test methods are no longer supported and will fail to compile. Search for any test methods declared with
async void
and change them to
async Task
. Test methods can be identified via the
[Fact]
or
[Theory]
attributes or other test attributes.
在xUnit.net v3中,
async void
测试方法不再被支持,且会编译失败。查找所有声明为
async void
的测试方法,并将其改为
async Task
。可通过
[Fact]
[Theory]
属性或其他测试属性识别测试方法。

Step 7: Address breaking change of attributes (if applicable)

步骤7:处理属性的破坏性变更(如适用)

In xUnit.net v3, some attributes were updated so that they accept a
System.Type
instead of two strings (fully qualified type name and assembly name). These attributes are:
  • CollectionBehaviorAttribute
  • TestCaseOrdererAttribute
  • TestCollectionOrdererAttribute
  • TestFrameworkAttribute
For example,
[assembly: CollectionBehavior("MyNamespace.MyCollectionFactory", "MyAssembly")]
must be converted to
[assembly: CollectionBehavior(typeof(MyNamespace.MyCollectionFactory))]
.
在xUnit.net v3中,部分属性已更新为接受
System.Type
类型参数,而非两个字符串(完全限定类型名和程序集名)。这些属性包括:
  • CollectionBehaviorAttribute
  • TestCaseOrdererAttribute
  • TestCollectionOrdererAttribute
  • TestFrameworkAttribute
例如,
[assembly: CollectionBehavior("MyNamespace.MyCollectionFactory", "MyAssembly")]
必须转换为
[assembly: CollectionBehavior(typeof(MyNamespace.MyCollectionFactory))]

Step 8: Inheriting from FactAttribute or TheoryAttribute (if applicable)

步骤8:继承自FactAttribute或TheoryAttribute(如适用)

Identify if there are any custom attributes that inherit from
FactAttribute
or
TheoryAttribute
. These custom user-defined attributes must now provide source information. For example, if the attribute looked like this:
csharp
internal sealed class MyFactAttribute : FactAttribute
{
    public MyFactAttribute()
    {
    }
}
it must be changed to this:
csharp
internal sealed class MyFactAttribute : FactAttribute
{
    public MyFactAttribute(
        [CallerFilePath] string? sourceFilePath = null,
        [CallerLineNumber] int sourceLineNumber = -1
    ) : base(sourceFilePath, sourceLineNumber)
    {
    }
}
识别是否存在继承自
FactAttribute
TheoryAttribute
的自定义属性。这些用户自定义属性现在必须提供源信息。例如,如果原属性如下:
csharp
internal sealed class MyFactAttribute : FactAttribute
{
    public MyFactAttribute()
    {
    }
}
必须修改为:
csharp
internal sealed class MyFactAttribute : FactAttribute
{
    public MyFactAttribute(
        [CallerFilePath] string? sourceFilePath = null,
        [CallerLineNumber] int sourceLineNumber = -1
    ) : base(sourceFilePath, sourceLineNumber)
    {
    }
}

Step 9: Inheriting from BeforeAfterTestAttribute (if applicable)

步骤9:继承自BeforeAfterTestAttribute(如适用)

Identify if there are any custom attributes that inherit from
BeforeAfterTestAttribute
. These custom user-defined attributes must update their method signatures. Previously, they would have
Before
/
After
overrides that look like this:
csharp
    public override void Before(MethodInfo methodUnderTest)
    {
        // Possibly some custom logic here
        base.Before(methodUnderTest);
        // Possibly some custom logic here
    }

    public override void After(MethodInfo methodUnderTest)
    {
        // Possibly some custom logic here
        base.After(methodUnderTest);
        // Possibly some custom logic here
    }
it must be changed to this:
csharp
    public override void Before(MethodInfo methodUnderTest, IXunitTest test)
    {
        // Possibly some custom logic here
        base.Before(methodUnderTest, test);
        // Possibly some custom logic here
    }

    public override void After(MethodInfo methodUnderTest, IXunitTest test)
    {
        // Possibly some custom logic here
        base.After(methodUnderTest, test);
        // Possibly some custom logic here
    }
识别是否存在继承自
BeforeAfterTestAttribute
的自定义属性。这些用户自定义属性必须更新其方法签名。之前的
Before
/
After
重写方法如下:
csharp
    public override void Before(MethodInfo methodUnderTest)
    {
        // 可能包含自定义逻辑
        base.Before(methodUnderTest);
        // 可能包含自定义逻辑
    }

    public override void After(MethodInfo methodUnderTest)
    {
        // 可能包含自定义逻辑
        base.After(methodUnderTest);
        // 可能包含自定义逻辑
    }
必须修改为:
csharp
    public override void Before(MethodInfo methodUnderTest, IXunitTest test)
    {
        // 可能包含自定义逻辑
        base.Before(methodUnderTest, test);
        // 可能包含自定义逻辑
    }

    public override void After(MethodInfo methodUnderTest, IXunitTest test)
    {
        // 可能包含自定义逻辑
        base.After(methodUnderTest, test);
        // 可能包含自定义逻辑
    }

Step 10: Address new xUnit analyzer warnings (if applicable)

步骤10:处理新的xUnit分析器警告(如适用)

xunit.v3 introduced new analyzer warnings. The most notable is xUnit1051 (use
TestContext.Current.CancellationToken
for methods accepting
CancellationToken
). Address these if present.
xunit.v3引入了新的分析器警告。最值得注意的是xUnit1051(为接受
CancellationToken
的方法使用
TestContext.Current.CancellationToken
)。如果存在此类警告,请进行处理。

Step 11: Migrate
Xunit.SkippableFact
(if applicable)

步骤11:迁移
Xunit.SkippableFact
(如适用)

If there are any package references to
Xunit.SkippableFact
, remove all these package references entirely.
Then, follow these steps to eliminate usages of APIs coming from the removed package reference:
  • Update any
    SkippableFact
    attribute to the regular
    Fact
    attribute.
  • Update any
    SkippableTheory
    attribute to the regular
    Theory
    attribute.
  • Change
    Skip.If
    method calls to
    Assert.SkipWhen
    .
  • Change
    Skip.IfNot
    method calls to
    Assert.SkipUnless
    .
如果项目引用了
Xunit.SkippableFact
包,请完全移除所有此类包引用。
然后按照以下步骤消除已移除包引用的API用法:
  • 将所有
    SkippableFact
    属性更新为常规
    Fact
    属性。
  • 将所有
    SkippableTheory
    属性更新为常规
    Theory
    属性。
  • Skip.If
    方法调用改为
    Assert.SkipWhen
  • Skip.IfNot
    方法调用改为
    Assert.SkipUnless

Step 12: Update companion packages (if applicable)

步骤12:更新配套包(如适用)

  • Xunit.Combinatorial
    1.x → latest 2.x
  • Xunit.StaFact
    1.x → latest 3.x
  • Xunit.Combinatorial
    1.x → 最新2.x版本
  • Xunit.StaFact
    1.x → 最新3.x版本

Step 13: Build and verify

步骤13:构建并验证

Build the solution and fix any remaining compilation errors. Run
dotnet test
to verify all tests pass with the same results as before migration.
构建解决方案并修复所有剩余的编译错误。运行
dotnet test
以验证所有测试的运行结果与迁移前一致。