How can I hide my stack frames in a TestCase subclass?

Peter Otten __peter__ at web.de
Thu Oct 4 18:41:24 EDT 2012


David Banks wrote:

> I want to add a custom assert method to a TestCase subclass.  I tried to
> copy my implementation from the unittest module so that it would match
> the behaviour of the regular TestCase as closely as possible.  (I would
> prefer to just delegate to self.assertEqual() but this causes even more
> backtrace noise, see below.)  The unittest module seems to automatically
> hide some internal details of its implementation when reporting failed
> assertions.
> 
>   import unittest
> 
>   class MyTestCase(unittest.TestCase):
>       def assertLengthIsOne(self, sequence, msg=None):
>           if len(sequence) != 1:
>               msg = self._formatMessage(msg, "length is not one")
>               raise self.failureException(msg)
> 
>   class TestFoo(MyTestCase):
>       seq = (1, 2, 3, 4, 5)
> 
>       def test_stock_unittest_assertion(self):
>           self.assertEqual(len(self.seq), 1)
> 
>       def test_custom_assertion(self):
>           self.assertLengthIsOne(self.seq)
> 
> 
>   unittest.main()
> 
> The output of this is as such:
> 
>   amoe at vuurvlieg $ python unittest-demo.py
>   FF
>   ======================================================================
>   FAIL: test_custom_assertion (__main__.TestFoo)
>   ----------------------------------------------------------------------
>   Traceback (most recent call last):
>     File "unittest-demo.py", line 16, in test_custom_assertion
>       self.assertLengthIsOne(self.seq)
>     File "unittest-demo.py", line 7, in assertLengthIsOne
>       raise self.failureException(msg)
>   AssertionError: length is not one
> 
>   ======================================================================
>   FAIL: test_stock_unittest_assertion (__main__.TestFoo)
>   ----------------------------------------------------------------------
>   Traceback (most recent call last):
>     File "unittest-demo.py", line 13, in test_stock_unittest_assertion
>       self.assertEqual(len(self.seq), 1)
>   AssertionError: 5 != 1
> 
>   ----------------------------------------------------------------------
>   Ran 2 tests in 0.000s
> 
>   FAILED (failures=2)
> 
> Note that the custom assert method causes a stack trace with two frames,
> one inside the method itself, whereas the stock unittest method only has
> one frame, the relevant line in the user's code.  How can I apply this
> frame-hiding behaviour to my own method?

Move MyTestCase in a separate module and define a global variable 

__unittest = True

$ cat mytestcase.py 
import unittest

__unittest = True

class MyTestCase(unittest.TestCase):
    def assertLengthIsOne(self, sequence, msg=None):
        if len(sequence) != 1:
            msg = self._formatMessage(msg, "length is not one")
            raise self.failureException(msg)

$ cat mytestcase_demo.py 
import unittest
from mytestcase import MyTestCase

class TestFoo(MyTestCase):
    seq = (1, 2, 3, 4, 5)

    def test_stock_unittest_assertion(self):
        self.assertEqual(len(self.seq), 1)

    def test_custom_assertion(self):
        self.assertLengthIsOne(self.seq)

if __name__ == "__main__":
    unittest.main()

$ python mytestcase_demo.py 
FF
======================================================================
FAIL: test_custom_assertion (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "mytestcase_demo.py", line 11, in test_custom_assertion
    self.assertLengthIsOne(self.seq)
AssertionError: length is not one

======================================================================
FAIL: test_stock_unittest_assertion (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "mytestcase_demo.py", line 8, in test_stock_unittest_assertion
    self.assertEqual(len(self.seq), 1)
AssertionError: 5 != 1

----------------------------------------------------------------------
Ran 2 tests in 0.000s

FAILED (failures=2)
$ 





More information about the Python-list mailing list