如何测试阻塞功能

本文关键字:功能 测试 何测试 | 更新日期: 2023-09-27 18:33:49

如何测试函数在特定情况下是否无限期阻塞?

[Test]
public void BlockingTest()
{
    blockingFunction();    // this function halts execution indefinitely
    Assert.Fail("Execution not halted.");
}

假设blockingFunction()是一个等待某事发生的函数,它应该阻止执行,直到特定事件发生,并且测试假设此事件永远不会发生。

编辑:我实际上正在寻找的是一个优雅的解决方案,可能不必在报告成功之前明确等待硬编码时间。

发布我目前的情况以供参考:

[Test]
public void BlockTest() {
    BytesStream bs = new BytesStream();
    bs.Write(new byte[] { 1, 2 }, 0, 2);
    var buff2 = new byte[2];
    bs.Read(buff2, 0, 2);
    bool dataWritten = false;
    new Thread(() => {
        for(int i=0; i<100; i++)
            Thread.Sleep(0); // ensure the parent thread execute next line
        dataWritten = true;
        bs.Write(new byte[] { 3, 4 }, 0, 2);
    }).Start();
    Assert.AreNotEqual(0, bs.Read(buff2, 0, 2), "#1");
    if(!dataWritten)
        Assert.Fail("#2");
    Assert.AreEqual(new byte[] { 3, 4 }, buff2, "#3");
}

如何测试阻塞功能

如何测试函数在特定情况下是否无限期阻塞?

这称为停止问题。 事实证明,这是不可能解决的。

也许让你的函数由 Threadpool 对象执行,看看它是否在指定的时间跨度内返回,如下所示:

    [Test]
    public void BlockingTest()
    {
        AutoResetEvent ev = new AutoResetEvent(false);
        BlockingFunctionHelper(ev);    
        // specify time out in ms, thus here: wait 1 s
        Assert.IsTrue(ev.WaitOne(1000), "Execution not halted.");
        ev.Dispose();
    }
    private void BlockingFunctionHelper(AutoResetEvent ev)
    {
        ThreadPool.QueueUserWorkItem((e) =>
            {
                BlockingFunction(); // this function halts execution indefinitely
                ((AutoResetEvent) e).Set();
            }, ev);
    }

你已经回答了你的问题。您的测试方法将无限期地等待,如果blockingFunction更早返回,则失败。只要让它运行并在失败时修复代码。


现在回答这里真正的问题:你真正想测试什么?

实际上要求blockingFunction阻止执行吗?我认为,如果它会消耗队列项目而不阻止执行,那就更好了——但你的虚构测试会失败。

换句话说:我认为你的blockingFunction块并不重要,你应该测试业务逻辑而不是技术行为,除非有实际用例。

就像如果您的使用者在 t 秒内没有生成任何项目而终止,那么您可以等待 t 秒,如果它更早返回,则失败。

如果您想测试您的使用者在空闲一段时间后是否"醒来",您可以等待 n 秒,然后生成一个项目。失败时,使用者会更早地执行某些操作,如果在生成项目后它没有消耗,则失败。

只有你能真正回答这个问题,因为我们不知道你真正想在这里测试什么。我希望我设法以一种有用的方式阐明这一点。

如果你

有一个应该唤醒调用的触发器,一个想法:

在线程 a 中:

  1. 调用阻塞函数
  2. 一秒钟或更多一点,消耗 100% CPU
  3. 让线程返回

在线程 b 中:

  1. 使用操作系统 API 查找线程 a 的运行状态。 验证它当前是否处于睡眠状态。
  2. 触发使线程从阻塞函数返回的事件
  3. 使用操作系统 API 查找线程 b 的运行状态,验证它当前是否正在运行
  4. 与线程 a 同步