diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 57649250..b3ce5fdf 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -261,6 +261,21 @@ or by setting the :code:`render_collapsed` in a configuration file (pytest.ini, **NOTE:** Setting :code:`render_collapsed` will, unlike the query parameter, affect all statuses. + +Keep original test cases run order +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, all rows in the **Results** table will be sorted by category. Failed test cases will be placed at the top of the **Results** table. + +This behavior can be customized by setting the :code:`keep_original_order` in a configuration file (pytest.ini, setup.cfg, etc). + +.. code-block:: ini + + [pytest] + keep_original_order = True + +**NOTE:** Setting :code:`keep_original_order` will turn off a possibility of changing order by table headers. + Controlling Test Result Visibility Via Query Params ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/pytest_html/html_report.py b/src/pytest_html/html_report.py index 66e10f07..09e660eb 100644 --- a/src/pytest_html/html_report.py +++ b/src/pytest_html/html_report.py @@ -36,15 +36,20 @@ def __init__(self, logfile, config): def _appendrow(self, outcome, report): result = TestResult(outcome, report, self.logfile, self.config) if result.row_table is not None: - index = bisect.bisect_right(self.results, result) - self.results.insert(index, result) tbody = html.tbody( result.row_table, class_="{} results-table-row".format(result.outcome.lower()), ) if result.row_extra is not None: tbody.append(result.row_extra) - self.test_logs.insert(index, tbody) + + if self.config.getini("keep_original_order"): + self.results.append(result) + self.test_logs.append(tbody) + else: + index = bisect.bisect_right(self.results, result) + self.results.insert(index, result) + self.test_logs.insert(index, tbody) def append_passed(self, report): if report.when == "call": @@ -145,11 +150,21 @@ def _generate_report(self, session): if i < len(outcomes): summary.append(", ") + sortable_class_attrib = "sortable" + initial_sort_class_attrib = "initial-sort" + if self.config.getini("keep_original_order"): + sortable_class_attrib = "" + initial_sort_class_attrib = "" + cells = [ - html.th("Result", class_="sortable result initial-sort", col="result"), - html.th("Test", class_="sortable", col="name"), - html.th("Duration", class_="sortable", col="duration"), - html.th("Links", class_="sortable links", col="links"), + html.th( + "Result", + class_=f"{sortable_class_attrib} result {initial_sort_class_attrib}", + col="result", + ), + html.th("Test", class_=f"{sortable_class_attrib}", col="name"), + html.th("Duration", class_=f"{sortable_class_attrib}", col="duration"), + html.th("Links", class_=f"{sortable_class_attrib} links", col="links"), ] session.config.hook.pytest_html_results_table_header(cells=cells) diff --git a/src/pytest_html/plugin.py b/src/pytest_html/plugin.py index 0034da19..80c74488 100644 --- a/src/pytest_html/plugin.py +++ b/src/pytest_html/plugin.py @@ -59,6 +59,13 @@ def pytest_addoption(parser): help="A list of regexes corresponding to environment " "table variables whose values should be redacted from the report", ) + parser.addini( + "keep_original_order", + type="bool", + default=False, + help="Keep original order of test cases run in report. " + "That option turns off a possibility of order rows by table headers.", + ) def pytest_configure(config): diff --git a/testing/test_pytest_html.py b/testing/test_pytest_html.py index b13dd4c6..1157d888 100644 --- a/testing/test_pytest_html.py +++ b/testing/test_pytest_html.py @@ -1095,6 +1095,123 @@ def test_pass(): assert len(re.findall(collapsed_html, html)) == expected_count assert_results(html, tests=2, passed=1, failed=1) + @pytest.mark.parametrize( + "keep_original_order, expected_table_header_tag", + [ + ( + False, + [ + {"html_tag": '