通过


从 MSTest v3 迁移到 v4

稳定版 MSTest v4 现已推出。 此迁移指南探讨 MSTest v4 中更改的内容以及如何迁移到此版本。

Note

一般来说,MSTest v4 与 MSTest v3 在二进制级别上不兼容。 针对 v3 编译的任何库都必须针对 v4 重新编译。

源代码破坏性变更

这些重大变更可能会导致你的测试项目无法编译。

TestMethodAttribute 重大变化

将 TestMethodAttribute.Execute 更改为 TestMethodAttribute.ExecuteAsync

如果实现自己的TestMethodAttribute,则需要将 Execute 替代更改为 ExecuteAsync。 此更改旨在修复由 API 的同步阻塞性质导致的长期存在的死锁错误。

例如,如果您以前有如下内容:

public sealed class MyTestMethodAttribute : TestMethodAttribute
{
    public override TestResult[] Execute(ITestMethod testMethod)
    {
        // ...
        return result;
    }
}

需要将其更改为以下内容:

public sealed class MyTestMethodAttribute : TestMethodAttribute
{
    public override Task<TestResult[]> ExecuteAsync(ITestMethod testMethod)
    {
        // ...
        return Task.FromResult(result);
    }
}

TestMethodAttribute 现在使用调用方信息属性

