pythontestingpyqt5pytestpytest-qt

pytest-qt to test menu functionality


I have a menu that I created


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None)
    ...
    create_menu_bar()
    ...

    def create_menu_bar(self):
        sheet_one = QtWidgets.QAction("sheet_one", self)
        sheet_one.triggered.connect(lambda: self.load_df(sheet_name="sheet one"))
        # more QActions createad

        menu = self.menuBar()
        menu.addAction(sheet_one)
        # drop down list
        sheet_five_menu = menu.addMenu("&sheet five")
        sheet_five_menu.addAction(sheet_five_one)
        sheet_five_menu.addAction(sheet_five_two)
        ...

I am trying to use pytest-qt to imitate a user clicking on one of the menu options, or clicking on one of the drop down menu options from sheet_five_menu

After reading the documentation I have been able to understand how to open a window and view it. But I am having trouble understanding how to imitate user mouse clicks on my implementation of the menu. I read this stackoverflow, implemented, but got this error.

E AttributeError: 'NoneType' object has no attribute 'triggered'

test_app.py:11: AttributeError

what my test code currently looks like


def test_menu(qtbot):
    window = my_app.MainWindow()
    qtbot.add_widget(window)
    window.show()
    window.findChild(QtWidgets.QAction, 'sheet_one').trigger()


EDIT

reading this qt docs I understand that I should be able to trigger the QAction in this way but I am also getting error

revised code :


window.sheet_one.trigger()

but I am getting this error:

E AttributeError: 'MainWindow' object has no attribute 'sheet_one'

I also tried example:


menu = window.create_menu_bar()
menu.actions()[0]
menu.trigger()

but am getting this error:

E AttributeError: 'NoneType' object has no attribute 'trigger'


Solution

  • findChild uses the objectName property to find any child QObject.

    You are just setting the text, which is mainly a visual clue, but has absolutely no relation with the Qt object name, nor it should ever have any, since the text of an action could change during runtime, and updating the object name based on the text could become a serious problem.

    By default QObjects have no object name set (an empty string), so findChild() will return None as there is no QAction that have sheet_one as its objectName.

    You also used a space in the text, but you called findChild() using sheet_one with an underscore, so it wouldn't have worked anyway.

    Note that if you intended to use that sheet_one as a reference to the variable assigned in create_menu_bar that would be completely pointless, since that is just a local reference and its name is irrelevant; even if you used an instance attribute it wouldn't have worked anyway, because Qt has absolutely no knowledge about python.

    Just set the proper object name for the action:

    sheet_one.setObjectName('sheet_one')