[英]Where to catch a KeyboardInterrupt in unittests?
我正在使用Appium服务器在移动设备上进行UI测试。 我希望能够在开发测试时取消测试过程。 当前,当我CTRL-C
退出进程(python unittest)时,我必须重新启动appium服务器,因为会话未正确关闭(这可以在测试的tearDown()
方法中完成,但是(因为我按了CTRL-C,所以将不会执行该操作。)相反,我想每次通过KeyboardInterrupt
取消测试时都将tearDown()
触发。
现在的问题是:在哪里放置try-catch块来实现这一目标? 有没有在Python单元测试中处理此问题的最佳实践? 在KeyboardInterrupt
触发后,我需要访问一个类变量( self.driver.quit()
)。 该类变量位于unittest.TestSuite
,该类位于unittest.TextTestRunner
正在运行的内部。
try:
self.test_something()
except KeyboadInterrupt:
self.driver.quit()
我已经研究了unittest.TestResult
及其stop()
方法,但是还没有找到正确解释其用法的实际示例。
您可以更改有关SIGINT的Python的默认行为,以适合您的需求:
import signal
def my_ctrlc_handler(signal, frame):
driver_class.quit()
raise KeyboardInterrupt
signal.signal(signal.SIGINT, my_ctrlc_handler)
我制作了一个自定义的TestCase,以确保如果使用Ctrl-C
取消了测试,则都可以运行tearDown()
, tearDownClass()
和tearDownModule()
。 如果setUp()
引发任何异常,它还可以确保tearDown()
等全部运行。
class SafeTestCase(TestCase):
"""
SafeTestCase makes sure that tearDown / cleanup methods are always run when
They should be.
"""
def run(self, result=None):
test_method = getattr(self, self._testMethodName)
wrapped_test = self._cleanup_wrapper(test_method, KeyboardInterrupt)
setattr(self, self._testMethodName, wrapped_test)
self.setUp = self._cleanup_wrapper(self.setUp, BaseException)
return super().run(result)
def _cleanup_wrapper(self, method, exception):
def wrapped(*args, **kwargs):
try:
return method(*args, **kwargs)
except exception:
self.tearDown()
self.doCleanups()
raise
return wrapped
要使用此功能,只需确保您的TestCase
继承自SafeTestCase
而不是unittest.TestCase
。
class MyTestCase(SafeTestCase):
@classmethod
def setUpClass(cls) -> None:
print('setUpClass entered')
print('setUpClass exited')
@classmethod
def tearDownClass(cls) -> None:
print('tearDownClass entered')
print('tearDownClass exited')
def setUp(self) -> None:
print('setUp entered')
# raise ValueError() # tearDown() and tearDownClass() will still run
print('setUp exited')
def tearDown(self):
print('tearDown entered')
foo = 1
print('tearDown exited')
def test_test(self):
print('test entered')
raise KeyboardInterrupt() # tearDown() and tearDownClass() will still run
print('test exited')
将打印类似
setUpClass entered
setUpClass exited
setUp entered
setUp exited
test entered
tearDown entered
tearDown exited
tearDownClass entered
tearDownClass exited
并切换注释哪个异常将打印类似
setUpClass entered
setUpClass exited
setUp entered
tearDown entered
tearDown exited
tearDownClass entered
tearDownClass exited
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.