Skip to content

Commit

Permalink
Merge pull request #3234 from thisch/showcapture_log_support
Browse files Browse the repository at this point in the history
Add captured-log support to --show-capture
  • Loading branch information
nicoddemus authored Feb 19, 2018
2 parents 3bc8b50 + acda6c4 commit 97bb6ab
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 54 deletions.
19 changes: 10 additions & 9 deletions _pytest/debugging.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ def _enter_pdb(node, excinfo, rep):
tw = node.config.pluginmanager.getplugin("terminalreporter")._tw
tw.line()

captured_stdout = rep.capstdout
if len(captured_stdout) > 0:
tw.sep(">", "captured stdout")
tw.line(captured_stdout)

captured_stderr = rep.capstderr
if len(captured_stderr) > 0:
tw.sep(">", "captured stderr")
tw.line(captured_stderr)
showcapture = node.config.option.showcapture

for sectionname, content in (('stdout', rep.capstdout),
('stderr', rep.capstderr),
('log', rep.caplog)):
if showcapture in (sectionname, 'all') and content:
tw.sep(">", "captured " + sectionname)
if content[-1:] == "\n":
content = content[:-1]
tw.line(content)

tw.sep(">", "traceback")
rep.toterminal(tw)
Expand Down
14 changes: 7 additions & 7 deletions _pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ def pytest_addoption(parser):
help="traceback print mode (auto/long/short/line/native/no).")
group._addoption('--show-capture',
action="store", dest="showcapture",
choices=['no', 'stdout', 'stderr', 'both'], default='both',
help="Controls how captured stdout/stderr is shown on failed tests. "
"Default is 'both'.")
choices=['no', 'stdout', 'stderr', 'log', 'all'], default='all',
help="Controls how captured stdout/stderr/log is shown on failed tests. "
"Default is 'all'.")
group._addoption('--fulltrace', '--full-trace',
action="store_true", default=False,
help="don't cut any tracebacks (default is to cut).")
Expand Down Expand Up @@ -630,12 +630,12 @@ def summary_errors(self):

def _outrep_summary(self, rep):
rep.toterminal(self._tw)
if self.config.option.showcapture == 'no':
showcapture = self.config.option.showcapture
if showcapture == 'no':
return
for secname, content in rep.sections:
if self.config.option.showcapture != 'both':
if not (self.config.option.showcapture in secname):
continue
if showcapture != 'all' and showcapture not in secname:
continue
self._tw.sep("-", secname)
if content[-1:] == "\n":
content = content[:-1]
Expand Down
2 changes: 1 addition & 1 deletion changelog/1478.feature
Original file line number Diff line number Diff line change
@@ -1 +1 @@
New ``--show-capture`` command-line option that allows to specify how to display captured output when tests fail: ``no``, ``stdout``, ``stderr`` or ``both`` (the default).
New ``--show-capture`` command-line option that allows to specify how to display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log`` or ``all`` (the default).
1 change: 1 addition & 0 deletions changelog/3204.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Captured logs are printed before entering pdb.
22 changes: 3 additions & 19 deletions doc/en/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,26 +50,10 @@ These options can also be customized through ``pytest.ini`` file:
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
Further it is possible to disable reporting logs on failed tests completely
with::
Further it is possible to disable reporting of captured content (stdout,
stderr and logs) on failed tests completely with::

pytest --no-print-logs

Or in the ``pytest.ini`` file:

.. code-block:: ini
[pytest]
log_print = False
Shows failed tests in the normal manner as no logs were captured::

----------------------- Captured stdout call ----------------------
text going to stdout
----------------------- Captured stderr call ----------------------
text going to stderr
==================== 2 failed in 0.02 seconds =====================
pytest --show-capture=no


caplog fixture
Expand Down
18 changes: 18 additions & 0 deletions testing/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,24 @@ def test_1():
assert "captured stderr" not in output
self.flush(child)

@pytest.mark.parametrize('showcapture', ['all', 'no', 'log'])
def test_pdb_print_captured_logs(self, testdir, showcapture):
p1 = testdir.makepyfile("""
def test_1():
import logging
logging.warn("get " + "rekt")
assert False
""")
child = testdir.spawn_pytest("--show-capture=%s --pdb %s" % (showcapture, p1))
if showcapture in ('all', 'log'):
child.expect("captured log")
child.expect("get rekt")
child.expect("(Pdb)")
child.sendeof()
rest = child.read().decode("utf8")
assert "1 failed" in rest
self.flush(child)

def test_pdb_interaction_exception(self, testdir):
p1 = testdir.makepyfile("""
import pytest
Expand Down
52 changes: 34 additions & 18 deletions testing/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -851,31 +851,47 @@ def pytest_report_header(config, startdir):
def test_show_capture(self, testdir):
testdir.makepyfile("""
import sys
import logging
def test_one():
sys.stdout.write('!This is stdout!')
sys.stderr.write('!This is stderr!')
logging.warning('!This is a warning log msg!')
assert False, 'Something failed'
""")

result = testdir.runpytest("--tb=short")
result.stdout.fnmatch_lines(["!This is stdout!"])
result.stdout.fnmatch_lines(["!This is stderr!"])

result = testdir.runpytest("--show-capture=both", "--tb=short")
result.stdout.fnmatch_lines(["!This is stdout!"])
result.stdout.fnmatch_lines(["!This is stderr!"])

result = testdir.runpytest("--show-capture=stdout", "--tb=short")
assert "!This is stderr!" not in result.stdout.str()
assert "!This is stdout!" in result.stdout.str()

result = testdir.runpytest("--show-capture=stderr", "--tb=short")
assert "!This is stdout!" not in result.stdout.str()
assert "!This is stderr!" in result.stdout.str()

result = testdir.runpytest("--show-capture=no", "--tb=short")
assert "!This is stdout!" not in result.stdout.str()
assert "!This is stderr!" not in result.stdout.str()
result.stdout.fnmatch_lines(["!This is stdout!",
"!This is stderr!",
"*WARNING*!This is a warning log msg!"])

result = testdir.runpytest("--show-capture=all", "--tb=short")
result.stdout.fnmatch_lines(["!This is stdout!",
"!This is stderr!",
"*WARNING*!This is a warning log msg!"])

stdout = testdir.runpytest(
"--show-capture=stdout", "--tb=short").stdout.str()
assert "!This is stderr!" not in stdout
assert "!This is stdout!" in stdout
assert "!This is a warning log msg!" not in stdout

stdout = testdir.runpytest(
"--show-capture=stderr", "--tb=short").stdout.str()
assert "!This is stdout!" not in stdout
assert "!This is stderr!" in stdout
assert "!This is a warning log msg!" not in stdout

stdout = testdir.runpytest(
"--show-capture=log", "--tb=short").stdout.str()
assert "!This is stdout!" not in stdout
assert "!This is stderr!" not in stdout
assert "!This is a warning log msg!" in stdout

stdout = testdir.runpytest(
"--show-capture=no", "--tb=short").stdout.str()
assert "!This is stdout!" not in stdout
assert "!This is stderr!" not in stdout
assert "!This is a warning log msg!" not in stdout


@pytest.mark.xfail("not hasattr(os, 'dup')")
Expand Down

0 comments on commit 97bb6ab

Please sign in to comment.