如何在 xUnit 中同时同步 运行 测试?
How to synchronize concurrently running tests in xUnit?
我需要并行启动可能有数十个测试用例,但有一个问题 - 所有测试用例都达到了一个点,即无论有多少个测试用例,单个操作都应该只执行一次 运行.此操作结束后,测试可以恢复并独立继续 运行。
现在我在 NUnit 中有以下实现:
[TestFixture]
public class ScheduleJobTest
{
private static readonly Subject<Unit> s_tickets = new Subject<Unit>();
[OneTimeSetUp]
public static void SetUp()
{
Task.Run(() => s_tickets
.Throttle(TimeSpan.FromSeconds(1))
.SelectMany(_ => PollSchedulesNow())
.DefaultIfEmpty()
.GetAwaiter()
.GetResult());
}
[OneTimeTearDown]
public static void TearDown()
{
s_tickets.OnCompleted();
}
private static IObservable<Unit> PollSchedulesNow()
{
// Do something that eventually unblocks all the test cases
}
[TestCaseSource(nameof(ProvideNamespaces)), Parallelizable(ParallelScope.Children)]
public void ScheduleJob(NamespaceConnectionInfo nci)
{
// Do something
s_tickets.OnNext(Unit.Default);
// Resume - blocks until the actions of PollSchedulesNow take effect
}
private static IEnumerable<TestCaseData> ProvideNamespaces()
{
return ...
}
}
每个测试用例都会为应该只执行一次的特殊操作排队一张票。节流确保只要票在最多一秒的时间间隔内到达,就不会发生任何事情。但是一旦发生暂停,它就会触发该特殊操作。如果出于某种原因,在暂停之后会有更多的测试用例,那么将再次调用特殊操作——这很好。我只是不希望它同时被 100 个并发测试用例调用 100 次 运行。
这是我在 NUnit 中所能想到的最好的。有没有更好的方法在 xUnit 中实现它?或者也许我首先需要一个不同的框架?
首先:不可以。除非您在测试中自己编写协调代码,否则 NUnit 无法跨测试进行协调。即使那样,您也必须确保 NUnit 一起运行所有这些,如果没有您的帮助,它可能会也可能不会。
但是是的!你可以完成你想要的。您正在尝试使用多个 NUnit 测试对本质上是跨多个线程的单个测试进行建模。不要那样做!编写一个单独的测试,它可以根据需要生成尽可能多的独立线程。等待它们完成,然后验证该操作是否只执行了一次。这里只有一个断言,证明只有一个测试。
您可以针对不同数量的线程和错误条件重复此操作,次数不限。这些变化中的每一个都是一个单一的测试。
我需要并行启动可能有数十个测试用例,但有一个问题 - 所有测试用例都达到了一个点,即无论有多少个测试用例,单个操作都应该只执行一次 运行.此操作结束后,测试可以恢复并独立继续 运行。
现在我在 NUnit 中有以下实现:
[TestFixture]
public class ScheduleJobTest
{
private static readonly Subject<Unit> s_tickets = new Subject<Unit>();
[OneTimeSetUp]
public static void SetUp()
{
Task.Run(() => s_tickets
.Throttle(TimeSpan.FromSeconds(1))
.SelectMany(_ => PollSchedulesNow())
.DefaultIfEmpty()
.GetAwaiter()
.GetResult());
}
[OneTimeTearDown]
public static void TearDown()
{
s_tickets.OnCompleted();
}
private static IObservable<Unit> PollSchedulesNow()
{
// Do something that eventually unblocks all the test cases
}
[TestCaseSource(nameof(ProvideNamespaces)), Parallelizable(ParallelScope.Children)]
public void ScheduleJob(NamespaceConnectionInfo nci)
{
// Do something
s_tickets.OnNext(Unit.Default);
// Resume - blocks until the actions of PollSchedulesNow take effect
}
private static IEnumerable<TestCaseData> ProvideNamespaces()
{
return ...
}
}
每个测试用例都会为应该只执行一次的特殊操作排队一张票。节流确保只要票在最多一秒的时间间隔内到达,就不会发生任何事情。但是一旦发生暂停,它就会触发该特殊操作。如果出于某种原因,在暂停之后会有更多的测试用例,那么将再次调用特殊操作——这很好。我只是不希望它同时被 100 个并发测试用例调用 100 次 运行。
这是我在 NUnit 中所能想到的最好的。有没有更好的方法在 xUnit 中实现它?或者也许我首先需要一个不同的框架?
首先:不可以。除非您在测试中自己编写协调代码,否则 NUnit 无法跨测试进行协调。即使那样,您也必须确保 NUnit 一起运行所有这些,如果没有您的帮助,它可能会也可能不会。
但是是的!你可以完成你想要的。您正在尝试使用多个 NUnit 测试对本质上是跨多个线程的单个测试进行建模。不要那样做!编写一个单独的测试,它可以根据需要生成尽可能多的独立线程。等待它们完成,然后验证该操作是否只执行了一次。这里只有一个断言,证明只有一个测试。
您可以针对不同数量的线程和错误条件重复此操作,次数不限。这些变化中的每一个都是一个单一的测试。