Open impact27 opened 4 years ago
Sorry for the late answer! FWIW your code runs fine for me, with the same versions you're running:
============================= test session starts ==============================
platform linux -- Python 3.8.2, pytest-5.3.1, py-1.8.1, pluggy-0.13.1
PyQt5 5.12.3 -- Qt runtime 5.12.8 -- Qt compiled 5.12.8
rootdir: /home/florian/proj/pytest-qt, inifile: setup.cfg
plugins: qt-3.2.2
collected 1 item
test_qtbot.py . [100%]
============================== 1 passed in 1.13s ===============================
I tested it again and still have the problem. Maybe it is OSX specific?
% python3 test_qtbot.py
============================= test session starts ==============================
platform darwin -- Python 3.7.7, pytest-5.3.1, py-1.8.0, pluggy-0.13.1
PyQt5 5.12.3 -- Qt runtime 5.12.6 -- Qt compiled 5.12.6
rootdir: /Users/quentinpeter/Desktop
plugins: mock-1.12.1, lazy-fixture-0.6.2, flaky-3.6.1, ordering-0.6, qt-3.2.2
collected 1 item
test_qtbot.py
Yep, I can reproduce on macOS, even with pytest 5.4.2, pytest-qt 3.3.0 and PyQt5 5.14.2. Using -o faulthandler_timeout=10
confirms that it hangs in qtbot.wait
:
Thread 0x00007fffa5eb8380 (most recent call first):
File "/Users/florian/tmp/.venv/lib/python3.7/site-packages/pytestqt/wait_signal.py", line 51 in wait
File "/Users/florian/tmp/.venv/lib/python3.7/site-packages/pytestqt/qtbot.py", line 448 in wait
File "/Users/florian/tmp/test_qtbot.py", line 32 in test_qtbot
[...]
Works fine on Windows as well FWIW.
Yeah works fine for me too. Not sure how to proceed here I'm afraid, it might be something in your system. 😕
But @The-Compiler replicated the bug on macOS?
on a similar note (apologies if I missed it in the docs), qtbot hangs if itemClicked signals are emitted directly:
My case was a QListWidgetItem, which I triggered manually (leading to hanging), and then fixed with the proper qtbot usage.
list_widget.itemClicked.emit(item)
FIx:
center = list_widget.visualItemRect(item).center()
qtbot.mouseClick(list_widget.viewport(), qc.Qt.LeftButton, pos=center)
(I'm running inside a x86 debian docker container with xvfb on for CI reasons)
Update: It was my mistake, a message_prompt blocked the entire process, and in headless mode it was not obvious.
@nicoddemus should the “question” label be removed as this is a reproduced bug rather than a question? (Reproduced on macOS by @The-Compiler)
Indeed, changed!
However we need a volunteer with access to MacOS to investigate this.
Calling QEventLoop.quit()
inside QApplication.processEvents
has no effect on macOS.
Code to reproduce:
import time
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QEventLoop, QTimer
# from PyQt6.QtWidgets import QApplication
# from PyQt6.QtCore import QEventLoop, QTimer
if __name__ == "__main__":
app = QApplication([])
loop = QEventLoop()
def _wait_process_events():
# While we wait here, _quitloop_by_timeout is triggered
time.sleep(1)
# The timeout event is triggered
QApplication.processEvents()
def _quitloop_by_timeout():
# Ask the loop to quit
loop.quit()
print("Requesting loop to quit")
# Call _wait_process_events in the event loop
timer_1 = QTimer(loop)
timer_1.setSingleShot(True)
timer_1.setInterval(10)
timer_1.timeout.connect(_wait_process_events)
timer_1.start()
# Call _quitloop_by_timeout in the event loop after _wait_process_events
timer_2 = QTimer(loop)
timer_2.setSingleShot(True)
timer_2.setInterval(500)
timer_2.timeout.connect(_quitloop_by_timeout)
timer_2.start()
# Enter eventloop
loop.exec()
print("loop exited")
Executing this code with Python 3.9.12 under macOS 12.3.1 with either
Results in "Requesting loop to quit" being printed and the program freezing.
From the discussion here I understand that this does not affect linux or window
I will send a bug report on the pyqt mailing list
Have you tried with PySide rather than PyQt? If it happens there as well, it's likely a Qt bug.
@impact27 I'm also experiencing this so wanted to share my setup to see if we can find commonalities that may be causing this:
I also get hanging tests using libs:
name : pyside6
version : 6.4.0.1
description : Python bindings for the Qt cross-platform application and UI framework
dependencies
- PySide6-Addons 6.4.0.1
- PySide6-Essentials 6.4.0.1
- shiboken6 6.4.0.1
name : pytest
version : 6.2.5
description : pytest: simple powerful testing with Python
dependencies
- atomicwrites >=1.0
- attrs >=19.2.0
- colorama *
- iniconfig *
- packaging *
- pluggy >=0.12,<2.0
- py >=1.8.2
- toml *
required by
- pytest-qt >=3.0.0
name : pytest-qt
version : 4.2.0
description : pytest support for PyQt and PySide applications
dependencies
- pytest >=3.0.0
on MacOS 13.1 (darwin x86_64 architecture) using python 3.9.13
For my colleagues qtbot is not hanging. We haven't been able to isolate the difference either.
I modified the original test case for my dependencies and reproduced the hanging test:
from PySide6.QtCore import QCoreApplication, QTimer
from PySide6.QtWidgets import QWidget
from time import sleep
import pytest
class MyWidget(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._timer = QTimer(self)
self._timer.setSingleShot(True)
self._timer.setInterval(10)
self._timer.timeout.connect(self._wait_process_events)
self._timer.start()
def _wait_process_events(self):
sleep(1)
QCoreApplication.processEvents()
def test_qtbot(qtbot):
"""
qtbot does the following:
1. start QEventLoop
2. process an event that calls QApplication.processEvents()
3. this processes an event that calls loop.quit()
which doesn't quit the wait loop
"""
widget = MyWidget()
qtbot.addWidget(widget)
widget.show()
qtbot.wait(500)
if __name__ == "__main__":
pytest.main()
If qtbot tries to stop waiting while
QApplication.processEvents()
is being called, the test will hang indefinitely. What happens is that:QEventLoop
QApplication.processEvents()
is processed byQEventLoop
_quit_loop_by_timeout
is processed byQApplication.processEvents()
self._loop.quit()
doesn't quit the loop if it is called fromQApplication.processEvents()
Code to reproduce (save as test_qtbot.py):
Versions I am using: