Skip to content

Commit 5e4950b

Browse files
authored
Allow for redacting of environment table values (#431)
* Add untested change * Add tests * Add documentation * Add the changelog entry * remove debug code from test * Change wording of documentation
1 parent cc80986 commit 5e4950b

File tree

5 files changed

+92
-2
lines changed

5 files changed

+92
-2
lines changed

docs/changelog.rst

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Version History
1717

1818
* Thanks to `@gnikonorov <https://github.com/gnikonorov>`_ for the PR
1919

20+
* Implement :code:`environment_table_redact_list` to allow for redaction of environment table values. (`#233 <https://github.com/pytest-dev/pytest-html/issues/233>`_)
21+
22+
* Thanks to `@fenchu <https://github.com/fenchu>`_ for reporting and `@gnikonorov <https://github.com/gnikonorov>`_ for the PR
23+
2024
3.1.1 (2020-12-13)
2125
~~~~~~~~~~~~~~~~~~
2226

docs/user_guide.rst

+14-2
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,20 @@ Note that in the above example `@pytest.hookimpl(tryfirst=True)`_ is important,
8080
If this line is omitted, then the *Environment* table will **not** be updated since the :code:`pytest_sessionfinish` of the plugins will execute first,
8181
and thus not pick up your change.
8282

83-
The generated table will be sorted alphabetically unless the metadata is a
84-
:code:`collections.OrderedDict`.
83+
The generated table will be sorted alphabetically unless the metadata is a :code:`collections.OrderedDict`.
84+
85+
It is possible to redact variables from the environment table. Redacted variables will have their names displayed, but their values grayed out.
86+
This can be achieved by setting :code:`environment_table_redact_list` in your INI configuration file (e.g.: :code:`pytest.ini`).
87+
:code:`environment_table_redact_list` is a :code:`linelist` of regexes. Any environment table variable that matches a regex in this list has its value redacted.
88+
89+
For example, the following will redact all environment table variables that match the regexes :code:`^foo$`, :code:`.*redact.*`, or :code:`bar`:
90+
91+
.. code-block:: ini
92+
93+
[pytest]
94+
environment_table_redact_list = ^foo$
95+
.*redact.*
96+
bar
8597
8698
Additional summary information
8799
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/pytest_html/html_report.py

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import datetime
33
import json
44
import os
5+
import re
56
import time
67
from collections import defaultdict
78
from collections import OrderedDict
@@ -226,6 +227,10 @@ def _generate_environment(self, config):
226227

227228
for key in keys:
228229
value = metadata[key]
230+
if self._is_redactable_environment_variable(key, config):
231+
black_box_ascii_value = 0x2593
232+
value = "".join(chr(black_box_ascii_value) for char in str(value))
233+
229234
if isinstance(value, str) and value.startswith("http"):
230235
value = html.a(value, href=value, target="_blank")
231236
elif isinstance(value, (list, tuple, set)):
@@ -239,6 +244,14 @@ def _generate_environment(self, config):
239244
environment.append(html.table(rows, id="environment"))
240245
return environment
241246

247+
def _is_redactable_environment_variable(self, environment_variable, config):
248+
redactable_regexes = config.getini("environment_table_redact_list")
249+
for redactable_regex in redactable_regexes:
250+
if re.match(redactable_regex, environment_variable):
251+
return True
252+
253+
return False
254+
242255
def _save_report(self, report_content):
243256
dir_name = os.path.dirname(self.logfile)
244257
assets_dir = os.path.join(dir_name, "assets")

src/pytest_html/plugin.py

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ def pytest_addoption(parser):
5353
help="set the maximum filename length for assets "
5454
"attached to the html report.",
5555
)
56+
parser.addini(
57+
"environment_table_redact_list",
58+
type="linelist",
59+
help="A list of regexes corresponding to environment "
60+
"table variables whose values should be redacted from the report",
61+
)
5662

5763

5864
def pytest_configure(config):

testing/test_pytest_html.py

+55
Original file line numberDiff line numberDiff line change
@@ -1209,3 +1209,58 @@ def test_show_capture_no():
12091209
assert extra_log_div_regex.search(html) is not None
12101210
else:
12111211
assert extra_log_div_regex.search(html) is None
1212+
1213+
def test_environment_table_redact_list(self, testdir):
1214+
testdir.makeini(
1215+
"""
1216+
[pytest]
1217+
environment_table_redact_list = ^foo$
1218+
.*redact.*
1219+
bar
1220+
"""
1221+
)
1222+
1223+
testdir.makeconftest(
1224+
"""
1225+
def pytest_configure(config):
1226+
config._metadata["foo"] = "will not appear a"
1227+
config._metadata["afoo"] = "will appear"
1228+
config._metadata["foos"] = "will appear"
1229+
config._metadata["redact"] = "will not appear ab"
1230+
config._metadata["will_redact"] = "will not appear abc"
1231+
config._metadata["redacted_item"] = "will not appear abcd"
1232+
config._metadata["unrelated_item"] = "will appear"
1233+
config._metadata["bar"] = "will not appear abcde"
1234+
config._metadata["bars"] = "will not appear abcdef"
1235+
"""
1236+
)
1237+
1238+
testdir.makepyfile(
1239+
"""
1240+
def test_pass():
1241+
assert True
1242+
"""
1243+
)
1244+
1245+
result, html = run(testdir)
1246+
assert result.ret == 0
1247+
assert_results(html)
1248+
1249+
black_box_ascii_value = 0x2593
1250+
expected_environment_values = {
1251+
"foo": "".join(chr(black_box_ascii_value) for value in range(17)),
1252+
"afoo": "will appear",
1253+
"foos": "will appear",
1254+
"redact": "".join(chr(black_box_ascii_value) for value in range(18)),
1255+
"will_redact": "".join(chr(black_box_ascii_value) for value in range(19)),
1256+
"redacted_item": "".join(chr(black_box_ascii_value) for value in range(20)),
1257+
"unrelated_item": "will appear",
1258+
"bar": "".join(chr(black_box_ascii_value) for value in range(21)),
1259+
"bars": "".join(chr(black_box_ascii_value) for value in range(22)),
1260+
}
1261+
for variable in expected_environment_values:
1262+
variable_value = expected_environment_values[variable]
1263+
variable_value_regex = re.compile(
1264+
f"<tr>\n.*<td>{variable}</td>\n.*<td>{variable_value}</td></tr>"
1265+
)
1266+
assert variable_value_regex.search(html) is not None

0 commit comments

Comments
 (0)