Skip to content

Commit

Permalink
test: really parse HTML reports to make assertions about the rendered…
Browse files Browse the repository at this point in the history
… text
  • Loading branch information
nedbat committed Aug 27, 2024
1 parent 2afe04d commit 9494ba7
Showing 1 changed file with 53 additions and 3 deletions.
56 changes: 53 additions & 3 deletions tests/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import re
import sys

from unittest import mock
from html.parser import HTMLParser
from typing import Any, IO
from unittest import mock

import pytest

Expand Down Expand Up @@ -94,6 +95,12 @@ def get_html_index_content(self) -> str:
)
return index

def get_html_report_text_lines(self, module: str) -> list[str]:
"""Parse the HTML report, and return a list of strings, the text rendered."""
parser = HtmlReportParser()
parser.feed(self.get_html_report_content(module))
return parser.text()

def assert_correct_timestamp(self, html: str) -> None:
"""Extract the time stamp from `html`, and assert it is recent."""
timestamp_pat = r"created at (\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})"
Expand Down Expand Up @@ -133,6 +140,43 @@ def assert_valid_hrefs(self, directory: str = "htmlcov") -> None:
)


class HtmlReportParser(HTMLParser): # pylint: disable=abstract-method
"""An HTML parser for our HTML reports.
Assertions are made about the structure we expect.
"""
def __init__(self) -> None:
super().__init__()
self.lines: list[list[str]] = []
self.in_source = False

def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
if tag == "main":
assert attrs == [("id", "source")]
self.in_source = True
elif self.in_source and tag == "a":
dattrs = dict(attrs)
assert "id" in dattrs
ida = dattrs["id"]
assert ida is not None
assert ida[0] == "t"
line_no = int(ida[1:])
self.lines.append([])
assert line_no == len(self.lines)

def handle_endtag(self, tag: str) -> None:
if tag == "main":
self.in_source = False

def handle_data(self, data: str) -> None:
if self.in_source and self.lines:
self.lines[-1].append(data)

def text(self) -> list[str]:
"""Get the rendered text as a list of strings, one per line."""
return ["".join(l).rstrip() for l in self.lines]


class FileWriteTracker:
"""A fake object to track how `open` is used to write files."""
def __init__(self, written: set[str]) -> None:
Expand Down Expand Up @@ -1141,10 +1185,10 @@ def test_bug_1828(self) -> None:

cov = coverage.Coverage()
backslashes = self.start_import_stop(cov, "backslashes")
cov.html_report(backslashes, directory="out")
cov.html_report(backslashes)

contains(
"out/backslashes_py.html",
"htmlcov/backslashes_py.html",
# line 2 is `"bbb \`
r'<a id="t2" href="#t2">2</a></span>'
+ r'<span class="t"> <span class="str">"bbb \</span>',
Expand All @@ -1153,6 +1197,12 @@ def test_bug_1828(self) -> None:
+ r'<span class="t"><span class="str"> ccc"</span><span class="op">]</span>',
)

assert self.get_html_report_text_lines("backslashes.py") == [
'1a = ["aaa",\\',
'2 "bbb \\',
'3 ccc"]',
]

def test_unicode(self) -> None:
surrogate = "\U000e0100"

Expand Down

0 comments on commit 9494ba7

Please sign in to comment.