I am having an issue with tests sporadically failing when using nunit 3 and using parallel test running.
We have a number of tests that currently are structured as follows
[TestFixture]
public class CalculateShipFromStoreShippingCost
{
private IService_service;
private IClient _client;
[SetUp]
public void SetUp()
{
_service = Substitute.For<IService>();
_client = new Client(_service);
}
[Test]
public async Task WhenScenario1()
{
_service.Apply(Args.Any<int>).Returns(1);
var result = _client.DoTheThing();
Assert.IsTrue(1,result);
}
[Test]
public async Task WhenScenario2()
{
_service.Apply(Args.Any<int>).Returns(2);
var result = _client.DoTheThing();
Assert.IsTrue(2,result);
}
}
Sometimes the test fail as one of the substitutes is returning the value for the other test.
How should this test be structured so that with Nunit it will run reliably when done in parallel
答案 0 :(得分:2)
您未在示例中显示任何Parallelizable
属性,因此我假设您在更高级别使用该属性,最有可能在程序集上。否则,不会发生并行执行。此外,由于您说测试用例并行运行,因此您显然已指定ParallelScope.Children
。
夹具中显示的两个测试用例不能并行运行。您应该记住,SetUp方法针对每个测试运行。因此,您的两个测试中的每一个都设置_service的值,它是CalculateShipFromStoreShippingCost
的单个实例的状态的一部分,由两个测试共享。这就是你看到&#34;错误&#34;替换有时被退回。
如果两个测试用例都改变了夹具的状态,则它们不可能并行可靠地运行。请注意,_service
的赋值是在测试方法本身还是在SetUp方法中进行并不重要 - 两者都作为测试用例的一部分执行。因此,您必须停止并行运行这两种情况或停止更改状态。
要停止并行运行测试,只需向每个测试方法添加[NonParallelizable]
即可。如果您未使用最新的框架版本,请改用[Parallelizable(ParallelScope.None)]
。你的其他测试将继续并行运行,但这两个测试不会。
或者,在程序集级别使用ParallelScope.Fixture
。这将导致灯具默认并行运行,而其中的各个测试用例各自按顺序运行。在汇编级别使用ParallelizableAttribute
时,有时最好采用更保守的方法,在一些有用的灯具中添加更多的并行性。
完全不同的方法是让您的测试无状态。消除_service
成员并在测试方法本身中使用本地值。您的每个测试都会添加两行,如...
var service = SubstituteFor<IService>();
var client = new Client(service);
如您的示例所示,我认为通过并行运行这两种方法可以获得很少的性能提升,因此除非我看到特定的性能原因,否则我不会使用最后一种方法。
作为最后的注释......如果你使用make你的灯具默认并行运行(使用汇编级属性或每个灯具上的属性)并且在你的测试用例中没有Parallelizable
属性, NUnit使用优化,其中夹具内的所有测试都在同一个线程上运行。这种上下文更改的节省通常可以弥补您希望通过并行运行获得的任何性能提升的损失。