@@ -155,6 +155,68 @@ ensuring the results are correct::
155155 assert_application_results(app)
156156
157157
158+ Exceptions in virtual methods
159+ =============================
160+
161+ It is common in Qt programming to override virtual C++ methods to customize
162+ behavior, like listening for mouse events, implement drawing routines, etc.
163+
164+ Fortunately, both ``PyQt `` and ``PySide `` support overriding this virtual methods
165+ naturally in your python code::
166+
167+ class MyWidget(QWidget):
168+
169+ # mouseReleaseEvent
170+ def mouseReleaseEvent(self, ev):
171+ print('mouse released at: %s' % ev.pos())
172+
173+ This works fine, but if python code in Qt virtual methods raise an exception
174+ ``PyQt `` and ``PySide `` will just print the exception traceback to standard
175+ error, since this method is called deep within Qt's even loop handling and
176+ exceptions are not allowed at that point.
177+
178+ This might be surprising for python users which are used to exceptions
179+ being raised at the calling point: for example, the following code will just
180+ print a stack trace without raising any exception::
181+
182+ class MyWidget(QWidget):
183+
184+ def mouseReleaseEvent(self, ev):
185+ raise RuntimeError('unexpected error')
186+
187+ w = MyWidget()
188+ QTest.mouseClick(w, QtCore.Qt.LeftButton)
189+
190+
191+ To make testing Qt code less surprising, ``pytest-qt `` automatically
192+ installs an exception hook which captures errors and fails tests when exceptions
193+ are raised inside virtual methods, like this::
194+
195+ E Failed: Qt exceptions in virtual methods:
196+ E ________________________________________________________________________________
197+ E File "x:\pytest-qt\pytestqt\_tests\test_exceptions.py", line 14, in event
198+ E raise RuntimeError('unexpected error')
199+ E
200+ E RuntimeError: unexpected error
201+
202+
203+ Disabling the automatic exception hook
204+ --------------------------------------
205+
206+ You can disable the automatic exception hook on individual tests by using a
207+ ``qt_no_exception_capture `` marker::
208+
209+ @pytest.mark.qt_no_exception_capture
210+ def test_buttons(qtbot):
211+ ...
212+
213+ Or even disable it for your entire project in your ``pytest.ini `` file::
214+
215+ [pytest]
216+ qt_no_exception_capture = 1
217+
218+ This might be desirable if you plan to install a custom exception hook.
219+
158220QtBot
159221=====
160222
0 commit comments