我有一个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
结束时关闭。有没有办法像这样处理上下文管理器的实例化,还是我必须在每个测试夹具中重复它?
答案 0 :(得分:2)
根据the documentation对于tearDown:
即使测试方法引发异常
,也会调用此方法
因此,您只需在setUp
中打开套接字,然后在tearDown
中将其关闭即可。即使您的测试用例引发异常,套接字仍将关闭。
答案 1 :(得分:1)
这是一个非常有趣的问题。正如BrenBarn指出的那样,单元测试框架并不支持你想做的事情,但在我看来,没有特别的理由让你无法适应它。 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()