pytest-qt icon indicating copy to clipboard operation
pytest-qt copied to clipboard

Help with "Okaying" a message box using pytest-qt.

Open CiaranWelsh opened this issue 2 years ago • 1 comments

Hello - I'd like to ask a question if you don't mind. Given a simple message box application such as :

from PyQt5.QtWidgets import QMessageBox, QWidget


def messageBoxFactory(parent : QWidget, title:str, msg:str, level="info"):
    """Display a popup of type `level` containing msg[0] (title) and msg[1] the message.

    Makes use of the full QMessageBox (rather than QMessageBox.warning, for example) because
    it is necessary to have a handle to the box later for testing.
    """
    box = None
    if level == "info":
        box = QMessageBox(QMessageBox.Information, title, msg, QMessageBox.Ok, parent)
    elif level == "warning":
        box = QMessageBox(QMessageBox.Warning, title, msg, QMessageBox.Ok, parent)
    elif level == "critical":
        box = QMessageBox(QMessageBox.Critical, title, msg, QMessageBox.Ok, parent)

    if not box:
        raise ValueError("no QMessageBox created")
    box.exec()
    return box

how would one go about using pytest-qt's qbot to okay the popup? Here's my best try so far which does not work since the QMessageBox exec loop is running before qtbot can try to press anything.

from PyQt5.QtWidgets import QMainWindow, QDialogButtonBox
from PyQt5.QtCore import Qt
import pytest
from pytestqt.qtbot import QtBot
from accos.view.MessageBoxFactory import messageBoxFactory

def test_mbf(qtbot: QtBot):
    main_window = QMainWindow()
    box = messageBoxFactory(main_window, "Informational Message", "Some information", level="info")
    dialogButtonBox : QDialogButtonBox = box.children()[2]
    okayBtn = dialogButtonBox.buttons()[0]
    qtbot.mouseClick(okayBtn, Qt.LeftButton, Qt.NoModifier)

Thanks Ciaran

CiaranWelsh avatar Jul 07 '22 14:07 CiaranWelsh

Hey,

Modal dialogs are often a pain to test, I suggest to mock (using monkeypatch or pytest-mock) the exec() function. This way the message box won't even popup, and you can check in your test that exec has been called, something like:

def test_mbf(qtbot: QtBot, mocker):
    main_window = QMainWindow()
    exec_mock = mocker.patch.object(QMessageBox, "exec")
    messageBoxFactory(main_window, "Informational Message", "Some information", level="info")
    assert exec_mock.call_count == 1 

nicoddemus avatar Jul 07 '22 15:07 nicoddemus