这在一些测试过程中出现了。我试图在 MRE 中重现该问题以隔离问题但没有成功。
我有一个这样的测试(简化了,但是这个简化的版本也出现了同样的问题):
def test_if_index_already_exists_should_be_deleted(request, qtbot):
response = requests.delete(f'http://localhost:9200/some_index')
...添加这两行并运行 pytest 会导致一系列意外的失败和错误。我正在使用 pytest-random-order,所以它们会有所不同。错误是可怕的
RuntimeError: QTextEdit 类型的包装 C/C++ 对象已被删除
...但是如果我注释掉该requests.delete
行,则没有任何反应:所有测试都通过多次随机顺序运行。
索引是否存在应该不是问题(或者实际上 Elasticsearch 是否正在运行)。我有点困惑。
AQTextEdit
存在于我的 GUI 中,并且使用信号来更新它。来自 pytest 的跟踪信息如下所示:
File "/media/mike/software projects/EclipseWorkspace/doc_indexer/src/core/indexing_task_class.py", line 72, in set_extra_text
self.extra_info_text_edit.setText(msg)
RuntimeError: wrapped C/C++ object of type QTextEdit has been deleted
这表明当这些测试失败时会触发更新此 GUI 元素的信号。作为回应,我删除了应用程序和测试代码中的信号和所有对它的引用。在此之后,测试都通过了。
为什么调用命令requests.delete
会导致看似虚假的信号触发(显然在拆卸期间)?pytest-qt 是否requests
可能在其内部使用?
PS删除qtbot
上面的夹具并不能解决问题。
编辑
如果我放入traceback.print_stack()
被解雇的插槽,我会得到:
...
File "/media/apps/Python/virtual_envs/doc_indexer/lib/python3.10/site-packages/pytestqt/plugin.py", line 142, in pytest_runtest_setup
_process_events()
File "/media/apps/Python/virtual_envs/doc_indexer/lib/python3.10/site-packages/pytestqt/plugin.py", line 182, in _process_events
app.processEvents()
File "/media/mike/software projects/EclipseWorkspace/doc_indexer/src/core/indexing_task_class.py", line 71, in set_extra_text
traceback.print_stack()
Exceptions caught in Qt event loop:
________________________________________________________________________________
Traceback (most recent call last):
File "/media/mike/software projects/EclipseWorkspace/doc_indexer/src/core/indexing_task_class.py", line 72, in set_extra_text
self.extra_info_text_edit.setText(msg)
RuntimeError: wrapped C/C++ object of type QTextEdit has been deleted
从上面可以看出,触发信号的东西是pytestqt内部的东西:
... /site-packages/pytestqt/plugin.py", line 182, in _process_events
该方法如下所示:
def _process_events():
"""Calls app.processEvents() while taking care of capturing exceptions
or not based on the given item's configuration.
"""
app = qt_api.QtWidgets.QApplication.instance()
if app is not None:
app.processEvents()