我正在运行一组集成测试,大部分测试都能在合理的时间范围内完成,但有两个测试需要等待特定条件(精确到金融市场条件),可能需要持续2-3个小时。因此,我希望实现以下两点:
- 在其他测试完成后再开始这两个测试
- 并行运行它们
是否有办法在NUnit / XUnit(或其他测试运行器)中实现这一点?
并行测试运行取决于测试运行器的参数。如果您使用 xUnit 控制台测试运行器,则可以使用 -parallel 参数或 MSBuild 选项,参见:https://xunit.net/docs/running-tests-in-parallel。但无论如何,您都必须将长时间运行的测试拆分为单独的测试类。
更难保证测试运行的顺序,您可以使用 TestCollection(但根据指南集合按顺序运行)。您可以重命名长时间运行的测试以将它们放在列表末尾,即 TestClass2 将在 TestClass1 之后执行。您还可以使用类别属性参数将测试分开,并通过 2 个命令运行它们:dotnet test --filter=TestCategory=LongTests(一个用于长时间运行的测试,另一个用于其他测试),请参见 https://learn.microsoft.com/ru-ru/dotnet/core/testing/selective-unit-tests?pivots=mstest
在其他测试完成后启动这两个测试
您可以将这两个测试保留在单独的NUnit测试项目中,以便您可以单独运行所有其他测试。
关于并行运行测试,此博客有一篇不错的文章:
https://blog.sanderaernouts.com/running-unit-tests-in-parallel-with-nunit
请标记您的测试夹具为Parallelizable属性,并将并行范围设置为ParallelScope.All。 创建一个名为TestScope的私有类,并实现IDisposable接口。 将所有启动和清理逻辑放置在TestScope构造函数和.Dispose()方法中。 将您的测试代码包装在using (var scope = new TestScope) { ... }块中。[TestFixture]
[Parallelizable(ParallelScope.All)]
public class MyClassTests {
[Test]
public void MyParallelTest() {
using(var scope = new TestScope()) {
scope.Sut.DoSomething();
scope.Repository.Received(1).Save();
}
}
private sealed class TestScope : IDisposable {
public IRepository Repository{get;}
public MyClass Sut {get;}
public TestScope() {
Repository = Substitute.For<IRepository>();
Sut = new MyClass(Repository);
}
public void Dispose() {
//clean-up code goes here
Repository?.Dispose()
}
}
}
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class MyClassTests {
[Test]
public void MyParallelTest() {
using(var scope = new TestScope()) {
scope.Sut.DoSomething();
scope.Repository.Received(1).Save();
}
}
private sealed class TestScope : IDisposable {
public IRepository Repository{get;}
public MyClass Sut {get;}
public TestScope() {
Repository = Substitute.For<IRepository>();
Sut = new MyClass(Repository);
}
public void Dispose() {
//clean-up code goes here
Repository?.Dispose()
}
}
}