代码之家  ›  专栏  ›  技术社区  ›  simonzack

测试方法各有不同的设置/拆卸

  •  1
  • simonzack  · 技术社区  · 10 年前

    我正在测试一个类,有很多测试方法。但是,每个方法都有一个唯一的上下文。然后我编写代码如下:

    class TestSomeClass(unittest.TestCase):
        def test_a():
            with a_context() as c:
                pass
    
        def test_b():
            with b_context() as c:
                pass
    
        def test_c():
            with c_context() as c:
                pass
    

    然而,上下文管理器与测试用例无关,并生成临时文件。为了在测试失败时不污染文件系统,我希望在设置/拆卸场景中使用每个上下文管理器。

    我看过鼻子 with_setup ,但文档表示这只适用于函数,而不是方法。另一种方法是将测试方法移动到单独的类中,每个类都有一个设置/拆卸功能。有什么好方法可以做到这一点?

    1 回复  |  直到 10 年前
        1
  •  1
  •   John Hazen    10 年前

    首先,我不确定为什么你所拥有的不起作用。我写了一些测试代码,它显示 出口 代码总是在unittest.main()执行环境下被调用。(注意,我没有测试鼻子,所以也许这就是我无法复制您的失败的原因。)也许您的上下文管理器坏了?

    这是我的测试:

    import unittest
    import contextlib
    import sys
    
    @contextlib.contextmanager
    def context_mgr():
        print "setting up context"
        try:
            yield
        finally:
            print "tearing down context"
    
    class TestSomeClass(unittest.TestCase):
        def test_normal(self):
            with context_mgr() as c:
                print "normal task"
    
        def test_raise(self):
            with context_mgr() as c:
                print "raise task"
                raise RuntimeError
    
        def test_exit(self):
            with context_mgr() as c:
                print "exit task"
                sys.exit(1)
    
    if __name__ == '__main__':
        unittest.main()
    

    通过使用 $ python test_test.py 我懂了 tearing down context 对于所有3个测试。

    无论如何,为了回答您的问题,如果您希望为每个测试单独设置和拆卸,那么您需要将每个测试放在自己的类中。您可以设置一个父类来为您完成大部分工作,这样就不会有太多额外的样板:

    class TestClassParent(unittest.TestCase):
        context_guard = context_mgr()
        def setUp(self):
            #do common setup tasks here
            self.c = self.context_guard.__enter__()
        def tearDown(self):
            #do common teardown tasks here
            self.context_guard.__exit__(None,None,None)
    
    class TestA(TestClassParent):
        context_guard = context_mgr('A')
        def test_normal(self):
            print "task A"
    
    class TestB(TestClassParent):
        context_guard = context_mgr('B')
        def test_normal(self):
            print "task B"
    

    这将产生以下输出:

    $ python test_test.py 
    setting up context: A
    task A
    tearing down context: A
    .setting up context: B
    task B
    tearing down context: B
    .
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK