I have a python function which if passed bad data gets caught in an infinite loop. I'd like to write a unit test to confirm that it handles bad parameters gracefully. The problem is of course that if it doesn't detect the bad parameters it won't return.
Is it acceptable to use threads to write a test for this type of thing?
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")
The only problem I see with this is that if the test fails I'm stuck with this additional thread, potentially consuming cpu and memory resources, while the remainder of the tests are executed. On the other hand, I've fixed the code and the likelihood of regression here is very slim, so I don't know if it even matters whether I include the test or not.
You can add a timeout decorator. It's good to separate the logic of your testcase from the timeout mechanism implementation. This will make your code more readable and easier to maintain.
See http://pypi.python.org/pypi/timeout .
I would add the test to test for the infinite loop, since if it hangs during the tests then at least you've caught the bug before production. If the chance of it happening is slim (as you say), then i wouldn't worry about a complicated test, but I'd test the code nonetheless.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With