【问题标题】:python 'with' statement and its use in a classpython 'with' 语句及其在类中的使用
【发布时间】:2012-12-14 08:11:38
【问题描述】:

我有一个使用套接字进行测试的 TestCase。即使在出现错误的情况下,您也应该始终关闭套接字,因此我创建了一个抽象套接字的上下文管理器类。

测试夹具如下所示,其中MyClassToTest 是要测试的实际类,它在内部使用套接字设备。

with SocketContextManager() as device:
    foo = MyClassToTest(device)
    # make tests with foo

我想避免这两行在每个测试夹具中重复,但始终放在setUp 中。但是我该怎么做呢?以下代码

def setUp(self):
    with SocketContextManager() as device:
        self.foo = MyClassToTest(device)

不起作用,因为设备将在setUp 结束时关闭。有没有办法像这样处理上下文管理器的实例化,还是我必须在每个测试夹具中重复它?

【问题讨论】:

    标签: python unit-testing with-statement


    【解决方案1】:

    根据the documentation进行拆解:

    即使测试方法引发异常也会调用此方法

    所以你可以在setUp 中打开套接字,然后在tearDown 中关闭它。即使您的测试用例引发异常,套接字仍然会关闭。

    【讨论】:

    • 当然可以,但是您必须记住关闭tearDown 中的套接字。 with 语句的目的是自动发生。
    • @Alex:是的,但你必须在测试情况下放弃这种便利(或者接受在每个测试中编写with 语句)。设置和拆除测试可能需要手动执行一些在其他条件下会自动完成的操作,因为您正在创建一个“气泡”以供测试运行并让测试框架捕获其错误。跨度>
    • 好的,我想这回答了我的问题。谢谢。
    【解决方案2】:

    这是一个非常有趣的问题。正如 BrenBarn 指出的那样,unittest 框架不支持做你想做的事,但在我看来,没有什么特别的原因不能让你适应它。 setUp/tearDown 配对是其他没有生成器的语言的遗留物。

    下面的代码定义了一个新的 'ContextTest' 类,它将 setUp 和 tearDown 方法合并到一个生成器中,该生成器同时构建和销毁测试的上下文。您可以将 with 语句与任何其他样板文件一起放入 context() 方法中。

    #!/usr/bin/python3.3
    import unittest
    
    class ContextTest(unittest.TestCase):
        """A unit test where setUp/tearDown are amalgamated into a
        single generator"""
        def context(self):
            """Put both setUp and tearDown code in this generator method
            with a single `yield` between"""
            yield
    
        def setUp(self):
            self.__context = self.context()
            next(self.__context)
        def tearDown(self):
            for _ in self.__context:
                raise RuntimeError("context method should only yield once")
    
    from contextlib import closing
    from urllib.request import urlopen
    
    class MyTest(ContextTest):
        def context(self):
            with closing(urlopen('http://www.python.org')) as self.page:
                yield
    
        def testFoo(self):
            self.assertIsNotNone(self.page)
    
    if __name__=='__main__':
        unittest.main()
    

    【讨论】:

      猜你喜欢
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-01
      • 2010-12-31
      相关资源
      最近更新 更多