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

时间:2011-04-14 14:04:19

标签: python multithreading unit-testing

我有一个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 个答案:

答案 0 :(得分:12)

您可以添加超时装饰器。将测试用例的逻辑与超时机制实现分开是很好的。这将使您的代码更易读,更易于维护。

参见http://pypi.python.org/pypi/timeout

答案 1 :(得分:1)

我会添加测试来测试无限循环,因为如果它在测试期间挂起,那么至少你在生产之前就已经发现了这个bug。如果它发生的可能性很小(如你所说),那么我不会担心复杂的测试,但我仍然会测试代码。

答案 2 :(得分:0)

对这种情况进行测试是一个好主意。在测试代​​码时,您可以对其质量更有信心。

至于您为测试函数而创建的主题,这里是two ways to kill a thread in python。由于您位于具有无限循环的函数内部,因此您必须使用第二种方法来摆脱循环。

答案 3 :(得分:0)

实际上你不必抓住它。只要它在您的测试中,您一定会注意到它是否出错。

答案 4 :(得分:0)

你无法测试这个。如果另一个线程只是“慢”或更糟“活锁”(即等待共享资源)怎么办?你所做的任何假设都可能与现实相悖。

你不能耸耸肩说:“它总是习惯在1.5秒内终止,但现在似乎要花一点时间。我会尝试2秒钟,看看它是否通过了。”那是不可接受的。

您必须始终证明所有循环的终止。所有循环。

任何不足只是一种设计,它是如此糟糕,以至于它永远不会看到光明。

如果你无法阻止和无限循环,你就没有完成设计。

这不是可以测试的东西。

答案 5 :(得分:0)

也许在你的情况下你可以解决它,因为接受的答案说。对你有益。 然而,当你无法统治“永远挂起”的情况时,有些情况(对于集成和冒烟测试,而不是单元测试)。对于这些情况,我喜欢this timeout解决方案。