如何测试阻塞功能
本文关键字:功能 测试 何测试 | 更新日期: 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 中:
- 调用阻塞函数
- 一秒钟或更多一点,消耗 100% CPU
- 让线程返回
在线程 b 中:
- 使用操作系统 API 查找线程 a 的运行状态。 验证它当前是否处于睡眠状态。
- 触发使线程从阻塞函数返回的事件
- 使用操作系统 API 查找线程 b 的运行状态,验证它当前是否正在运行
- 与线程 a 同步