Incorrect waitSignal + connect
import pytest
from PySide6.QtCore import QObject, Signal, QThread, QTimer
from PySide6.QtWidgets import QApplication
from pytestqt.qtbot import QtBot
@pytest.fixture(scope="session", autouse=True)
def qapp_instance():
app = QApplication.instance()
if app is None:
app = QApplication([])
return app
class MySignalEmitter(QObject):
signal_A_emitted = Signal(str, int)
signal_B_emitted = Signal(bool, float)
def __init__(self):
super().__init__()
self._thread = QThread()
self.moveToThread(self._thread)
self._thread.started.connect(self._keep_thread_alive)
def _keep_thread_alive(self):
pass
def start(self):
if not self._thread.isRunning():
self._thread.start()
def stop(self):
if self._thread.isRunning():
self._thread.quit()
self._thread.wait(500)
def emit_signal_A(self, message: str, code: int):
if self._thread.isRunning():
QTimer.singleShot(0, lambda: self.signal_A_emitted.emit(message, code))
else:
self.signal_A_emitted.emit(message, code)
def emit_signal_B(self, status: bool, value: float):
if self._thread.isRunning():
QTimer.singleShot(0, lambda: self.signal_B_emitted.emit(status, value))
else:
self.signal_B_emitted.emit(status, value)
def test_signals(qtbot: QtBot):
emitter = MySignalEmitter()
emitter.start()
with qtbot.waitSignal((emitter.signal_A_emitted, "A"), timeout=3000, raising=True) as blocker:
blocker.connect((emitter.signal_B_emitted, "B"))
emitter.emit_signal_B(True, 3.14)
assert blocker.signal_triggered is True
assert blocker.args == [True, 3.14]
assert blocker.signal_name == "B"
with qtbot.waitSignal((emitter.signal_A_emitted, "A"), timeout=3000, raising=True) as blocker:
blocker.connect((emitter.signal_B_emitted, "B"))
emitter.emit_signal_A("message", 0)
assert blocker.signal_triggered is True
assert blocker.args == ["message", 0]
assert blocker.signal_name == "A"
emitter.stop()
will fail with:
> assert blocker.signal_name == "A"
E AssertionError: assert 'B' == 'A'
E
E - A
E + B
src\tests\issue_pytestqt_test.py:73: AssertionError
what is the workaround to have an OR condition?
Hi @danicc097,
I'm not sure I understand why emitter.emit_signal_A ends up emitting signal_B_emitted. 🤔
Ok, looking at connect I see it overrides self.signal_name, so thats the issue. MultiSignalBlocker waits for all signals so I don't know if it'd be simpler to allow it to wait for the first n signals instead of updating the SignalBlocker
Ok, looking at connect I see it overrides self.signal_name, so thats the issue.
I see thanks.
MultiSignalBlocker waits for all signals
There's blocker.all_signals_and_args, perhaps that helps?
Ok, looking at connect I see it overrides self.signal_name, so thats the issue.
I see thanks.
MultiSignalBlocker waits for all signals
There's
blocker.all_signals_and_args, perhaps that helps?
Unfortunately MultiSignalBlocker would still require waiting for both signals.
For my tests the only reason I wanted this OR condition was to skip waiting for long timeouts when tests fail and the wrong signals are triggered (say error instead of success), so assertNotEmitted fits more in that case.
Regarding the original issue, I think the signal_name should be corrected once any of the connected signals is triggered