构造函数 TestMethodAttribute 已更改,现在包含用于提供调用方信息属性的参数。

  • 如果继承自 TestMethodAttribute,还应提供这样一个构造函数,用于将信息传播到基类。

    public class MyTestMethodAttribute : TestMethodAttribute
    {
        public MyTestMethodAttribute([CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = -1)
        : base(callerFilePath, callerLineNumber)
        {
        }
    }
    
  • 如果你有属性应用,如 [TestMethodAttribute("Custom display name")],请将其切换到 [TestMethodAttribute(DisplayName = "Custom display name")]

Tip

即将发布包含代码修正的分析器,帮助你进行此迁移。 在 IDE 中单击一次即可修复解决方案中的所有实例。

ClassCleanupBehavior 枚举类型已删除

现在,ClassCleanup 方法仅在测试类的末尾运行。 删除了对在汇编结束时运行类清理的支持。 如果必须运行程序集结束时的清理逻辑,请在 AssemblyCleanup 中执行,而不是在 ClassCleanup 中执行。 类清理的默认行为以前是“EndOfAssembly”,用户认为这是一个错误。

如果以前有以下代码:

[ClassCleanup(ClassCleanupBehavior.EndOfClass)]
public static void ClassCleanup(TestContext testContext)
{
}

需要将其更改为以下内容:

[ClassCleanup]
public static void ClassCleanup(TestContext testContext)
{
}

TestContext.Properties 现在是 IDictionary<string 和 object>

以前,TestContext.Properties 是一个 IDictionary。 为了提供更好的键入功能,现在它是 IDictionary<string, object>

如果调用 TestContext.Properties.Contains,请将其更新为调用 TestContext.Properties.ContainsKey

TestTimeout 枚举已删除

此枚举只有一个成员, Infinite其值为 int.MaxValue。 如果有 [Timeout(TestTimeout.Infinite)] 的实例,请将其更新为 [Timeout(int.MaxValue)]

TestContext.ManagedType 现已删除

删除该属性 TestContext.ManagedType 。 请改用 TestContext.FullyQualifiedTestClassName

不供公众使用的类型将被设为内部类型或被删除。

  • Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.ObjectModel.ITestMethod 被设为内部状态。
    • 请注意,此接口与 TestFramework 程序集中的 ITestMethod 不同,后者并未发生改变。
    • Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface.ObjectModel.ITestMethod 对用户而言没有任何有效用途,因此它被设置为内部的。
  • 某些已过时的类型被设置为内部使用。 这包括:
    • MSTestDiscoverer
    • MSTestExecutor
    • AssemblyResolver (程序集解析器)
    • LogMessageListener
    • TestExecutionManager
    • TestMethodInfo
    • TestResultExtensions
    • UnitTestOutcomeExtensions
    • GenericParameterHelper
    • 平台服务程序集中的类型

核实 API 签名更改

  • 接受 messageobject[] 这两个参数的断言 API 现在仅接受 message。 请改用字符串内插。 这是支持断言 API 的调用方参数表达式的必要更改。
  • Assert.AreEqual 的 API IEquatable<T> 已被删除。 此 API 的用户很少,API 具有误导性。 大多数用户不受此删除的影响,因为 API 最初不存在于 MSTest v3 中,并在 3.2.2 中引入。
    • 此 API 也会导致 F# 用户出现问题。 例如,请参阅 fsharp/fslang-suggestions/issues/905
    • 如果受到影响,将收到有关泛型类型推理的编译错误。 只需将类型参数显式指定为 object
  • 弃用的Assert.ThrowsException API 已被移除。 MSTest 3.10 中的分析器和代码修复有助于帮助你迁移到更新的 API。
  • 现在的 Assert.IsInstanceOfType<T>(x, out var t) 用法应更改为 var t = Assert.IsInstanceOfType<T>(x)
    • 没有 out 参数的现有替代已更改为返回 T 类型(而不是 void 类型)的实例。 这只是 F# 的一个重大变化。

已删除 ExpectedExceptionAttribute API

已废弃的 ExpectedExceptionAttribute API 已被移除。 MSTest 3.2 中的分析器(MSTEST0006)和代码修正可帮助迁移到 Assert.Throws

例如,如果你有以下代码:

[ExpectedException(typeof(SomeExceptionType))]
[TestMethod]
public void TestMethod()
{
    MyCall();
}

你(或分析器和代码修复)需要将其更改为如下内容:

[TestMethod]
public void TestMethod()
{
    Assert.ThrowsExactly<SomeExceptionType>(() => MyCall());
}

已删除不支持的目标框架

删除对目标框架 .NET Core 3.1 到 .NET 7 的支持。 支持的最低 .NET 版本为 .NET 8。 此更改不会影响 .NET Framework。 .NET Framework 4.6.2 仍然是受支持的最低 .NET Framework 目标。

展开策略已从单个数据源转移到 TestMethodAttribute

展开策略是 MSTest 3.7 中引入的一项最新功能,旨在解决已知限制。 该属性已添加到单个数据源,如 DataRowAttributeDynamicDataAttribute。 此属性已移动到 TestMethodAttribute

ConditionBaseAttribute.ShouldRun API 更改

ConditionBaseAttribute.ShouldRun 属性已重命名为 IsConditionMet. 这使得更加明确,不应在实现中使用ConditionMode

默认情况下,多个分析器被设置为启用警告

以下分析器的默认严重性从信息更改为警告:

行为中断性变更

这些重大变更可能会影响运行时的行为。

在 Microsoft.Testing.Platform 下运行时,DisableAppDomain 现在默认为 true

在 v4 中,使用 Microsoft.Testing.Platform 运行时,默认情况下(未指定)禁用 AppDomains,因为大多数情况下提供的自定义隔离是无用的,并且对性能有重要影响(在隔离下运行时最多 30% 慢)。

但是,此功能仍可用。 如果有需要它的场景,请在 runsettings 中添加 DisableAppDomain 设置。

重要

启用 AppDomain 隔离后,MSTest 将在所有测试完成后卸载 AppDomain,这会中止与 AppDomain 关联的所有线程,包括前台线程。 因此,如果在 MSTest v3 中永久运行前台线程,测试运行将成功完成。 在 MSTest v4 中同一场景将会挂起,这是理想的情况,因为当前台线程仍在运行时,进程不应退出。

使用不当时会出现 TestContext 异常

TestContext 类型将传递给 AssemblyInitialize、ClassInitialize 和测试,但每个阶段的可用信息不同。 现在,当访问与测试运行信息相关的属性作为AssemblyInitializeClassInitialize的一部分时,会引发异常。

  • TestContext.FullyQualifiedTestClassName 无法在程序集初始化中访问。
  • TestContext.TestName 无法在程序集初始化或类初始化中访问。

TestCase.Id 正在被更改

为了解决许多用户提交的 bug 长期未解决问题,已更改了 TestCase.Id 生成。 这会影响 Azure DevOps 功能,例如跟踪一段时间内的测试失败。

TreatDiscoveryWarningsAsErrors 现在默认设置为 true

v4 使用更严格的默认值。 因此,默认值 TreatDiscoveryWarningsAsErrors 为现在 true。 这应该是大多数用户的透明更改,应该可帮助其他用户发现隐藏的 bug。

使用 Microsoft.Testing.Platform 时,MSTest.Sdk 不再添加 Microsoft.NET.Test.Sdk 引用

默认情况下,MSTest.Sdk 使用 Microsoft.Testing.Platform。 UseVSTest如果 MSBuild 属性设置为 true,它将改用 VSTest。 在 MSTest 3.x 中,SDK 添加了对 Microsoft.NET.Test.Sdk(这带来了 VSTest 支持)的引用,即使在使用 Microsoft.Testing.Platform 时也是如此。 当使用 Microsoft.Testing.Platform 运行并在 MSTest v4 中删除时,不需要此包引用。

如果您仍希望支持 VSTest(例如,要使用 vstest.console 运行),则需要手动向项目中添加对 Microsoft.NET.Test.Sdk NuGet 包的引用。