Skip to content

Commit 01d88b9

Browse files
committed
Using contextual information in Qt5 for logging message failures
#55
1 parent 81b5b66 commit 01d88b9

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

pytestqt/_tests/test_logging.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from pytestqt.qt_compat import qDebug, qWarning, qCritical, QtDebugMsg, \
6-
QtWarningMsg, QtCriticalMsg
6+
QtWarningMsg, QtCriticalMsg, QT_API
77

88
pytest_plugins = 'pytester'
99

@@ -36,9 +36,9 @@ def test_types():
3636
if qt_log:
3737
res.stdout.fnmatch_lines([
3838
'*-- Captured Qt messages --*',
39-
'QtDebugMsg: this is a DEBUG message*',
40-
'QtWarningMsg: this is a WARNING message*',
41-
'QtCriticalMsg: this is a CRITICAL message*',
39+
'*QtDebugMsg: this is a DEBUG message*',
40+
'*QtWarningMsg: this is a WARNING message*',
41+
'*QtCriticalMsg: this is a CRITICAL message*',
4242
])
4343
else:
4444
res.stdout.fnmatch_lines([
@@ -293,7 +293,7 @@ def test1():
293293
res.assertoutcome(passed=passed, failed=int(not passed))
294294

295295

296-
def test_logging_fails_lineno(testdir):
296+
def test_lineno_failure(testdir):
297297
"""
298298
Test that tests when failing because log messages were emitted report
299299
the correct line number.
@@ -310,8 +310,17 @@ def test_logging_fails_lineno(testdir):
310310
"""
311311
from pytestqt.qt_compat import qWarning
312312
def test_foo():
313+
assert foo() == 10
314+
def foo():
313315
qWarning('this is a WARNING message')
316+
return 10
314317
"""
315318
)
316319
res = testdir.runpytest()
317-
res.stdout.fnmatch_lines('*test_logging_fails_lineno.py:2: Failure:*')
320+
if QT_API == 'pyqt5':
321+
res.stdout.fnmatch_lines([
322+
'*test_lineno_failure.py:2: Failure*',
323+
'*test_lineno_failure.py:foo:5: QtWarning*'],
324+
)
325+
else:
326+
res.stdout.fnmatch_lines('*test_lineno_failure.py:2: Failure*')

pytestqt/plugin.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from collections import namedtuple
12
from contextlib import contextmanager
23
import functools
34
import sys
@@ -568,8 +569,12 @@ def pytest_addoption(parser):
568569

569570
parser.addoption('--no-qt-log', dest='qt_log', action='store_false',
570571
default=True)
571-
parser.addoption('--qt-log-format', dest='qt_log_format',
572-
default='{rec.type_name}: {rec.message}')
572+
if QT_API == 'pyqt5':
573+
default = '{rec.context.file}:{rec.context.function}:' \
574+
'{rec.context.line}: {rec.type_name}: {rec.message}'
575+
else:
576+
default = '{rec.type_name}: {rec.message}'
577+
parser.addoption('--qt-log-format', dest='qt_log_format', default=default)
573578

574579

575580
@pytest.mark.hookwrapper
@@ -671,7 +676,8 @@ def pytest_runtest_makereport(self, item, call):
671676
lines = []
672677
for rec in item.qt_log_capture.records:
673678
suffix = ' (IGNORED)' if rec.ignored else ''
674-
lines.append(log_format.format(rec=rec) + suffix)
679+
line = log_format.format(rec=rec) + suffix
680+
lines.append(line)
675681
if lines:
676682
long_repr.addsection('Captured Qt messages',
677683
'\n'.join(lines))
@@ -695,21 +701,34 @@ def __init__(self, ignore_regexes):
695701
self._records = []
696702
self._ignore_regexes = ignore_regexes or []
697703

698-
def _handle(self, msg_type, message):
704+
_Context = namedtuple('_Context', 'file function line')
705+
706+
def _handle(self, msg_type, message, context=None):
699707
"""
700708
Method to be installed using qInstallMsgHandler, stores each message
701709
into the `messages` attribute.
702710
"""
703-
if isinstance(message, bytes):
704-
message = message.decode('utf-8', 'replace')
711+
def to_unicode(s):
712+
if isinstance(s, bytes):
713+
s = s.decode('utf-8', 'replace')
714+
return s
715+
716+
message = to_unicode(message)
705717

706718
ignored = False
707719
for regex in self._ignore_regexes:
708720
if re.search(regex, message) is not None:
709721
ignored = True
710722
break
711723

712-
self._records.append(Record(msg_type, message, ignored))
724+
if context is not None:
725+
context = self._Context(
726+
to_unicode(context.file),
727+
to_unicode(context.function),
728+
context.line,
729+
)
730+
731+
self._records.append(Record(msg_type, message, ignored, context))
713732

714733
@property
715734
def records(self):
@@ -733,22 +752,26 @@ class Record(object):
733752
:ivar datetime.datetime when: when the message was captured
734753
:ivar bool ignored: If this record matches a regex from the "qt_log_ignore"
735754
option.
755+
:ivar context: a namedtuple containing the attributes ``file``,
756+
``function``, ``line``. Only available in Qt5, otherwise is None.
736757
"""
737758

738-
def __init__(self, msg_type, message, ignored):
759+
def __init__(self, msg_type, message, ignored, context):
739760
self._type = msg_type
740761
self._message = message
741762
self._type_name = self._get_msg_type_name(msg_type)
742763
self._log_type_name = self._get_log_type_name(msg_type)
743764
self._when = datetime.datetime.now()
744765
self._ignored = ignored
766+
self._context = context
745767

746768
message = property(lambda self: self._message)
747769
type = property(lambda self: self._type)
748770
type_name = property(lambda self: self._type_name)
749771
log_type_name = property(lambda self: self._log_type_name)
750772
when = property(lambda self: self._when)
751773
ignored = property(lambda self: self._ignored)
774+
context = property(lambda self: self._context)
752775

753776
@classmethod
754777
def _get_msg_type_name(cls, msg_type):

pytestqt/qt_compat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ def qInstallMsgHandler(handler):
101101
message handler's signature.
102102
"""
103103
def _Qt5MessageHandler(msg_type, context, msg):
104-
handler(msg_type, msg)
104+
handler(msg_type, msg, context)
105105
if handler is not None:
106106
return QtCore.qInstallMessageHandler(_Qt5MessageHandler)
107107
else:

0 commit comments

Comments
 (0)