作者:Amaury Levé Marco Rossignoli Jakub Jareš
排版:Alan Wang
我们很高兴推出 MSTest 运行器,这是一款全新的轻量级 MSTest 测试运行器。这个新的运行器使测试更加便携和可靠,运行速度更快,并且具有可扩展性,可以为您提供自选式的测试体验,以及为您添加成功所需的工具。
它是什么?
MSTest Runner 是一种将 MSTest 测试作为独立的可移植可执行文件构建和运行的方法。 您只需要一个简单的控制台应用程序用于托管和运行测试,不需要任何外部工具(例如 vstest.console、dotnet test 或 Visual Studio)来运行测试。这使其成为在那些性能方面或存储方面有限的设备上编写测试的完美工具。
安装 MSTest 运行器
任何经验水平的开发人员和任何规模的项目都可以体验新 MSTest 运行程序的速度和可移植性。我们欢迎您尝试一下!
自版本 3.2.0 起,MSTest 运行器就与 MSTest.TestAdapter NuGet 包捆绑在一起。
在您的项目中启用它只需要安装更新包并设置两个 MSBuild 属性 和 :
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><!-- Enable the MSTest runner, this is an opt-in feature --><EnableMSTestRunner>true</EnableMSTestRunner><!-- We need to produce an executable and not a DLL --><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable><IsPackable>false</IsPackable></PropertyGroup><ItemGroup><!-- MSTest meta package is the recommended way to reference MSTest.It's equivalent to referencing:Microsoft.NET.Test.SdkMSTest.TestAdapterMSTest.TestFrameworkMSTest.Analyzers--> <PackageReference Include="MSTest" Version="3.2.0" /></ItemGroup></Project>
进行这些更改后,重新构建您的测试项目,您的测试将创建一个直接运行测试的可执行文件:
完整示例 – Simple1
在上面的屏幕截图中,您可以看到我们不需要运行 dotnet test、使用 vstest.console 或在 Visual Studio 中运行来运行我们的测试。我们的测试只是一个用于发现并运行测试的普通控制台应用程序。
也就是说,运行器确实与 dotnet test、vstest.console、Visual Studio Test Explorer 和 Visual Studio Code Test Explorer 集成,为您提供与您习惯相同的体验。请参阅我们的文档以了解更多信息。
使用运行器 对比 VSTest 的优点
可移植性
直接从可执行文件运行测试可以消除运行测试通常所需的大量复杂性和基础架构。由于测试项目不再特殊,因此您可以使用现有的 dotnet 工具对测试项目执行有趣的操作,例如将它们构建为自包含的:
dotnet publish --runtime win-x64 --self-contained
上面的示例将发布测试项目及其需要的运行时。这允许您将项目移动到没有此运行时的计算机上,并在多台计算机上运行测试,而无需进行额外的设置。
或者,您可以使用此功能在每次失败的测试运行后创建一个 zip 文件,以便在本地以相同的方式重现在 CI 服务器上出现的故障,并用简便的方式来交互式调试失败的运行。
下面是针对托管在没有可用 dotnet SDK 的 docker 容器中的 dotnet 应用程序运行测试的另一个示例。对于我们的高级用户来说,这是一个经常遇到问题的场景:
RunInDocker> docker build . -t my-server-testsRunInDocker> docker run my-server-tests
Microsoft(R) Testing Platform Execution Command Line Tool
Version: 1.0.0-preview.23622.9+fe96e7475 (UTC 2023/12/22)
RuntimeInformation: linux-x64 - .NET 8.0.0
Copyright(c) Microsoft Corporation. All rights reserved.
info: Microsoft.Hosting.Lifetime[14]Now listening on: http://[::]:8080
info: Microsoft.Hosting.Lifetime[0]Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]Content root path: /test/test
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]Request starting HTTP/1.1 GET http://localhost:8080/hello - - -
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]Executing endpoint 'HTTP: GET /hello'
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]Executed endpoint 'HTTP: GET /hello'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]Request finished HTTP/1.1 GET http://localhost:8080/hello - 200 - text/plain;+charset=utf-8 73.5556ms
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 1.7s - MyServer.Tests.dll (linux-x64 - .NET 8.0.0)
完整示例 – RunInDocker
MSTest 运行器可移植性的另一个优点是,您现在可以像调试任何常规可执行文件一样轻松调试测试。例如,在 Visual Studio 中,您现在可以简单地进行如下操作:
- 在“解决方案资源管理器”中导航要运行的测试项目,右键选择它并选择“Set as Startup Project”。
- 导航到要调试的测试并添加断点
- 选择 Debug > Start Debugging(或使用 F5)来运行选定的测试项目。
您还可以使用 --filter 筛选出您想要调试的一个或多个方法,以加快调试速度。例如,–filter MSTestNamespace.UnitTest1.TestMethod2 仅允许运行(调试)命名空间 MSTestNamespace 中的类 UnitTest1 中的测试方法 TestMethod2。 您可以在文本中找到有关可用过滤器的更多信息。以下是 launchSettings.json 的示例:
{"profiles": {"MSTestProject": {"commandName": "Project","commandLineArgs": "--filter MSTestNamespace.UnitTest1.TestMethod2"}}
}
最后,我们正在研究使 MSTest 兼容 NativeAOT,以便您在 NativeAOT 模式下测试应用程序。 为了能够做到这一点,我们需要对 MSTest 的内部结构进行重大修改,如果您觉得这有用,请在我们的 GitHub 问题上添加评论或点赞。
性能
MSTest 运行器使用更少的进程和更少的进程跳跃来运行测试(相较于 dotnet 测试),以节省服务器上的资源。
它还避免了进程间串行通信的需要,并依赖现代 .NET API 来提高并行性并减少内存占用。
在改用新的 MSTest 运行器的 Microsoft 内部项目中,我们发现了在 CPU 和内存的使用方面得到了大幅的降低。一些项目在使用 dotnet 测试时,完成测试的速度提高了3倍,而使用的内存却减少了4倍。
这些数字可能令人印象深刻,但当您在测试项目中启用并行测试运行时,您将可以获得更大的收益。为此,我们为 MSTest 代码分析添加了一组新的分析器,以促进良好的实践和正确的测试设置。
可靠性
MSTest 运行器正在设置新的默认值,这些默认值更安全,并且使降低您意外地错过运行任何测试的可能性。我们倾向于做出更加严格决定,并在您不需要这种严格性的时候,让您自己选择。
例如,当项目没有运行任何测试时,MSTest 运行器将默认失败,这可以通过 --minimum-expected-tests 来控制,默认值为 1。您可以将其设置为 0,这样在没有测试的情况下不会失败,您也可以轻松地将其设置为更高的数字以防止回归:
C:\p\testfx\samples\mstest-runner\Simple1> C:\p\testfx\artifacts\bin\Simple1\Debug\net8.0\Simple1.exe --minimum-expected-tests 10
Microsoft(R) Testing Platform Execution Command Line Tool
Version: 1.0.0-preview.23622.9+fe96e7475 (UTC 2023/12/22)
RuntimeInformation: win-x64 - .NET 8.0.0
Copyright(c) Microsoft Corporation. All rights reserved.
Minimum expected tests policy violation, tests ran 1, minimum expected 10 - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 153ms - Simple1.dll (win-x64 - .NET 8.0.0)
但这并不是唯一的可靠性改进。我们从头开始编写 MSTest 运行器,使其更加可靠。
MSTest 运行器由于新的架构,不再依赖于文件夹扫描、动态加载或反射来检测和加载扩展。 这使得在本地和 CI 中更容易实现相同的行为,并且显着缩短了启动测试应用程序和运行第一个测试之间的时间。
运行器被设计为异步且可并行,从而防止使用 VSTest 时出现的一些挂起或死锁。
运行器不会检测目标框架或平台,或任何其他 .NET 配置。它完全依赖 .NET 平台来完成这项工作。这避免了逻辑重复,并避免了当规则突然改变时许多会破坏测试的边缘情况。
可扩展性
MSTest 运行器基于新的准系统测试平台和可扩展性模型,可以轻松扩展或覆盖测试执行的许多方面。
现在可以容易地提供您自己的报告生成器、测试编排、记录器,甚至增加可用的命令行选项。
Microsoft 提供了一系列可选扩展,以便您配备运行测试和排除故障所需的一切。
我们将继续努力提供更多扩展和功能,以丰富您的测试体验。 如果您有特定需求或想帮助开发库扩展,请与我们联系。
总结
MSTest 运行器是一个用于运行 MSTest 测试的高性能、可托管、可扩展、可靠且集成的解决方案。无论您是技术爱好者、使用 VSTest 时遇到一些问题还是只是好奇,我们都欢迎您尝试一下并在本文下面分享您的反馈。
特别感谢
我们要感谢团队的不懈努力和坚定不移的承诺使这一功能得以实现。
此外,我们还要对帮助试用并支持这一举措的内部团队表示衷心的感谢。