QT函数抑制python中的测试失败
Posted
技术标签:
【中文标题】QT函数抑制python中的测试失败【英文标题】:QT function suppressing test failures in python 【发布时间】:2022-01-02 14:59:21 【问题描述】:处理正在测试 python UI 的复杂单元测试,并且 QT 函数似乎正在抑制测试失败。我相信我已经能够创建一个重复该行为的最小文件:
import pytest
from unittest import TestCase
from PySide2.QtCore import QTimer
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):
def inner_test_2():
self.assertEqual(meaningless(),'x')
QTimer.singleShot(1, inner_test_2)
if __name__ == '__main__':
import sys
sys.exit(pytest.main([__file__]))
第一个测试失败了,但第二个测试错误地通过了。在我更复杂的真实世界单元测试中,“inner_test_2”的等效项确实会触发,并且可以在测试日志中看到由此产生的断言错误,但测试不会注册为失败。从我在 QT 文档中可以看出,这可能与多线程有关?如何让失败失败?
【问题讨论】:
您的示例没有运行事件循环,因此行为正确且符合预期。您可能应该使用 pytest-qt 之类的东西。 对不起,如果我在这里分裂头发,但在这种情况下,“预期行为”=“因为使用错误而无法正常工作”或“这是 QTimer 的合法使用,但它不会生产你想要的东西。” ? 好吧,你写了测试用例,所以只有你才能真正回答这个问题。你在测试成功还是失败?如果没有正在运行的事件循环,您究竟希望single-shot timer 做什么?测试用例部分(或有时甚至主要)旨在记录程序员对 API 的理解,而不仅仅是 API 本身。 由于您给出的示例不能代表您的真实代码(您的真实代码执行inner_test_2
,而示例没有)我只能猜测它可能与多线程有关?如果assertEqual(meaningless(),'x')
在不同的线程中运行,则可能会出现问题。
【参考方案1】:
这可能与多线程有关?
是的,没错。失败的测试是通过异常检测的,而不同线程中的异常不会被 unittest 框架捕获,因为它无法将线程与测试相关联。
minimal, reproducible example 将是:
import pytest
from unittest import TestCase
import threading
class TestClass(TestCase):
def test_2(self):
def inner_test_2():
self.assertTrue(False)
myTestThread = threading.Thread(target=inner_test_2)
myTestThread.start()
myTestThread.join()
if __name__ == '__main__':
import sys
sys.exit(pytest.main([__file__]))
请注意,虽然assertTrue(False)
引发异常,但我们没有看到失败的测试。但我们确实看到(除了异常的堆栈跟踪)是来自pytest
的警告:
warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg))
-- Docs: https://docs.pytest.org/en/stable/warnings.html
我如何让失败失败?
您需要从线程中捕获异常并在主线程中引发它们,以便 unittest 框架可以拾取它们并了解哪些测试失败了。如何做到这一点是另一个话题,请参阅Make Python unittest fail on exception from any thread。
【讨论】:
以上是关于QT函数抑制python中的测试失败的主要内容,如果未能解决你的问题,请参考以下文章