Giter Club home page Giter Club logo

Comments (3)

nicoddemus avatar nicoddemus commented on September 7, 2024

Hi Benjamin,

Well, this is an issue I find often at work with our xUnit code base. For QMessageBox.question specifically, I usually mock it:

def test_Qt(qtbot, mock):
    simple = Simple()
    qtbot.addWidget(simple)

    mock.patch.object(QMessageBox, 'question', return_value=QMessageBox.Yes)
    simple.query()
    assert simple.answer

(here I'm using pytest-mock, but using mock directly is fine too)

But the problem remains when you want to test a customized QDialog subclass. As you noted, exec_ enters its own loop and blocks main loop execution at that point.

One solution is to use a QTimer to fire an event some time after calling exec_():

def test_dialog(qtbot):
    dialog = Dialog()
    qtbot.addWidget(dialog)

    def interact():
        qtbot.click(dialog.button)

    QTimer.singleShot(500, interact)
    simple.query() # blocks

Another approach is to not call exec_ at all, using show() instead, which is fine if you are testing the dialog itself.

If you have some kind of Form widget that makes use of a custom QDialog in some of its interactions, I usually test the dialog separately using show(), and mock it when testing the Form itself like in the first example.

Cheers,

from pytest-qt.

baudren avatar baudren commented on September 7, 2024

Hi,

thanks for the mock example for the question, it works flawlessly.

I tried both of your suggestion for the a Form widget running a QDialog, and only managed to make the QTimer solution work. It is probably due to my poor understanding of how the mock.patch.object work, but when I try to give a custom class as the first argument, and an attribute name as the second argument, it searches the attribute inside the class. Would you have a ressource other than this that explains how this works?

In any case, I am fine with QTimer. I would suggest that it appears somewhere in the documentation - maybe it is because I am a beginner tester, but I find extremely tough to find any information on how to properly test a Qt application. Since qtbot provides so much possibility, it would be great to expand its documentation. I would say that your answer could go directly after this part.

Thanks again for your time and detailled answers.

from pytest-qt.

nicoddemus avatar nicoddemus commented on September 7, 2024

Thanks for the suggestion, I will add an example to the documentation (#19). 😄

About the example, I should have provided some code to make it clearer:

Suppose you have a custom dialog that asks the user for their name and age, and a Form that uses it. I usually add a convenience function that also has the nice benefit of making testing easier, like this:

class AskNameAndAgeDialog(QDialog):
    ...
    @classmethod
    def ask(cls, text, parent):
        dialog = cls(parent)
        dialog.text.setText(text)
        if dialog.exec_() == QDialog.Accepted:
            return dialog.getName(), dialog.getAge()
        else:
            return None, None                              

This allows clients of the dialog to use it as such:

name, age = AskNameAndAgeDialog.ask("Enter name and age because of bananas:", parent)
if name is not None:
    # use name and age for bananas

Now it is easy to mock AskNameAndAgeDialog.ask when testing Form:

def test_form_registration(qtbot, mock):
    form = RegistrationForm()

    mock.patch.object(AskNameAndAgeDialog, 'ask', return_value=('Jonh', 30))
    qtbot.click(form.enter_info()) # calls AskNameAndAgeDialog.ask
    # test that the rest of the form correctly behaves as if
    # user entered "Jonh" and 30 as name and age 

Hope that's clearer.

If you have any other questions, please don't hesitate to ask them. :)

Cheers

from pytest-qt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.