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

Ary*_*rog 5 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")
Run Code Online (Sandbox Code Playgroud)

我看到的唯一问题是,如果测试失败,我会遇到这个额外的线程,可能会消耗cpu和内存资源,而其余的测试都会被执行.另一方面,我已经修复了代码,回归的可能性非常小,所以我不知道是否包括测试是否重要.

Mic*_*jer 12

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

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

  • @ S.Lott:最终用户并不关心你的程序挂断的原因 - 它应该尽可能优雅地处理所有情况,包括那些资源不足的情况.例如,具有GUI的应用程序接管一秒钟以向用户动作提供反馈是完全不可接受的.您无需设置超时,该超时可以接近函数返回的时间.如果一个函数通常需要0.01秒才能返回,如果函数可以花费那么长时间并被认为是可接受的,那么可以将它设置为10秒. (4认同)

S.L*_*ott -1

你不可能对此进行测试。如果另一个线程只是“慢”或更糟糕的“活锁”(即等待共享资源)怎么办?您所做的任何假设都可能与现实相冲突。

你不能耸耸肩说:“以前总是在 1.5 秒内终止,但现在似乎需要更长的时间。我会尝试 2 秒,看看是否通过。” 这是不可接受的。

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

任何不足之处都只是一个糟糕的设计,永远不会出现。

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

这不是一个可以测试的东西。

  • 并非所有问题都有封闭的解决方案。在这种情况下确定输入的完整约束集并不是一个现实的方法。我的意思是简单地使用循环计数器来停止计算,一旦它走得太远。但要知道多远才算太远并不总是那么简单。 (3认同)