【问题标题】:How to synchronize concurrently running tests in xUnit?如何在 xUnit 中同步同时运行的测试?
【发布时间】:2018-05-25 16:57:46
【问题描述】:

我可能需要并行启动数十个测试用例,但有一个问题 - 所有这些都达到一个点,即单个操作只应执行一次,而不管有多少测试用例正在运行。此操作结束后,测试可以恢复并继续独立运行。

现在我在 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 中实现它?或者,也许我首先需要一个不同的框架?

【问题讨论】:

    标签: c# testing nunit xunit


    【解决方案1】:

    首先:不。在 NUnit 中没有办法跨测试进行协调,除非您在测试中自己编写协调代码。即使这样,您也必须确保 NUnit 一起运行所有这些,而这在没有您的帮助的情况下可能会也可能不会。

    但是是的!你可以完成你想要的。您正在尝试使用多个 NUnit 测试对本质上是跨多个线程的单个测试进行建模。不要那样做!编写一个测试,根据需要生成尽可能多的单独线程。等待他们完成,然后验证该操作只执行了一次。这里只有一个断言,证明只有一个测试。

    您可以针对不同数量的线程和错误条件重复此操作,次数不限。这些变体中的每一个都是一个测试。

    【讨论】:

    • 我需要有多个测试用例。该测试是一个部署冒烟测试——它断言调度是为客户端正确轮询的。从用户的角度来看,它们是独立的测试——每个客户端一个。虽然有实现细节 - 调度由多租户后台服务轮询,并且此轮询由服务于多租户 pod 的单个数据库中的记录触发。我可以为每个客户创建一个记录,它会起作用,但它会强调服务,我想避免它。
    • 如果你必须这样做,那么将所有测试放在一个夹具中,不要进行其他测试。在 OneTimeSetUp 中初始化并在 OneTimeTearDown 中进行检查。
    • 但是特殊动作要么在所有测试开始时,要么在所有测试结束时。就我而言,它位于中间。测试到达一个集合点,等待特殊操作完成,然后继续运行直到完成。
    • 特殊操作在您的生产代码中,而不是在测试中。假设您的测试保存了该信息,则可以在您的 TestFixtureTearDown 中检查特殊操作是否在适当的时刻仅执行一次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-09
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 2015-01-31
    相关资源
    最近更新 更多