[Tutor] unittest for: Raises an exception
Ben Finney
ben+python at benfinney.id.au
Wed Feb 18 21:40:55 CET 2015
Sydney Shall <s.shall at virginmedia.com> writes:
> My test code is the following:
>
> def test_func_getSurplusLabourTime_Exc(self):
>
> self.assertRaises(ValueError,self.cwp.getSurplusLabourTime(self.cwp.ww,self.cwp.uvc))
>
> [This last line should indented, but it refuses to do so!]
What is “it” which refuses to indent your text? You might need to use a
better message composition tool.
If you're typing into a Web application, please see the discussion
happening in this forum about appropriate email clients for posting
program code.
So I'll reformat that code for readability::
def test_func_getSurplusLabourTime_Exc(self):
self.assertRaises(
ValueError,
self.cwp.getSurplusLabourTime(self.cwp.ww, self.cwp.uvc))
> The traceback is as follows:
>
> ======================================================================
> ERROR: test_func_getSurplusLabourTime_Exc (__main__.Testcwp)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
[…]
> "/Applications/Canopy.app/appdata/canopy-1.5.1.2730.macosx-x86_64/Canopy.app/Contents/lib/python2.7/unittest/case.py", line 475, in assertRaises
> callableObj(*args, **kwargs)
> TypeError: 'float' object is not callable
The error message is correct: the ‘assertRaises’ method expects a
callable object in the second parameter, but you've supplied an object
which is not callable (a float).
Have a closer look at the documentation for ‘TestCase.assertRaises’::
assertRaises(exception, callable, *args, **kwds)
Test that an exception is raised when callable is called with any
positional or keyword arguments that are also passed to assertRaises().
<URL:https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises>
It's unfortunate the documentation doesn't give an example. But note
that clause “when `callable` is called with any […] arguments that *are
also passed to assertRaises*”.
So you don't call the function yourself; if you do, you get back its
return value (in your case, a float object) and *that's* your argument
to ‘assertRaises’ — not the function you're trying to test!
Instead of calling the function and getting its return value, you pass
*the function itself* to ‘assertRaises’, along with any arguments you
want *the test method* to call it with.
This indirection is a little confusing, and again I'm unhappy the
documentation doesn't show an example. Here's one::
def test_func_getSurplusLabourTime_Exc(self):
self.assertRaises(
ValueError,
self.cwp.getSurplusLabourTime,
self.cwp.ww, self.cwp.uvc)
What the documentation does show as an example, though, is a new-ish
feature that might suit you better.
You can now make your test code more comprehensible by instead using the
‘assertRaises’ method as a context manager, and then you just call your
function normally. Like this::
def test_func_getSurplusLabourTime_Exc(self):
with self.assertRaises(ValueError):
self.cwp.getSurplusLabourTime(self.cwp.ww, self.cwp.uvc)
Context managers are a very helpful feature that can make code more
elegant and readable. They might seem a little magic for now if you
haven't learned about them yet, but this is a good demonstration of
the improvement they can make.
--
\ “… one of the main causes of the fall of the Roman Empire was |
`\ that, lacking zero, they had no way to indicate successful |
_o__) termination of their C programs.” —Robert Firth |
Ben Finney
More information about the Tutor
mailing list