I'm writing a module, and I'm using unittest
to write unit tests alongside the actual code.
Sometimes (almost nondeterministically, it seems), a function like the following that doesn't explicity return a value, asserted with self.assertRaises(mymodule.MyEmptyException, myfunc())
(where self
refers to the subclass of unittest.TestCase
) raises a mysterious DeprecationWarning
.
Here's an example of such a function:
def insertn(self, items, lidex):
"""( z y x -- z b y x )
add a list of items to the stack at the given index"""
iter(items)
for idx, obj in enumerate(items):
self.insert(lidex, obj)
lidex += 1
Its corresponding unit test:
def test_insertn_fail(self):
"""expect failure during multiple insertion"""
self.assertRaises(mouse16.BadInternalCallException,
stack.insertn([8, 4, 12], 16))
with self.assertRaises(TypeError):
stack.insertn(8, 16)
gives (for example):
./mousetesting.py:103: DeprecationWarning: callable is None
I thought making the function have a non-None
return value might fix the problem (i.e. return 0
) but then I get (for example):
======================================================================
ERROR: test_insertn_fail (__main__.CoreStack)
expect failure during multiple insertion
----------------------------------------------------------------------
Traceback (most recent call last):
File "./mousetesting.py", line 103, in test_insertn_fail
stack.insertn([8, 4, 12], 16))
File "/usr/lib/python3.5/unittest/case.py", line 727, in assertRaises
return context.handle('assertRaises', args, kwargs)
File "/usr/lib/python3.5/unittest/case.py", line 176, in handle
callable_obj(*args, **kwargs)
TypeError: 'int' object is not callable
----------------------------------------------------------------------
So the unittest
module is trying to call the return value of a function... but doesn't complain that None
also isn't callable
?
I don't really know enough about the internals of Python to understand what's going on here. I'd like to avoid having my tests break in a way I don't know how to fix in the future because of a DeprecationWarning
I ignored.
Must my functions (but only some of them, and not all the time?) return a (memory-wasting) closure or meaningless lambda expression to avoid this? Or should I craft a thing that detects whether a test is in progress and only then return a no-op lambda? That seems like a lot of work just to avoid a DeprecationWarning
.
You are using self.assertRaises()
incorrectly. It has to call the test function for you, in order to catch the exception:
self.assertRaises(mouse16.BadInternalCallException,
stack.insertn, [8, 4, 12], 16)
You were passing in the result of the stack.insertn()
call (which didn't raise an exception, but returned either None
or an integer instead), and that return value is not callable. An older version of the method accepted None
for that argument as well, which is no longer supported, hence the deprecation warning when None
is passed in versus an integer.
The better way is to use self.assertRaises()
as a context manager:
with self.assertRaises(mouse16.BadInternalCallException):
stack.insertn([8, 4, 12], 16)
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