[TIP] [SOLUTION] Asserting behaviour of exception tracebacks
Ben Finney
bignose+hates-spam at benfinney.id.au
Thu Jan 31 22:35:36 PST 2008
Ben Finney <bignose+hates-spam at benfinney.id.au> writes:
> Michael Foord <fuzzyman at voidspace.org.uk> writes:
> > Well - if you find a *use-case* for the traceback object - then
> > you can test against that use case.
>
> This is the right way to think about the problem, thanks. I'll have
> to consider exactly what it is I want to assert about the behaviour,
> in terms of how the code is used.
Here's the solution I came up with. Likely others would have arrived
at something different to some degree.
The relevant unit test looks similar to this::
import sys
import minimock
from custom_test_framework import TestCase
import module_under_test
class Test_Foo(TestCase):
""" Test cases for the Foo class """
def tearDown(self):
""" Tear down test fixtures """
minimock.restore()
# ...
def test_frobnicate_raises_traceback_to_original_failure(self):
""" frobnicate() should raise traceback leading to the failure """
test_error = StandardError("Uh-oh!")
mock_inner_func = Mock(raises=test_error)
minimock.mock("module_under_test.something_called_by_frobnicate",
mock_obj=mock_inner_func)
try:
module_under_test.frobnicate()
except module_under_test.ModuleSpecificError:
exc_type, exc, exc_traceback = sys.exc_info()
else:
raise self.failureException("Failed to raise ModuleSpecificError")
self.failUnlessFunctionInTraceback(
exc_traceback, mock_inner_func.__call__)
The 'failUnlessFunctionInTraceback' was implemented in-line in the
test case, until I needed it elsewhere and decided to refactor. Then,
the 'custom_test_framework.TestCase' class grew a helper function::
import unittest
class TestCase(unittest.TestCase):
# ...
def failUnlessFunctionInTraceback(self, traceback, function):
""" Fail if the function 'function' is not in 'traceback' """
func_in_traceback = False
expect_code = function.func_code
current_traceback = traceback
while current_traceback is not None:
if expect_code is current_traceback.tb_frame.f_code:
func_in_traceback = True
break
current_traceback = current_traceback.tb_next
if not func_in_traceback:
msg = ("Traceback did not lead to original function"
" %(function)s"
) % vars()
raise self.failureException(msg)
assertFunctionInTraceback = failUnlessFunctionInTraceback
Thanks to those who led me in the right direction.
--
\ "An idea isn't responsible for the people who believe in it." |
`\ —Donald Robert Perry Marquis |
_o__) |
Ben Finney
More information about the testing-in-python
mailing list