我是使用Appium服务器在移动设备上进行UI测试。我希望能够在开发测试时取消测试过程。目前,当我CTRL-C
退出进程(python unittest)时,我必须重新启动appium服务器,因为会话没有正确关闭(这可以在tearDown()
方法中完成测试,但是因为我按CTRL-C,这将不会被执行。)相反,我希望每次测试被tearDown()
取消时都会KeyboardInterrupt
点火。
现在是我的问题:我在哪里放置try-catch块来实现这个目标?在Python单元测试中是否有处理此问题的最佳实践?我需要在self.driver.quit()
触发后立即访问类变量(KeyboardInterrupt
)。类变量位于放入unittest.TestSuite
正在运行的unittest.TextTestRunner
的类中。
try:
self.test_something()
except KeyboadInterrupt:
self.driver.quit()
我看了unittest.TestResult
及其stop()
方法,但没有找到解释其用法的实际例子。
答案 0 :(得分:2)
您可以根据需要更改Python的默认行为:
import signal
def my_ctrlc_handler(signal, frame):
driver_class.quit()
raise KeyboardInterrupt
signal.signal(signal.SIGINT, my_ctrlc_handler)
答案 1 :(得分:0)
我制作了一个自定义TestCase,以确保如果用tearDown()
取消了测试,则tearDownClass()
,tearDownModule()
和Ctrl-C
都可以运行。如果在tearDown()
中引发了 any 异常,它还可以确保setUp()
等全部运行。
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