在 的子类中QFileDialog
有一个方法 ,on_dir_entered
应该在QFileDialog
' 的信号directoryEntered
触发时调用它,因此:
self.directoryEntered.connect(self.on_dir_entered)
问题是信号需要很长时间才能生效。最初,我受到著名 PyQt5 专家 eyllanesc 的回答的启发。通过一个孤立的测试,这种技术QTimer.singleShot()
可以使用,尽管我从一开始就对它有模糊的怀疑。事实上,在我的机器上,我发现这种事情“测试泄漏”,特别是当有不止一种这样的测试方法时:奇怪的错误显然发生在测试本身之外:
TEARDOWN ERROR: Exceptions caught in Qt event loop:
...所以我回到 pytest-qt 文档,发现有各种可用的方法开始wait...
似乎可以解决信号或其他事件需要花费不可忽略的时间才能生效的问题。所以我做了一些尝试来测试信号directoryEntered
:
def test_directoryEntered_triggers_on_dir_entered(request, qtbot, tmpdir):
project = mock.Mock()
project.main_window = QtWidgets.QWidget()
project.home_dir_path = pathlib.Path(str(tmpdir))
fd = save_project_dialog_class.SaveProjectDialog(project)
with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
fd.directoryEntered.emit('dummy')
qtbot.waitSignal(fd.directoryEntered, timeout=1000)
mock_entered.assert_called_once()
接着
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
project = mock.Mock()
project.main_window = QtWidgets.QWidget()
project.home_dir_path = pathlib.Path(str(tmpdir))
fd = SaveProjectDialog(project)
qtbot.waitSignal(fd.directoryEntered, timeout=1000)
with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
fd.directoryEntered.emit('dummy')
mock_entered.assert_called_once()
接着
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
project = mock.Mock()
project.main_window = QtWidgets.QWidget()
project.home_dir_path = pathlib.Path(str(tmpdir))
fd = SaveProjectDialog(project)
with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
fd.directoryEntered.emit('dummy')
qtbot.wait(1000)
mock_entered.assert_called_once()
全部失败:该方法被调用 0 次。
我也试过:
def test_directoryEntered_triggers_on_dir_entered(qtbot, tmpdir):
project = mock.Mock()
project.main_window = QtWidgets.QWidget()
project.home_dir_path = pathlib.Path(str(tmpdir))
fd = SaveProjectDialog(project)
with mock.patch.object(fd, 'on_dir_entered') as mock_entered:
fd.directoryEntered.emit('dummy')
def check_called():
mock_entered.assert_called_once()
qtbot.waitUntil(check_called)
... 这超时(默认 5000 毫秒)。我已经反复检查并检查了connect
在此信号上设置的代码是否已执行。
之后
print
通过在被调用的 slot ( ) 中添加一条语句,on_dir_entered
我现在看到了问题所在:尽管有这with mock.patch...
条线,但该方法并没有被嘲笑!
在我对嘲笑等知识的低水平上,我倾向于认为这是因为使用信号emit()
来触发事件的事实:我想不出另一种解释。
注意这个信号是由 a 中的一个或两个事件“自然地”触发的QFileDialog
(例如单击“转到父目录” QToolButton
)。也许你必须这样做......所以我尝试了这个:
def test_directoryEntered_triggers_on_dir_entered(request, qtbot, tmpdir):
project = mock.Mock()
project.main_window = QtWidgets.QWidget()
project.home_dir_path = pathlib.Path(str(tmpdir))
fd = save_project_dialog_class.SaveProjectDialog(project)
to_parent_button = fd.findChild(QtWidgets.QToolButton, 'toParentButton')
print(f'qtbot {qtbot} type(qtbot) {type(qtbot)}')
with mock.patch.object(SaveProjectDialog, 'on_dir_entered') as mock_entered:
qtbot.mouseClick(to_parent_button, QtCore.Qt.LeftButton)
def check_called():
mock_entered.assert_called_once()
qtbot.waitUntil(check_called, timeout=1000)
暂停。0 次通话。我再次能够确定正在调用真正的方法,并且补丁不起作用。
我做错了什么,有没有办法用 pytest-qt 的东西来测试它?