如何在TestCase子类中隐藏我的堆栈帧?

时间:2012-09-25 12:31:42

标签: python unit-testing testing subclass stack-trace

我想将自定义断言方法添加到TestCase子类。我尝试从unittest模块复制我的实现,以便尽可能地匹配常规TestCase的行为。 (我更愿意委托给self.assertEqual(),但这会导致更多的回溯噪音,见下文。)unittest模块在​​报告失败的断言时似乎会自动隐藏其实现的一些内部细节。

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()

这样的输出是这样的:

amoe@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)

请注意,自定义断言方法会导致堆栈跟踪有两个帧,一个在方法本身内,而stock unittest方法只有一个帧,即用户代码中的相关行。如何将此框架隐藏行为应用于我自己的方法?

1 个答案:

答案 0 :(得分:14)

by Peter Otten on comp.lang.python回答了这个问题。

将MyTestCase移动到单独的模块中,并定义全局变量__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)
$