[Tutor] unittesting and nested functions

Kent Johnson kent37 at tds.net
Mon Dec 20 21:29:22 CET 2004


Christian Meesters wrote:
> Hi
> 
> I've written some unittests using the unittest module for my 
> 'DNA-class'. This class can cope with almost every input, but with no 
> 'numbers' whatsoever. Well, one of the tests is:
> 
> class TestFunctions(unittest.TestCase):
>     ...
>     def test__init__(self):
>         """testing whether __init__ will fail if nonsense data are 
> passed for initialization"""
>         self.failUnlessRaises(IOError,DNA('1 ATG'))

This should be
   self.failUnlessRaises(IOError, DNA, '1 ATG')

In your usage, you are calling DNA() and passing the result of the call to failUnlessRaises(). The 
call to DNA raises IOError. This happens *before* the call to failUnlessRaises(), so it is 
interpreted as an error.

In my version, I pass the DNA function itself to failUnlessRaises(), along with the arguments. The 
actual call to DNA() will be wrapped by a try/except block in failUnlessRaises(). The expected error 
is received and the test passes.

BTW, failUnlessRaises() is implemented using the extended call syntax that came up recently in 
another thread, and it is a good example of why this syntax is useful. It's also interesting that 
the except: statement uses the class that was passed in; I had no idea an except was dynamic in this 
way.

Here is the source for failUnlessRaises():

     def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
         try:
             callableObj(*args, **kwargs)
         except excClass:
             return
         else:
             if hasattr(excClass,'__name__'): excName = excClass.__name__
             else: excName = str(excClass)
             raise self.failureException, "%s not raised" % excName

Kent

>        
> Now, if 'nonsense data' are passed to the testing function I expect an 
> IOError to be raised. And this happens indeed. Still this test fails 
> (actually it doesn't: only an error occurs), but why?
> 
> This is the Traceback I get:
> 
> ======================================================================
> ERROR: testing whether __init__ will fail if nonsense data are passed 
> for initialization
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>   File "src/DNA.py", line 862, in test__init__
>     self.failUnlessRaises(IOError,DNA('1 ATG'))
>   File "src/DNA.py", line 100, in __init__
>     raise IOError
> IOError
> 
> ----------------------------------------------------------------------
> Ran 35 tests in 0.485s
> 
> FAILED (errors=1)
> 
> According to the documentation everything should be just fine:
> ----------
> 5.3.5 TestCase Objects
> ...
> failUnlessRaises(exception, callable, ...)
>  Test that an exception is raised when callable is called with  any 
> positional or keyword arguments that are also passed to assertRaises(). 
> The test passes if exception is  raised, is an error if another 
> exception is raised, or fails if no  exception is raised. To catch any 
> of a group of exceptions, a tuple  containing the exception classes may 
> be passed as exception.
> ----------
> 
> So, any idea, where my mistake is?
> 
> (Before I get comments about having the unittest in the same file as the 
> file to be tested: I'll change that! ;-) )
> 
> Thanks a lot in advance.
> Cheers
> Christian
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 


More information about the Tutor mailing list