Comments (3)
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.
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.
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)
- How to use qapp_args() ? HOT 2
- How to reset qapp_args for each test class? HOT 6
- macos 14.0 (sonoma) doesn't pass control to qt HOT 16
- Tests using qtbot hang indefinitely on Mac OS Sonoma HOT 1
- How to test the following code...? HOT 1
- pytest-qt fails when snake_case feature is used in a test HOT 1
- How to use QAbstractItemModelTester? HOT 8
- test_exceptions_dont_leak fails with Python 3.12 HOT 7
- Intermittently missing property of object under test HOT 3
- More verbose tracebacks on exceptions in event loop HOT 1
- QDBusConnection.systemBus() leaks thread after qapp teardown HOT 3
- Clarification about methods like keyEvent, etc.? HOT 1
- Segfault on Linux with PyQt6 HOT 2
- "RuntimeError: Failed to disconnect" with `PySide6==6.7.0` HOT 19
- Crash on macOs Sonoma HOT 3
- SystemError on disconnect with pyside 6.7.1 HOT 7
- Clarify documentation around qtbot.waitSignals HOT 1
- _QtApi object has no attribute QtTest HOT 1
- qtbot.screenshot() changes test behavior HOT 4
- waitUntil page should link to waitUntil API doc and/or demonstrate use of the timeout param
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pytest-qt.