如何让每个TestCase在setUp后都调用一个hook?

How to make each TestCase call a hook after setUp?

在我的项目中,我有一个 TestCase 的子类(称之为 BaseTest),它会做一些准备然后重置测试环境,以及大量实际的测试用例子类(大约 80 个),每个子类都有自己的独特的设置方法。

我希望每个单独的测试用例子类在它们的 setUp 方法结束时调用一个特定的挂钩。我想在不更改每一种方法的情况下执行此操作。

基本上,情况大致类似于这个示例文件:

import unittest


class BaseTest(unittest.TestCase):
    def setUp(self):
        super().setUp()
        print('prepping env')

    def tearDown(self):
        super().tearDown()
        print('resetting env')

    def post_setup_hook(self):
        print('in post_setup_hook')


class TestFeatureA(BaseTest):
    def setUp(self):
        super().setUp()
        print('prepping a')

    def tearDown(self):
        super().tearDown()

    def test_0(self):
        print('testing a0')

    def test_1(self):
        print('testing a1')


class TestFeatureB(BaseTest):
    def setUp(self):
        super().setUp()
        print('prepping b')

    def tearDown(self):
        super().tearDown()

    def test_0(self):
        print('testing b0')

    def test_1(self):
        print('testing b1')


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

我希望 运行ning python -m unittest example 的结果在每次打印 'prepping a' 或 'prepping b' 后打印 'in post setup hook',但不修改 TestFeatureA或 TestFeatureB。这能做到吗?

请注意,我使用的是 python 3.6。我认为这不会 运行 in python 2.x.

您可以覆盖 run method of BaseTest(TestCase) to call post_setup_hook after the setUp

只需将 run 方法复制粘贴到 BaseTest 并在 setUp 是 运行 之后添加 post_setup_hook 调用。

这里使用装饰器怎么样?

def post_setup(f):
    def wrapper(*args):
        print('in post_setup_hook')
        f(*args)  # execute BaseTest setUp
        print(args[0].FOO)  # Access BasteTest class attribute
        print(args[0].foo)  # Access BasteTest object foo attribute
        print('out post_setup_hook')
    return wrapper


class BaseTest(unittest.TestCase):
    FOO = 'BAR'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.foo = 'bar'

    @post_setup
    def setUp(self):
        super().setUp()
        print('BaseTest - prepping env')

    def tearDown(self):
        super().tearDown()
        print('BaseTest - resetting env')


class TestFeatureA(BaseTest):
    def test_0(self):
        print('TestFeatureA - testing a0')


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

输出:

in post_setup_hook
BaseTest - prepping env
BAR
bar
out post_setup_hook
TestFeatureA - testing a0
BaseTest - resetting env