Python UI单元测试中QT函数抑制测试失败,如何让失败被正确识别?
问题根本原因
你的测试用例test_2在调用QTimer.singleShot后就直接返回了,测试框架会认为该用例执行完成且无异常,直接标记为通过。后续定时器触发时,测试用例的异常捕获上下文已经销毁,断言抛出的AssertionError只会输出到日志,无法被测试框架识别为用例失败,和多线程无关,本质是Qt事件循环的异步执行逻辑和测试框架的同步用例判定逻辑不匹配。
解决方案
你需要让测试用例等待Qt事件循环执行完异步回调,同时捕获回调中抛出的异常并在测试主流程中抛出,调整后的代码如下:
import pytest from unittest import TestCase from PySide2.QtCore import QTimer, QEventLoop def meaningless(): return 'fire' class TestClass(TestCase): def test_1(self): def inner_test_1(): self.assertEqual(meaningless(),'x') inner_test_1() def test_2(self): loop = QEventLoop() test_exception = None def inner_test_2(): nonlocal test_exception try: self.assertEqual(meaningless(),'x') except Exception as e: # 捕获回调内的所有异常 test_exception = e finally: # 执行完回调后退出事件循环 loop.quit() QTimer.singleShot(1, inner_test_2) # 启动事件循环等待回调执行,最多等1秒避免死循环 QTimer.singleShot(1000, loop.quit) loop.exec_() # 如果回调内捕获到异常,在主流程抛出,让测试框架识别 if test_exception: raise test_exception if __name__ == '__main__': import sys sys.exit(pytest.main([__file__]))
改动点说明
- 新增
QEventLoop实例阻塞测试用例的主流程,直到异步回调执行完成或者超时 - 用
nonlocal变量存储回调中抛出的异常,在事件循环退出后检查该变量,存在异常则在测试主流程抛出 - 新增超时保护的定时器,避免异步回调未触发导致测试用例永久阻塞
内容的提问来源于stack exchange,提问作者Jed Godsey
相关产品推荐
相关产品推荐

