Drop support for legacy Python 2.7 (#230)

* Drop support for legacy Python 2.7

* Upgrade Python syntax with pyupgrade --py36-plus

* Require pytest 5+, supports only Python 3

* Format with Black
This commit is contained in:
Hugo van Kemenade 2019-09-09 11:10:07 +03:00 committed by Jim Brännlund
parent 1abfe5d590
commit e6e5ef2585
7 changed files with 127 additions and 226 deletions

View File

@ -17,15 +17,6 @@ jobs:
directories:
- $HOME/.cache/pre-commit
-
python: 2.7
env: TOXENV=py27
-
python: 2.7
env: TOXENV=py27-ansi2html
-
python: 3.6
env: TOXENV=py36
@ -45,14 +36,6 @@ jobs:
sudo: required
env: TOXENV=py37-ansi2html
-
python: pypy
env: TOXENV=pypy
-
python: pypy
env: TOXENV=pypy-ansi2html
-
python: pypy3
env: TOXENV=pypy3

View File

@ -28,7 +28,7 @@ Requirements
You will need the following prerequisites in order to use pytest-html:
- Python 2.7, 3.6, PyPy, or PyPy3
- Python 3.6+ or PyPy3
Installation
------------

View File

@ -9,11 +9,7 @@ environment:
- TOXENV: py36-pytest29
PYTHON_HOME: C:\Python36
- TOXENV: flake8
PYTHON_HOME: C:\Python27
- TOXENV: py27-pytest30
PYTHON_HOME: C:\Python27
- TOXENV: py27-pytest29
PYTHON_HOME: C:\Python27
PYTHON_HOME: C:\Python37
install:
- '%PYTHON_HOME%\Scripts\pip --version'
- '%PYTHON_HOME%\Scripts\pip install tox'

View File

@ -2,8 +2,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import absolute_import
from base64 import b64encode, b64decode
from collections import OrderedDict
from os.path import isfile
@ -11,12 +9,13 @@ import datetime
import json
import os
import pkg_resources
import sys
import time
import bisect
import warnings
import re
from html import escape
try:
from ansi2html import Ansi2HTMLConverter, style
@ -30,16 +29,6 @@ from py.xml import html, raw
from . import extras
from . import __version__, __pypi_url__
PY3 = sys.version_info[0] == 3
# Python 2.X and 3.X compatibility
if PY3:
basestring = str
from html import escape
else:
from codecs import open
from cgi import escape
def pytest_addhooks(pluginmanager):
from . import hooks
@ -95,10 +84,10 @@ def pytest_unconfigure(config):
def data_uri(content, mime_type="text/plain", charset="utf-8"):
data = b64encode(content.encode(charset)).decode("ascii")
return "data:{0};charset={1};base64,{2}".format(mime_type, charset, data)
return f"data:{mime_type};charset={charset};base64,{data}"
class HTMLReport(object):
class HTMLReport:
def __init__(self, logfile, config):
logfile = os.path.expanduser(os.path.expandvars(logfile))
self.logfile = os.path.abspath(logfile)
@ -136,7 +125,7 @@ class HTMLReport(object):
cells = [
html.td(self.outcome, class_="col-result"),
html.td(self.test_id, class_="col-name"),
html.td("{0:.2f}".format(self.time), class_="col-duration"),
html.td(f"{self.time:.2f}", class_="col-duration"),
html.td(self.links_html, class_="col-links"),
]
@ -181,7 +170,7 @@ class HTMLReport(object):
if not os.path.exists(os.path.dirname(asset_path)):
os.makedirs(os.path.dirname(asset_path))
relative_path = "{0}/{1}".format("assets", asset_file_name)
relative_path = f"assets/{asset_file_name}"
kwargs = {"encoding": "utf-8"} if "b" not in mode else {}
with open(asset_path, mode, **kwargs) as f:
@ -209,13 +198,10 @@ class HTMLReport(object):
)
html_div = html.a(html.img(src=content), href=content)
elif self.self_contained:
src = "data:{0};base64,{1}".format(extra.get("mime_type"), content)
src = "data:{};base64,{}".format(extra.get("mime_type"), content)
html_div = html.img(src=src)
else:
if PY3:
content = content.encode("utf-8")
content = b64decode(content)
content = b64decode(content.encode("utf-8"))
href = src = self.create_asset(
content, extra_index, test_index, extra.get("extension"), "wb"
)
@ -276,7 +262,7 @@ class HTMLReport(object):
for section in report.sections:
header, content = map(escape, section)
log.append(" {0} ".format(header).center(80, "-"))
log.append(f" {header:-^80} ")
log.append(html.br())
if ANSI:
converter = Ansi2HTMLConverter(inline=False, escaped=False)
@ -296,7 +282,7 @@ class HTMLReport(object):
self.results.insert(index, result)
tbody = html.tbody(
result.row_table,
class_="{0} results-table-row".format(result.outcome.lower()),
class_="{} results-table-row".format(result.outcome.lower()),
)
if result.row_extra is not None:
tbody.append(result.row_extra)
@ -345,9 +331,7 @@ class HTMLReport(object):
self.style_css = pkg_resources.resource_string(
__name__, os.path.join("resources", "style.css")
)
if PY3:
self.style_css = self.style_css.decode("utf-8")
).decode("utf-8")
if ANSI:
ansi_css = [
@ -362,12 +346,12 @@ class HTMLReport(object):
for path in self.config.getoption("css"):
self.style_css += "\n/******************************"
self.style_css += "\n * CUSTOM CSS"
self.style_css += "\n * {}".format(path)
self.style_css += f"\n * {path}"
self.style_css += "\n ******************************/\n\n"
with open(path, "r") as f:
self.style_css += f.read()
css_href = "{0}/{1}".format("assets", "style.css")
css_href = "assets/style.css"
html_css = html.link(href=css_href, rel="stylesheet", type="text/css")
if self.self_contained:
html_css = html.style(raw(self.style_css))
@ -401,12 +385,12 @@ class HTMLReport(object):
name="filter_checkbox",
class_="filter",
hidden="true",
**checkbox_kwargs
**checkbox_kwargs,
)
def generate_summary_item(self):
self.summary_item = html.span(
"{0} {1}".format(self.total, self.label), class_=self.class_html
f"{self.total} {self.label}", class_=self.class_html
)
outcomes = [
@ -422,9 +406,7 @@ class HTMLReport(object):
outcomes.append(Outcome("rerun", self.rerun))
summary = [
html.p(
"{0} tests ran in {1:.2f} seconds. ".format(numtests, suite_time_delta)
),
html.p(f"{numtests} tests ran in {suite_time_delta:.2f} seconds. "),
html.p(
"(Un)check the boxes to filter the results.",
class_="filter",
@ -472,19 +454,17 @@ class HTMLReport(object):
main_js = pkg_resources.resource_string(
__name__, os.path.join("resources", "main.js")
)
if PY3:
main_js = main_js.decode("utf-8")
).decode("utf-8")
body = html.body(
html.script(raw(main_js)),
html.h1(os.path.basename(self.logfile)),
html.p(
"Report generated on {0} at {1} by ".format(
"Report generated on {} at {} by ".format(
generated.strftime("%d-%b-%Y"), generated.strftime("%H:%M:%S")
),
html.a("pytest-html", href=__pypi_url__),
" v{0}".format(__version__),
f" v{__version__}",
),
onLoad="init()",
)
@ -501,12 +481,11 @@ class HTMLReport(object):
doc = html.html(head, body)
unicode_doc = u"<!DOCTYPE html>\n{0}".format(doc.unicode(indent=2))
if PY3:
# Fix encoding issues, e.g. with surrogates
unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace")
unicode_doc = unicode_doc.decode("utf-8")
return unicode_doc
unicode_doc = "<!DOCTYPE html>\n{}".format(doc.unicode(indent=2))
# Fix encoding issues, e.g. with surrogates
unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace")
return unicode_doc.decode("utf-8")
def _generate_environment(self, config):
if not hasattr(config, "_metadata") or config._metadata is None:
@ -522,10 +501,10 @@ class HTMLReport(object):
for key in keys:
value = metadata[key]
if isinstance(value, basestring) and value.startswith("http"):
if isinstance(value, str) and value.startswith("http"):
value = html.a(value, href=value, target="_blank")
elif isinstance(value, (list, tuple, set)):
value = ", ".join((str(i) for i in value))
value = ", ".join(str(i) for i in value)
rows.append(html.tr(html.td(key), html.td(value)))
environment.append(html.table(rows, id="environment"))
@ -569,6 +548,4 @@ class HTMLReport(object):
self._save_report(report_content)
def pytest_terminal_summary(self, terminalreporter):
terminalreporter.write_sep(
"-", "generated html file: file://{0}".format(self.logfile)
)
terminalreporter.write_sep("-", f"generated html file: file://{self.logfile}")

View File

@ -12,9 +12,10 @@ setup(
package_data={"pytest_html": ["resources/*"]},
entry_points={"pytest11": ["html = pytest_html.plugin"]},
setup_requires=["setuptools_scm"],
install_requires=["pytest>=3.0", "pytest-metadata"],
install_requires=["pytest>=5.0", "pytest-metadata"],
license="Mozilla Public License 2.0 (MPL 2.0)",
keywords="py.test pytest html report",
python_requires=">=3.6",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Framework :: Pytest",
@ -27,8 +28,9 @@ setup(
"Topic :: Software Development :: Testing",
"Topic :: Utilities",
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3 :: Only",
],
)

View File

@ -3,17 +3,14 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from base64 import b64encode
from distutils.version import LooseVersion
import json
import os
import sys
import pkg_resources
import random
import re
import pytest
PY3 = sys.version_info[0] == 3
pytest_plugins = ("pytester",)
@ -30,20 +27,19 @@ def read_html(path):
def assert_results_by_outcome(html, test_outcome, test_outcome_number, label=None):
# Asserts if the test number of this outcome in the summary is correct
regex_summary = r"(\d)+ {0}".format(label or test_outcome)
regex_summary = r"(\d)+ {}".format(label or test_outcome)
assert int(re.search(regex_summary, html).group(1)) == test_outcome_number
# Asserts if the generated checkbox of this outcome is correct
regex_checkbox = (
'<input checked="true" class="filter" '
'data-test-result="{0}"'.format(test_outcome)
f'<input checked="true" class="filter" data-test-result="{test_outcome}"'
)
if test_outcome_number == 0:
regex_checkbox += ' disabled="true"'
assert re.search(regex_checkbox, html) is not None
# Asserts if the table rows of this outcome are correct
regex_table = 'tbody class="{0} '.format(test_outcome)
regex_table = f'tbody class="{test_outcome} '
assert len(re.findall(regex_table, html)) == test_outcome_number
@ -85,7 +81,7 @@ class TestHTML:
"""
import time
def test_sleep():
time.sleep({0:f})
time.sleep({:f})
""".format(
sleep * 2
)
@ -106,18 +102,16 @@ class TestHTML:
def test_skip(self, testdir):
reason = str(random.random())
testdir.makepyfile(
"""
f"""
import pytest
def test_skip():
pytest.skip('{0}')
""".format(
reason
)
pytest.skip('{reason}')
"""
)
result, html = run(testdir)
assert result.ret == 0
assert_results(html, tests=0, passed=0, skipped=1)
assert "Skipped: {0}".format(reason) in html
assert f"Skipped: {reason}" in html
def test_fail(self, testdir):
testdir.makepyfile("def test_fail(): assert False")
@ -183,18 +177,16 @@ class TestHTML:
def test_xfail(self, testdir):
reason = str(random.random())
testdir.makepyfile(
"""
f"""
import pytest
def test_xfail():
pytest.xfail('{0}')
""".format(
reason
)
pytest.xfail('{reason}')
"""
)
result, html = run(testdir)
assert result.ret == 0
assert_results(html, passed=0, xfailed=1)
assert "XFailed: {0}".format(reason) in html
assert f"XFailed: {reason}" in html
def test_xpass(self, testdir):
testdir.makepyfile(
@ -223,7 +215,7 @@ class TestHTML:
path = os.path.join(path, report_name)
result, html = run(testdir, path)
assert result.ret == 0
report_title = "<h1>{0}</h1>".format(report_name)
report_title = f"<h1>{report_name}</h1>"
assert report_title in html
def test_report_title_addopts_env_var(self, testdir, monkeypatch):
@ -232,17 +224,15 @@ class TestHTML:
monkeypatch.setenv(report_location, report_name)
testdir.makefile(
".ini",
pytest="""
pytest=f"""
[pytest]
addopts = --html ${0}
""".format(
report_location
),
addopts = --html ${report_location}
""",
)
testdir.makepyfile("def test_pass(): pass")
result = testdir.runpytest()
assert result.ret == 0
report_title = "<h1>{0}</h1>".format(report_name)
report_title = f"<h1>{report_name}</h1>"
assert report_title in read_html(report_name)
def test_resources_inline_css(self, testdir):
@ -253,8 +243,7 @@ class TestHTML:
content = pkg_resources.resource_string(
"pytest_html", os.path.join("resources", "style.css")
)
if PY3:
content = content.decode("utf-8")
content = content.decode("utf-8")
assert content
assert content in html
@ -266,8 +255,7 @@ class TestHTML:
content = pkg_resources.resource_string(
"pytest_html", os.path.join("resources", "main.js")
)
if PY3:
content = content.decode("utf-8")
content = content.decode("utf-8")
assert content
assert content in html
regex_css_link = '<link href="assets/style.css" rel="stylesheet"'
@ -278,12 +266,10 @@ class TestHTML:
content = "<spam>ham</spam>"
escaped = "&lt;spam&gt;ham&lt;/spam&gt;"
testdir.makepyfile(
"""
f"""
def test_stdout():
print('{0}')
assert '{1}' == 'pass'""".format(
content, result
)
print('{content}')
assert f'{result}' == 'pass'"""
)
_, html = run(testdir)
assert content not in html
@ -294,17 +280,15 @@ class TestHTML:
content_summary = str(random.random())
content_suffix = str(random.random())
testdir.makeconftest(
"""
f"""
import pytest
from py.xml import html
def pytest_html_results_summary(prefix, summary, postfix):
prefix.append(html.p("prefix is {0}"))
summary.extend([html.p("extra summary is {1}")])
postfix.extend([html.p("postfix is {2}")])
""".format(
content_prefix, content_summary, content_suffix
)
prefix.append(html.p("prefix is {content_prefix}"))
summary.extend([html.p("extra summary is {content_summary}")])
postfix.extend([html.p("postfix is {content_suffix}")])
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
@ -316,7 +300,7 @@ class TestHTML:
def test_extra_html(self, testdir):
content = str(random.random())
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -324,10 +308,8 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.html('<div>{0}</div>')]
""".format(
content
)
report.extra = [extras.html('<div>{content}</div>')]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
@ -340,7 +322,7 @@ class TestHTML:
)
def test_extra_text(self, testdir, content, encoded):
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -348,22 +330,20 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.text({0})]
""".format(
content
)
report.extra = [extras.text({content})]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir, "report.html", "--self-contained-html")
assert result.ret == 0
href = "data:text/plain;charset=utf-8;base64,{0}".format(encoded)
link = '<a class="text" href="{0}" target="_blank">Text</a>'.format(href)
href = f"data:text/plain;charset=utf-8;base64,{encoded}"
link = f'<a class="text" href="{href}" target="_blank">Text</a>'
assert link in html
def test_extra_json(self, testdir):
content = {str(random.random()): str(random.random())}
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -371,27 +351,22 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.json({0})]
""".format(
content
)
report.extra = [extras.json({content})]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir, "report.html", "--self-contained-html")
assert result.ret == 0
content_str = json.dumps(content)
if PY3:
data = b64encode(content_str.encode("utf-8")).decode("ascii")
else:
data = b64encode(content_str)
href = "data:application/json;charset=utf-8;base64,{0}".format(data)
link = '<a class="json" href="{0}" target="_blank">JSON</a>'.format(href)
data = b64encode(content_str.encode("utf-8")).decode("ascii")
href = f"data:application/json;charset=utf-8;base64,{data}"
link = f'<a class="json" href="{href}" target="_blank">JSON</a>'
assert link in html
def test_extra_url(self, testdir):
content = str(random.random())
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -399,15 +374,13 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.url('{0}')]
""".format(
content
)
report.extra = [extras.url('{content}')]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
assert result.ret == 0
link = '<a class="url" href="{0}" target="_blank">URL</a>'.format(content)
link = f'<a class="url" href="{content}" target="_blank">URL</a>'
assert link in html
@pytest.mark.parametrize(
@ -422,7 +395,7 @@ class TestHTML:
def test_extra_image(self, testdir, mime_type, extension):
content = str(random.random())
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -430,16 +403,14 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.{0}('{1}')]
""".format(
extension, content
)
report.extra = [extras.{extension}('{content}')]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir, "report.html", "--self-contained-html")
assert result.ret == 0
src = "data:{0};base64,{1}".format(mime_type, content)
assert '<img src="{0}"/>'.format(src) in html
src = f"data:{mime_type};base64,{content}"
assert f'<img src="{src}"/>' in html
def test_extra_image_windows(self, mocker, testdir):
mock_isfile = mocker.patch("pytest_html.plugin.isfile")
@ -452,7 +423,7 @@ class TestHTML:
)
def test_extra_text_separated(self, testdir, content):
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -460,16 +431,14 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.text({0})]
""".format(
content
)
report.extra = [extras.text({content})]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
assert result.ret == 0
src = "assets/test_extra_text_separated.py__test_pass_0_0.txt"
link = '<a class="text" href="{0}" target="_blank">'.format(src)
link = f'<a class="text" href="{src}" target="_blank">'
assert link in html
assert os.path.exists(src)
@ -478,9 +447,9 @@ class TestHTML:
[("png", "image"), ("png", "png"), ("svg", "svg"), ("jpg", "jpg")],
)
def test_extra_image_separated(self, testdir, file_extension, extra_type):
content = b64encode("foo".encode("utf-8")).decode("ascii")
content = b64encode(b"foo").decode("ascii")
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -488,18 +457,14 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.{0}('{1}')]
""".format(
extra_type, content
)
report.extra = [extras.{extra_type}('{content}')]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
assert result.ret == 0
src = "assets/test_extra_image_separated.py__test_pass_0_0.{}".format(
file_extension
)
link = '<a class="image" href="{0}" target="_blank">'.format(src)
src = f"assets/test_extra_image_separated.py__test_pass_0_0.{file_extension}"
link = f'<a class="image" href="{src}" target="_blank">'
assert link in html
assert os.path.exists(src)
@ -508,9 +473,9 @@ class TestHTML:
[("png", "image"), ("png", "png"), ("svg", "svg"), ("jpg", "jpg")],
)
def test_extra_image_separated_rerun(self, testdir, file_extension, extra_type):
content = b64encode("foo".encode("utf-8")).decode("ascii")
content = b64encode(b"foo").decode("ascii")
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -518,10 +483,8 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.{0}('{1}')]
""".format(
extra_type, content
)
report.extra = [extras.{extra_type}('{content}')]
"""
)
testdir.makepyfile(
"""
@ -534,8 +497,8 @@ class TestHTML:
for i in range(1, 4):
asset_name = "test_extra_image_separated_rerun.py__test_fail"
src = "assets/{}_0_{}.{}".format(asset_name, i, file_extension)
link = '<a class="image" href="{0}" target="_blank">'.format(src)
src = f"assets/{asset_name}_0_{i}.{file_extension}"
link = f'<a class="image" href="{src}" target="_blank">'
assert result.ret
assert link in html
assert os.path.exists(src)
@ -544,7 +507,7 @@ class TestHTML:
def test_extra_image_non_b64(self, testdir, src_type):
content = src_type
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
@ -552,10 +515,8 @@ class TestHTML:
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.image('{0}')]
""".format(
content
)
report.extra = [extras.image('{content}')]
"""
)
testdir.makepyfile("def test_pass(): pass")
if src_type == "image.png":
@ -580,17 +541,15 @@ class TestHTML:
# This will get truncated
test_name = "test_{}".format("a" * 300)
testdir.makepyfile(
"""
def {0}():
f"""
def {test_name}():
assert False
""".format(
test_name
)
"""
)
result, html = run(testdir)
file_name = "test_very_long_test_name.py__{}_0_0.png".format(test_name)[-255:]
file_name = f"test_very_long_test_name.py__{test_name}_0_0.png"[-255:]
src = "assets/" + file_name
link = '<a class="image" href="{0}" target="_blank">'.format(src)
link = f'<a class="image" href="{src}" target="_blank">'
assert result.ret
assert link in html
assert os.path.exists(src)
@ -633,12 +592,10 @@ class TestHTML:
def test_environment(self, testdir):
content = str(random.random())
testdir.makeconftest(
"""
f"""
def pytest_configure(config):
config._metadata['content'] = '{0}'
""".format(
content
)
config._metadata['content'] = '{content}'
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
@ -649,13 +606,11 @@ class TestHTML:
def test_environment_xdist(self, testdir):
content = str(random.random())
testdir.makeconftest(
"""
f"""
def pytest_configure(config):
for i in range(2):
config._metadata['content'] = '{0}'
""".format(
content
)
config._metadata['content'] = '{content}'
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir, "report.html", "-n", "1")
@ -666,13 +621,11 @@ class TestHTML:
def test_environment_xdist_reruns(self, testdir):
content = str(random.random())
testdir.makeconftest(
"""
f"""
def pytest_configure(config):
for i in range(2):
config._metadata['content'] = '{0}'
""".format(
content
)
config._metadata['content'] = '{content}'
"""
)
testdir.makepyfile("def test_fail(): assert False")
result, html = run(testdir, "report.html", "-n", "1", "--reruns", "1")
@ -683,16 +636,14 @@ class TestHTML:
def test_environment_list_value(self, testdir):
content = tuple(str(random.random()) for i in range(10))
content += tuple(random.random() for i in range(10))
expected_content = ", ".join((str(i) for i in content))
expected_html_re = r"<td>content</td>\n\s+<td>{}</td>".format(expected_content)
expected_content = ", ".join(str(i) for i in content)
expected_html_re = fr"<td>content</td>\n\s+<td>{expected_content}</td>"
testdir.makeconftest(
"""
f"""
def pytest_configure(config):
for i in range(2):
config._metadata['content'] = {0}
""".format(
content
)
config._metadata['content'] = {content}
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir)
@ -714,12 +665,6 @@ class TestHTML:
assert "Environment" in html
assert len(re.findall("ZZZ.+AAA", html, re.DOTALL)) == 1
@pytest.mark.xfail(
sys.version_info < (3, 2)
and LooseVersion(pytest.__version__) >= LooseVersion("2.8.0"),
reason="Fails on earlier versions of Python and pytest",
run=False,
)
def test_xdist_crashing_slave(self, testdir):
"""https://github.com/pytest-dev/pytest-html/issues/21"""
testdir.makepyfile(
@ -779,17 +724,15 @@ class TestHTML:
@pytest.mark.parametrize("content", [("'foo'"), ("u'\u0081'")])
def test_utf8_longrepr(self, testdir, content):
testdir.makeconftest(
"""
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
if report.when == 'call':
report.longrepr = 'utf8 longrepr: ' + {0}
""".format(
content
)
report.longrepr = 'utf8 longrepr: ' + {content}
"""
)
testdir.makepyfile(
"""
@ -821,7 +764,7 @@ class TestHTML:
css = {}
cssargs = []
for color in colors:
style = "* {{color: {}}}".format(color)
style = f"* {{color: {color}}}"
path = testdir.makefile(".css", **{color: style})
css[color] = {"style": style, "path": path}
cssargs.extend(["--css", path])

View File

@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
envlist = py{27,36,37,py,py3}{,-ansi2html}, linting
envlist = py{36,37,py3}{,-ansi2html}, linting
[testenv]
setenv = PYTHONDONTWRITEBYTECODE=1
@ -12,7 +12,7 @@ deps =
pytest-xdist
pytest-rerunfailures
pytest-mock
py{27,36,py,py3}-ansi2html: ansi2html
py{36,37,py3}-ansi2html: ansi2html
commands = pytest -v -r a {posargs}
[testenv:linting]