Python单元测试潜在的无限循环

5 投票
6 回答
5855 浏览
提问于 2025-04-16 15:44

我有一个Python函数,如果传入不好的数据,它会陷入无限循环。我想写一个单元测试,确认这个函数能优雅地处理这些不好的参数。问题是,如果它没有检测到这些不好的参数,就不会返回结果。

用线程来写这样的测试可以吗?

import threading, unittest
import mymodule

class CallSuspectFunctionThread(threading.Thread):
    def __init__(self, func, *args):
        self.func = func
        self.args = args
        super(CallSuspectFunctionThread, self).__init__()
    def run(self):
        self.func(*self.args)

class TestNoInfiniteLoop(unittest.TestCase):
    def test_no_infinite_loop(self):
        myobj = mymodule.MyObject()
        bad_args = (-1,0)
        test_thread = CallSuspectFunctionThread(mybj.func_to_test, *bad_args)
        test_thread.daemon = True
        test_thread.start()
        # fail if func doesn't return after 8 seconds
        for i in range(32):
            test_thread.join(0.25)
            if not test_thread.is_alive():
                return
        self.fail("function doesn't return")

我看到的唯一问题是,如果测试失败了,我就会有一个额外的线程在那儿,可能会消耗CPU和内存资源,而其他测试还在执行。另一方面,我已经修复了代码,这里出现问题的可能性非常小,所以我不知道是否真的有必要包含这个测试。

6 个回答

1

我建议加一个测试来检查是否有无限循环,因为如果在测试过程中程序卡住了,至少你能在正式上线之前发现这个问题。如果发生这种情况的可能性很小(就像你说的那样),那我就不太担心测试写得复杂,但我还是会对代码进行测试。

12

你可以添加一个超时装饰器。把测试用例的逻辑和超时机制分开是个好主意。这样做会让你的代码更容易读懂,也更方便维护。

可以查看这个链接:http://pypi.python.org/pypi/timeout

-1

你根本无法测试这个问题。假设另一个线程只是“慢”,或者更糟糕的是“活锁”(也就是在等待一个共享资源),那么你做出的任何假设都可能与现实不符。

你不能随便说“以前总是1.5秒就结束,但现在似乎要久一点。我试试2秒,看能不能通过。” 这样是不可接受的。

你必须确保所有的循环都能在任何时候结束。所有的循环。

如果做不到这一点,那就是设计得太糟糕,根本不应该被使用。

如果你不能防止出现无限循环,那你的设计就还没完成。

这不是可以通过测试来解决的问题。

撰写回答