Skip to content

Commit e8f9c78

Browse files
codambroCody D'Ambrosiopre-commit-ci[bot]
authored
Add logging to TAP file (#94)
* add TAP logging * Update AUTHORS * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix line breaks * add test * improve log out * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add diagnostics to ok tests * Update setup.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixes and cleanup * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * use showcapture arg * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Cody D'Ambrosio <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 3764cb2 commit e8f9c78

File tree

6 files changed

+76
-4
lines changed

6 files changed

+76
-4
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Contributors
44
------------
55

66
* Allison Karlitskaya
7+
* Cody D'Ambrosio
78
* Dan Dofter
89
* Erik Cederstrand
910
* Frédéric Mangano-Tarumi

conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ def sample_test_file(testdir):
88
testdir.makepyfile(
99
"""
1010
import pytest
11+
import logging
12+
13+
LOGGER = logging.getLogger(__name__)
1114
1215
def test_ok():
16+
LOGGER.info("Running test_ok")
17+
LOGGER.debug("Debug logging info")
1318
assert True
1419
1520
def test_not_ok():
21+
LOGGER.error("Running test_not_ok")
1622
assert False
1723
1824
@pytest.mark.parametrize('param', ("foo", "bar"))

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
include_package_data=True,
3636
zip_safe=False,
3737
platforms="any",
38-
install_requires=["pytest>=3.0", "tap.py>=3.0,<4.0"],
38+
install_requires=["pytest>=3.0", "tap.py>=3.2,<4.0"],
3939
classifiers=[
4040
"Development Status :: 5 - Production/Stable",
4141
"Framework :: Pytest",

src/pytest_tap/plugin.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
from tap.formatter import format_as_diagnostics
66
from tap.tracker import Tracker
77

8+
SHOW_CAPTURE_LOG = ("log", "all")
9+
SHOW_CAPTURE_OUT = ("stdout", "all")
10+
SHOW_CAPTUER_ERR = ("stderr", "all")
11+
812

913
class TAPPlugin:
1014
def __init__(self, config: pytest.Config) -> None:
@@ -25,6 +29,9 @@ def __init__(self, config: pytest.Config) -> None:
2529
# Disable it automatically for streaming.
2630
self._tracker.header = False
2731

32+
self.tap_logging = config.option.showcapture
33+
self.tap_log_passing_tests = config.option.tap_log_passing_tests
34+
2835
@pytest.hookimpl()
2936
def pytest_runtestloop(self, session):
3037
"""Output the plan line first."""
@@ -70,9 +77,12 @@ def pytest_runtest_logreport(self, report: pytest.TestReport):
7077
directive = "TODO unexpected success{}".format(reason)
7178
self._tracker.add_ok(testcase, description, directive=directive)
7279
elif report.passed:
73-
self._tracker.add_ok(testcase, description)
80+
diagnostics = None
81+
if self.tap_log_passing_tests:
82+
diagnostics = _make_as_diagnostics(report, self.tap_logging)
83+
self._tracker.add_ok(testcase, description, diagnostics=diagnostics)
7484
elif report.failed:
75-
diagnostics = _make_as_diagnostics(report)
85+
diagnostics = _make_as_diagnostics(report, self.tap_logging)
7686

7787
# pytest treats an unexpected success from unitest.expectedFailure
7888
# as a failure.
@@ -143,6 +153,12 @@ def pytest_addoption(parser):
143153
"If the directory does not exist, it will be created."
144154
),
145155
)
156+
group.addoption(
157+
"--tap-log-passing-tests",
158+
default=False,
159+
action="store_true",
160+
help="Capture log information for passing tests to TAP report",
161+
)
146162

147163

148164
@pytest.hookimpl(trylast=True)
@@ -161,7 +177,27 @@ def pytest_configure(config: pytest.Config) -> None:
161177
config.pluginmanager.register(TAPPlugin(config), "tapplugin")
162178

163179

164-
def _make_as_diagnostics(report):
180+
def _make_as_diagnostics(report, tap_logging):
165181
"""Format a report as TAP diagnostic output."""
166182
lines = report.longreprtext.splitlines(keepends=True)
183+
184+
if tap_logging in SHOW_CAPTURE_LOG:
185+
if lines:
186+
lines[-1] += "\n"
187+
lines += ["--- Captured Log ---\n"] + (
188+
report.caplog.splitlines(keepends=True) or [""]
189+
)
190+
if tap_logging in SHOW_CAPTURE_OUT:
191+
if lines:
192+
lines[-1] += "\n"
193+
lines += ["--- Captured Out ---\n"] + (
194+
report.capstdout.splitlines(keepends=True) or [""]
195+
)
196+
if tap_logging in SHOW_CAPTUER_ERR:
197+
if lines:
198+
lines[-1] += "\n"
199+
lines += ["--- Captured Err ---\n"] + (
200+
report.capstderr.splitlines(keepends=True) or [""]
201+
)
202+
167203
return format_as_diagnostics(lines)

tests/test_help.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ def test_includes_options(testdir):
77
"*--tap-files*",
88
"*--tap-combined*",
99
"*--tap-outdir=path*",
10+
"*--tap-log-passing-tests*",
1011
]
1112
result.stdout.fnmatch_lines(expected_option_flags)
1213

tests/test_plugin.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,34 @@ def test_outdir(testdir, sample_test_file):
8686
assert testresults.check()
8787

8888

89+
def test_logging(testdir, sample_test_file):
90+
"""Test logs are added to TAP diagnostics."""
91+
result = testdir.runpytest_subprocess("--tap")
92+
result.stdout.fnmatch_lines(
93+
[
94+
"# --- Captured Log ---",
95+
"*Running test_not_ok*",
96+
"# --- Captured Out ---",
97+
"# --- Captured Err ---",
98+
]
99+
)
100+
result.stdout.no_fnmatch_line("*Running test_ok*")
101+
102+
103+
def test_log_passing_tests(testdir, sample_test_file):
104+
"""Test logs are added to TAP diagnostics."""
105+
result = testdir.runpytest_subprocess(
106+
"--tap", "--tap-log-passing-tests", "--log-level", "INFO"
107+
)
108+
result.stdout.fnmatch_lines(
109+
[
110+
"# --- Captured Log ---",
111+
"*Running test_ok*",
112+
]
113+
)
114+
result.stdout.no_fnmatch_line("*Debug logging info*")
115+
116+
89117
def test_xfail_no_reason(testdir):
90118
"""xfails output gracefully when no reason is provided."""
91119
testdir.makepyfile(

0 commit comments

Comments
 (0)