Skip to content

Commit

Permalink
Capture exceptions during test teardown
Browse files Browse the repository at this point in the history
Fixes #65
  • Loading branch information
nicoddemus committed Aug 1, 2015
1 parent 1a29606 commit 70437e3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 5 deletions.
35 changes: 34 additions & 1 deletion pytestqt/_tests/test_exceptions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest
import sys
from pytestqt.plugin import format_captured_exceptions
from pytestqt.plugin import format_captured_exceptions, QT_API


pytest_plugins = 'pytester'
Expand Down Expand Up @@ -58,6 +58,8 @@ def test_format_captured_exceptions():


@pytest.mark.parametrize('no_capture_by_marker', [True, False])
@pytest.mark.skipif(QT_API == 'pyqt5', reason='non captured exceptions on PyQt'
' 5.5+ crash the interpreter.')
def test_no_capture(testdir, no_capture_by_marker):
"""
Make sure options that disable exception capture are working (either marker
Expand Down Expand Up @@ -90,3 +92,34 @@ def test_widget(qtbot):
'''.format(marker_code=marker_code))
res = testdir.inline_run()
res.assertoutcome(passed=1)


def test_exception_capture_on_teardown(testdir):
"""
Exceptions should also be captured during test teardown.
:type testdir: TmpTestdir
"""
testdir.makepyfile('''
import pytest
from pytestqt.qt_compat import QWidget, QtCore, QEvent
class MyWidget(QWidget):
def event(self, ev):
raise RuntimeError('event processed')
def test_widget(qtbot, qapp):
w = MyWidget()
# keep a reference to the widget so it will lives after the test
# ends. This will in turn trigger its event() during test tear down,
# raising the exception during its event processing
test_widget.w = w
qapp.postEvent(w, QEvent(QEvent.User))
''')
res = testdir.runpytest('-s')
res.stdout.fnmatch_lines([
"*RuntimeError('event processed')*",
'*1 error*',
])

20 changes: 16 additions & 4 deletions pytestqt/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,7 @@ def qtbot(qapp, request):
that they are properly closed after the test ends.
"""
result = QtBot()
no_capture = request.node.get_marker('qt_no_exception_capture') or \
request.config.getini('qt_no_exception_capture')
no_capture = _exception_capture_disabled(request.node)
if no_capture:
yield result # pragma: no cover
else:
Expand All @@ -557,6 +556,13 @@ def qtbot(qapp, request):
result._close()


def _exception_capture_disabled(item):
"""returns if exception capture is disabled for the given test item.
"""
return item.get_marker('qt_no_exception_capture') or \
item.config.getini('qt_no_exception_capture')


def pytest_addoption(parser):
parser.addini('qt_no_exception_capture',
'disable automatic exception capture')
Expand All @@ -581,15 +587,21 @@ def pytest_addoption(parser):


@pytest.mark.hookwrapper
def pytest_runtest_teardown():
def pytest_runtest_teardown(item):
"""
Hook called after each test tear down, to process any pending events and
avoiding leaking events to the next test.
"""
yield
app = QApplication.instance()
if app is not None:
app.processEvents()
if _exception_capture_disabled(item):
app.processEvents()
else:
with capture_exceptions() as exceptions:
app.processEvents()
if exceptions:
pytest.fail('TEARDOWN ERROR: ' + format_captured_exceptions(exceptions))


def pytest_configure(config):
Expand Down

0 comments on commit 70437e3

Please sign in to comment.