Skip to content

Commit

Permalink
Post process html to include teardown in log (#271)
Browse files Browse the repository at this point in the history
  • Loading branch information
csm10495 authored Sep 18, 2020
1 parent c5a8263 commit f2d41db
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ Release Notes

* Thanks to `@Zac-HD <https://github.com/Zac-HD>`_ for the fix

* Post process HTML generation to allow teardown to appear in the HTML output. (`#131 <https://github.com/pytest-dev/pytest-html/issues/131>`_)

* Thanks to `@iwanb <https://github.com/iwanb>`_ for reporting and `@csm10495 <https://github.com/csm10495>`_ for the fix

**2.1.1 (2020-03-18)**

* Fix issue with funcargs causing failures. (`#282 <https://github.com/pytest-dev/pytest-html/issues/282>`_)
Expand Down
77 changes: 68 additions & 9 deletions pytest_html/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import warnings
from base64 import b64decode
from base64 import b64encode
from collections import defaultdict
from collections import OrderedDict
from functools import lru_cache
from html import escape
Expand Down Expand Up @@ -148,6 +149,7 @@ def __init__(self, logfile, config):
self.rerun = 0 if has_rerun else None
self.self_contained = config.getoption("self_contained_html")
self.config = config
self.reports = defaultdict(list)

class TestResult:
def __init__(self, outcome, report, logfile, config):
Expand Down Expand Up @@ -279,7 +281,12 @@ def append_extra_html(self, extra, extra_index, test_index):
def append_log_html(self, report, additional_html):
log = html.div(class_="log")
if report.longrepr:
for line in report.longreprtext.splitlines():
# longreprtext is only filled out on failure by pytest
# otherwise will be None.
# Use full_text if longreprtext is None-ish
# we added full_text elsewhere in this file.
text = report.longreprtext or report.full_text
for line in text.splitlines():
separator = line.startswith("_ " * 10)
if separator:
log.append(line[:80])
Expand Down Expand Up @@ -620,15 +627,66 @@ def _save_report(self, report_content):
with open(style_path, "w", encoding="utf-8") as f:
f.write(self.style_css)

def _post_process_reports(self):
for test_name, test_reports in self.reports.items():
outcome = "passed"
wasxfail = False
failure_when = None
full_text = ""
extras = []
duration = 0.0

# in theory the last one should have all logs so we just go
# through them all to figure out the outcome, xfail, duration,
# extras, and when it swapped from pass
for test_report in test_reports:
full_text += test_report.longreprtext
extras.extend(getattr(test_report, "extra", []))
duration += getattr(test_report, "duration", 0.0)

if (
test_report.outcome not in ("passed", "rerun")
and outcome == "passed"
):
outcome = test_report.outcome
failure_when = test_report.when

if hasattr(test_report, "wasxfail"):
wasxfail = True

if test_report.outcome == "rerun":
self.append_other(test_report)

# the following test_report.<X> = settings come at the end of us
# looping through all test_reports that make up a single
# case.

# outcome on the right comes from the outcome of the various
# test_reports that make up this test case
# we are just carrying it over to the final report.
test_report.outcome = outcome
test_report.when = "call"
test_report.nodeid = test_name
test_report.longrepr = full_text
test_report.extra = extras
test_report.duration = duration

if wasxfail:
test_report.wasxfail = True

if test_report.outcome == "passed":
self.append_passed(test_report)
elif test_report.outcome == "skipped":
self.append_skipped(test_report)
elif test_report.outcome == "failed":
test_report.when = failure_when
self.append_failed(test_report)

# we don't append other here since the only case supported
# for append_other is rerun, which is handled in the loop above

def pytest_runtest_logreport(self, report):
if report.passed:
self.append_passed(report)
elif report.failed:
self.append_failed(report)
elif report.skipped:
self.append_skipped(report)
else:
self.append_other(report)
self.reports[report.nodeid].append(report)

def pytest_collectreport(self, report):
if report.failed:
Expand All @@ -638,6 +696,7 @@ def pytest_sessionstart(self, session):
self.suite_start_time = time.time()

def pytest_sessionfinish(self, session):
self._post_process_reports()
report_content = self._generate_report(session)
self._save_report(report_content)

Expand Down
56 changes: 56 additions & 0 deletions testing/test_pytest_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -980,3 +980,59 @@ def pytest_html_report_title(report):
result, html = run(testdir)
assert result.ret == 0
assert len(re.findall(content_report_title, html)) == 1

def test_setup_and_teardown_in_html(self, testdir):
testdir.makepyfile(
"""
import pytest
@pytest.fixture(scope="function")
def setupAndTeardown():
print ("this is setup")
yield
print ("this is teardown")
def test_setup_and_teardown(setupAndTeardown):
print ("this is the test case")
"""
)
result, html = run(testdir)
assert result.ret == 0
assert_results(html, tests=1, passed=1)
assert "this is setup" in html
assert "this is teardown" in html
assert "this is the test case" in html

def test_setup_failures_are_errors(self, testdir):
testdir.makepyfile(
"""
import pytest
@pytest.fixture(scope="function")
def setup():
assert 0, "failure!"
def test_setup(setup):
print ("this is the test case")
"""
)
result, html = run(testdir)
assert result.ret == 1
assert_results(html, tests=0, passed=0, errors=1)
assert "this is the test case" not in html

def test_teardown_failures_are_errors(self, testdir):
testdir.makepyfile(
"""
import pytest
@pytest.fixture(scope="function")
def teardown():
yield
assert 0, "failure!"
def test_setup(teardown):
print ("this is the test case")
"""
)
result, html = run(testdir)
assert result.ret == 1
assert_results(html, tests=0, passed=0, errors=1)
assert "this is the test case" in html

0 comments on commit f2d41db

Please sign in to comment.