Capture qutebrowser/httpbin output separately.
When using print and relying on pytest to capture it as stdout, we ran into this pytest/pytest-qt issue: https://github.com/pytest-dev/pytest-qt/issues/113 Now we use our own capturing mechanism instead, which also means we get nicer output. Fixes #1122.
This commit is contained in:
parent
7f83c6c5c8
commit
bba6589e19
@ -23,3 +23,4 @@
|
|||||||
|
|
||||||
from webserver import httpbin, httpbin_after_test
|
from webserver import httpbin, httpbin_after_test
|
||||||
from quteprocess import quteproc_process, quteproc
|
from quteprocess import quteproc_process, quteproc
|
||||||
|
from testprocess import pytest_runtest_makereport
|
||||||
|
@ -174,7 +174,7 @@ class QuteProc(testprocess.Process):
|
|||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
if (log_line.loglevel in ['INFO', 'WARNING', 'ERROR'] or
|
if (log_line.loglevel in ['INFO', 'WARNING', 'ERROR'] or
|
||||||
pytest.config.getoption('--verbose')):
|
pytest.config.getoption('--verbose')):
|
||||||
print(line)
|
self._log(line)
|
||||||
|
|
||||||
start_okay_message_load = (
|
start_okay_message_load = (
|
||||||
"load status for <qutebrowser.browser.webview.WebView tab_id=0 "
|
"load status for <qutebrowser.browser.webview.WebView tab_id=0 "
|
||||||
@ -306,7 +306,7 @@ class QuteProc(testprocess.Process):
|
|||||||
with open(session, encoding='utf-8') as f:
|
with open(session, encoding='utf-8') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
|
|
||||||
print(data)
|
self._log(data)
|
||||||
return yaml.load(data)
|
return yaml.load(data)
|
||||||
|
|
||||||
def get_content(self, plain=True):
|
def get_content(self, plain=True):
|
||||||
@ -341,8 +341,9 @@ def quteproc_process(qapp, httpbin, request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture
|
@pytest.yield_fixture
|
||||||
def quteproc(quteproc_process, httpbin):
|
def quteproc(quteproc_process, httpbin, request):
|
||||||
"""Per-test qutebrowser fixture which uses the per-file process."""
|
"""Per-test qutebrowser fixture which uses the per-file process."""
|
||||||
|
request.node._quteproc_log = quteproc_process.captured_log
|
||||||
quteproc_process.before_test()
|
quteproc_process.before_test()
|
||||||
yield quteproc_process
|
yield quteproc_process
|
||||||
quteproc_process.after_test()
|
quteproc_process.after_test()
|
||||||
|
@ -23,6 +23,7 @@ import re
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import pytest
|
||||||
import pytestqt.plugin
|
import pytestqt.plugin
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject, QElapsedTimer
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QProcess, QObject, QElapsedTimer
|
||||||
from PyQt5.QtTest import QSignalSpy
|
from PyQt5.QtTest import QSignalSpy
|
||||||
@ -71,6 +72,28 @@ class Line:
|
|||||||
return '{}({!r})'.format(self.__class__.__name__, self.data)
|
return '{}({!r})'.format(self.__class__.__name__, self.data)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
|
def pytest_runtest_makereport(item, call):
|
||||||
|
"""Add qutebrowser/httpbin sections to captured output if a test failed."""
|
||||||
|
outcome = yield
|
||||||
|
if call.when != 'call':
|
||||||
|
return
|
||||||
|
report = outcome.get_result()
|
||||||
|
|
||||||
|
if report.passed:
|
||||||
|
return
|
||||||
|
|
||||||
|
quteproc_log = getattr(item, '_quteproc_log', None)
|
||||||
|
httpbin_log = getattr(item, '_httpbin_log', None)
|
||||||
|
|
||||||
|
if quteproc_log is not None:
|
||||||
|
report.longrepr.addsection("qutebrowser output",
|
||||||
|
'\n'.join(quteproc_log))
|
||||||
|
if httpbin_log is not None:
|
||||||
|
report.longrepr.addsection("httpbin output",
|
||||||
|
'\n'.join(httpbin_log))
|
||||||
|
|
||||||
|
|
||||||
class Process(QObject):
|
class Process(QObject):
|
||||||
|
|
||||||
"""Abstraction over a running test subprocess process.
|
"""Abstraction over a running test subprocess process.
|
||||||
@ -93,11 +116,16 @@ class Process(QObject):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
self.captured_log = []
|
||||||
self._invalid = []
|
self._invalid = []
|
||||||
self._data = []
|
self._data = []
|
||||||
self.proc = QProcess()
|
self.proc = QProcess()
|
||||||
self.proc.setReadChannel(QProcess.StandardError)
|
self.proc.setReadChannel(QProcess.StandardError)
|
||||||
|
|
||||||
|
def _log(self, line):
|
||||||
|
"""Add the given line to the captured log output."""
|
||||||
|
self.captured_log.append(line)
|
||||||
|
|
||||||
def _parse_line(self, line):
|
def _parse_line(self, line):
|
||||||
"""Parse the given line from the log.
|
"""Parse the given line from the log.
|
||||||
|
|
||||||
@ -146,12 +174,12 @@ class Process(QObject):
|
|||||||
parsed = self._parse_line(line)
|
parsed = self._parse_line(line)
|
||||||
except InvalidLine:
|
except InvalidLine:
|
||||||
self._invalid.append(line)
|
self._invalid.append(line)
|
||||||
print("INVALID: {}".format(line))
|
self._log("INVALID: {}".format(line))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if parsed is None:
|
if parsed is None:
|
||||||
if self._invalid:
|
if self._invalid:
|
||||||
print("IGNORED: {}".format(line))
|
self._log("IGNORED: {}".format(line))
|
||||||
else:
|
else:
|
||||||
self._data.append(parsed)
|
self._data.append(parsed)
|
||||||
self.new_data.emit(parsed)
|
self.new_data.emit(parsed)
|
||||||
|
@ -129,7 +129,7 @@ class HTTPBin(testprocess.Process):
|
|||||||
return [r for r in requests if r.path != '/favicon.ico']
|
return [r for r in requests if r.path != '/favicon.ico']
|
||||||
|
|
||||||
def _parse_line(self, line):
|
def _parse_line(self, line):
|
||||||
print(line)
|
self._log(line)
|
||||||
if line == (' * Running on http://127.0.0.1:{}/ (Press CTRL+C to '
|
if line == (' * Running on http://127.0.0.1:{}/ (Press CTRL+C to '
|
||||||
'quit)'.format(self.port)):
|
'quit)'.format(self.port)):
|
||||||
self.ready.emit()
|
self.ready.emit()
|
||||||
@ -164,7 +164,8 @@ def httpbin(qapp):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.yield_fixture(autouse=True)
|
@pytest.yield_fixture(autouse=True)
|
||||||
def httpbin_after_test(httpbin):
|
def httpbin_after_test(httpbin, request):
|
||||||
"""Fixture to clean httpbin request list after each test."""
|
"""Fixture to clean httpbin request list after each test."""
|
||||||
|
request.node._httpbin_log = httpbin.captured_log
|
||||||
yield
|
yield
|
||||||
httpbin.after_test()
|
httpbin.after_test()
|
||||||
|
Loading…
Reference in New Issue
Block a user