【问题标题】:How to make each TestCase call a hook after setUp?如何让每个TestCase在setUp之后调用一个钩子?
【发布时间】:2017-04-28 07:04:18
【问题描述】:

在我的项目中,我有一个 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()

我希望运行python -m unittest example 的结果在每次打印“准备 a”或“准备 b”后打印“在设置后挂钩中”,但不修改 TestFeatureA 或 TestFeatureB。这个可以吗?

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

【问题讨论】:

  • 为什么不能在BaseTest.setUp 中调用post_setup_hook?订单很重要?
  • 是的,关键是它必须在TestFeatureA.setUp之后调用,这就是为什么它被称为post_setup_hook而不是sometime_during_setup_hook。
  • Python 标准库很好,但unittest 不是,特别是对于一些严肃的事情,你绝对应该看看pytest
  • 你注意到我说我有 80 个测试班吗?他们中的大多数都有几个测试用例。其中一些测试用例非常复杂。我可以在不重写的情况下切换到 pytest 吗?
  • 是的,AFAIK pytest 支持使用 unittest 编写的测试,并允许您逐步重写测试以使用夹具和其他很棒的东西

标签: python python-3.x unit-testing testing python-unittest


【解决方案1】:

您可以覆盖BaseTest(TestCase)run 方法来调用post_setup_hook after the setUp

只需将run 方法复制粘贴到BaseTest 中,然后在setUp 运行后添加post_setup_hook 调用。

【讨论】:

  • 哇,太丑了!虽然可以,因为我可以将运行覆盖放在单独的类/文件中
【解决方案2】:

在这里使用装饰器怎么样?

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

输出:

在 post_setup_hook BaseTest - 准备环境 酒吧 酒吧 出 post_setup_hook TestFeatureA - 测试 a0 BaseTest - 重置环境

【讨论】:

  • 不起作用; post-setup-hook 在设置之前调用,而不是之后调用
  • 请参考代码和输出中的“in post_setup_hook”和“out post_setup_hook”...装饰器函数允许在装饰函数的代码之前和/或之后执行特定代码。
  • 'in post-setup-hook' 和 'out post-setup-hook' 都应该在 ''preping a' 之后打印(你把它拿出来了,违背了练习的目的)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-08
  • 2014-10-23
  • 2017-08-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-20
  • 1970-01-01
相关资源
最近更新 更多