From 1ce234dc783c92e8ffc70c726c2fb109573c0461 Mon Sep 17 00:00:00 2001 From: Fabian Sturm Date: Wed, 1 Nov 2023 15:41:46 +0100 Subject: [PATCH 01/14] Add summary for xfails with -rxX option --- src/_pytest/terminal.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index ea26d9368dc..7a8839afb60 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -878,8 +878,10 @@ def pytest_sessionfinish( def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() self.summary_failures() + self.summary_xfailures() self.summary_warnings() self.summary_passes() + self.summary_xpasses() try: return (yield) finally: @@ -1022,6 +1024,20 @@ def summary_passes(self) -> None: self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) + def summary_xpasses(self) -> None: + if self.config.option.tbstyle != "no": + if self.hasopt("X"): + reports: List[TestReport] = self.getreports("xpassed") + if not reports: + return + self.write_sep("=", "XPASSES") + for rep in reports: + if rep.sections: + msg = self._getfailureheadline(rep) + self.write_sep("_", msg, green=True, bold=True) + self._outrep_summary(rep) + self._handle_teardown_sections(rep.nodeid) + def _get_teardown_reports(self, nodeid: str) -> List[TestReport]: reports = self.getreports("") return [ @@ -1064,6 +1080,25 @@ def summary_failures(self) -> None: self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) + def summary_xfailures(self) -> None: + if self.config.option.tbstyle != "no": + if self.hasopt("x"): + reports: List[BaseReport] = self.getreports("xfailed") + if not reports: + return + self.write_sep("=", "XFAILURES") + if self.config.option.tbstyle == "line": + for rep in reports: + line = self._getcrashline(rep) + self.write_line(line) + else: + for rep in reports: + msg = self._getfailureheadline(rep) + self.write_sep("_", msg, red=True, bold=True) + self._outrep_summary(rep) + self._handle_teardown_sections(rep.nodeid) + + def summary_errors(self) -> None: if self.config.option.tbstyle != "no": reports: List[BaseReport] = self.getreports("error") From 0cd183dc0a1938fc2b7c0c5e1f32685bfdf4cb67 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:03:27 +0000 Subject: [PATCH 02/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/terminal.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 7a8839afb60..16a484dc18c 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1098,7 +1098,6 @@ def summary_xfailures(self) -> None: self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) - def summary_errors(self) -> None: if self.config.option.tbstyle != "no": reports: List[BaseReport] = self.getreports("error") From b247f574a3e2fb9209ab17cf220c87639402c539 Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Fri, 22 Dec 2023 19:10:14 -0800 Subject: [PATCH 03/14] Slight tweak to xfail summary, and added tests --- test_xfail.py | 21 +++++++++++++++++++++ venv/pyvenv.cfg | 6 ++++++ xfail/pyproject.toml | 3 +++ xfail/test_xfail.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 test_xfail.py create mode 100644 venv/pyvenv.cfg create mode 100644 xfail/pyproject.toml create mode 100644 xfail/test_xfail.py diff --git a/test_xfail.py b/test_xfail.py new file mode 100644 index 00000000000..53cd13bf73d --- /dev/null +++ b/test_xfail.py @@ -0,0 +1,21 @@ +import pytest + +def test_pass(): + ... + + +def test_fail(): + a,b = 1,2 + assert a == b + +@pytest.mark.xfail +def test_xfail(): + a,b = 1,2 + assert a == b + + +@pytest.mark.xfail +def test_xpass(): + a,b = 1,1 + assert a == b + diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg new file mode 100644 index 00000000000..df2e9449154 --- /dev/null +++ b/venv/pyvenv.cfg @@ -0,0 +1,6 @@ +home = /Library/Frameworks/Python.framework/Versions/3.11/bin +include-system-site-packages = false +version = 3.11.5 +prompt = 'pytest' +executable = /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 +command = /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m venv --prompt="." /Users/okken/projects/pytest/venv diff --git a/xfail/pyproject.toml b/xfail/pyproject.toml new file mode 100644 index 00000000000..81a978dc6c4 --- /dev/null +++ b/xfail/pyproject.toml @@ -0,0 +1,3 @@ +[tool.pytest.ini_options] +addopts = "-ra --strict-markers" +#xfail_strict = true diff --git a/xfail/test_xfail.py b/xfail/test_xfail.py new file mode 100644 index 00000000000..2bf9d58405d --- /dev/null +++ b/xfail/test_xfail.py @@ -0,0 +1,30 @@ +import pytest + +def test_pass(): + print('in test_pass') + + +def test_fail(): + print('in test_fail') + a,b = 1,2 + assert a == b + +@pytest.mark.xfail +def test_xfail(): + print('in test_xfail') + a,b = 1,2 + assert a == b + +@pytest.mark.xfail(reason="reason 1") +def test_xfail_reason(): + print('in test_xfail') + a,b = 1,2 + assert a == b + + +@pytest.mark.xfail(reason="reason 2") +def test_xpass(): + print('in test_xpass') + a,b = 1,1 + assert a == b + From e6aa406c876141b3a8b4ce11442f92236ccda03c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 23 Dec 2023 03:11:10 +0000 Subject: [PATCH 04/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test_xfail.py | 17 +++++++++-------- xfail/test_xfail.py | 30 ++++++++++++++++-------------- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/test_xfail.py b/test_xfail.py index 53cd13bf73d..c99f51d0081 100644 --- a/test_xfail.py +++ b/test_xfail.py @@ -1,21 +1,22 @@ import pytest + def test_pass(): - ... + ... def test_fail(): - a,b = 1,2 - assert a == b + a, b = 1, 2 + assert a == b + @pytest.mark.xfail def test_xfail(): - a,b = 1,2 - assert a == b + a, b = 1, 2 + assert a == b @pytest.mark.xfail def test_xpass(): - a,b = 1,1 - assert a == b - + a, b = 1, 1 + assert a == b diff --git a/xfail/test_xfail.py b/xfail/test_xfail.py index 2bf9d58405d..46d24dd5f56 100644 --- a/xfail/test_xfail.py +++ b/xfail/test_xfail.py @@ -1,30 +1,32 @@ import pytest + def test_pass(): - print('in test_pass') + print("in test_pass") def test_fail(): - print('in test_fail') - a,b = 1,2 - assert a == b + print("in test_fail") + a, b = 1, 2 + assert a == b + @pytest.mark.xfail def test_xfail(): - print('in test_xfail') - a,b = 1,2 - assert a == b + print("in test_xfail") + a, b = 1, 2 + assert a == b + @pytest.mark.xfail(reason="reason 1") def test_xfail_reason(): - print('in test_xfail') - a,b = 1,2 - assert a == b + print("in test_xfail") + a, b = 1, 2 + assert a == b @pytest.mark.xfail(reason="reason 2") def test_xpass(): - print('in test_xpass') - a,b = 1,1 - assert a == b - + print("in test_xpass") + a, b = 1, 1 + assert a == b From a5d36c1440ac500af308d076c5bf917fde2b3b22 Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:30:58 -0800 Subject: [PATCH 05/14] summary changes + testing for xfail and xpass --- src/_pytest/terminal.py | 45 ++++++++++++++-- testing/test_terminal.py | 114 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index ea26d9368dc..3278e88be06 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -878,8 +878,10 @@ def pytest_sessionfinish( def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() self.summary_failures() + self.summary_xfailures() self.summary_warnings() self.summary_passes() + self.summary_xpasses() try: return (yield) finally: @@ -1022,6 +1024,20 @@ def summary_passes(self) -> None: self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) + def summary_xpasses(self) -> None: + if self.config.option.tbstyle != "no": + if self.hasopt("X"): + reports: List[TestReport] = self.getreports("xpassed") + if not reports: + return + self.write_sep("=", "XPASSES") + for rep in reports: + if rep.sections: + msg = self._getfailureheadline(rep) + self.write_sep("_", msg, green=True, bold=True) + self._outrep_summary(rep) + self._handle_teardown_sections(rep.nodeid) + def _get_teardown_reports(self, nodeid: str) -> List[TestReport]: reports = self.getreports("") return [ @@ -1064,6 +1080,24 @@ def summary_failures(self) -> None: self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) + def summary_xfailures(self) -> None: + if self.config.option.tbstyle != "no": + if self.hasopt("x"): + reports: List[BaseReport] = self.getreports("xfailed") + if not reports: + return + self.write_sep("=", "XFAILURES") + if self.config.option.tbstyle == "line": + for rep in reports: + line = self._getcrashline(rep) + self.write_line(line) + else: + for rep in reports: + msg = self._getfailureheadline(rep) + self.write_sep("_", msg, red=True, bold=True) + self._outrep_summary(rep) + self._handle_teardown_sections(rep.nodeid) + def summary_errors(self) -> None: if self.config.option.tbstyle != "no": reports: List[BaseReport] = self.getreports("error") @@ -1152,8 +1186,10 @@ def show_xfailed(lines: List[str]) -> None: markup_word = self._tw.markup( verbose_word, **{_color_for_type["warnings"]: True} ) - nodeid = _get_node_id_with_markup(self._tw, self.config, rep) - line = f"{markup_word} {nodeid}" + color = _color_for_type.get("xfailed", _color_for_type_default) + line = _get_line_with_reprcrash_message( + self.config, rep, self._tw, {color: True} + ) reason = rep.wasxfail if reason: line += " - " + str(reason) @@ -1168,8 +1204,11 @@ def show_xpassed(lines: List[str]) -> None: verbose_word, **{_color_for_type["warnings"]: True} ) nodeid = _get_node_id_with_markup(self._tw, self.config, rep) + line = f"{markup_word} {nodeid}" reason = rep.wasxfail - lines.append(f"{markup_word} {nodeid} {reason}") + if reason: + line += " - " + str(reason) + lines.append(line) def show_skipped(lines: List[str]) -> None: skipped: List[CollectReport] = self.stats.get("skipped", []) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 80958f2107f..4f8d449e7c7 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2614,3 +2614,117 @@ def test_format_trimmed() -> None: assert _format_trimmed(" ({}) ", msg, len(msg) + 4) == " (unconditional skip) " assert _format_trimmed(" ({}) ", msg, len(msg) + 3) == " (unconditional ...) " + + +def test_summary_xfail_reason(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + assert False + + @pytest.mark.xfail(reason="foo") + def test_xfail_reason(): + assert False + """ + ) + result = pytester.runpytest("-rx") + expect1 = "XFAIL test_summary_xfail_reason.py::test_xfail - assert False" + expect2 = "XFAIL test_summary_xfail_reason.py::test_xfail_reason - assert False - foo" + result.stdout.fnmatch_lines([expect1, expect2]) + assert result.stdout.lines.count(expect1) == 1 + assert result.stdout.lines.count(expect2) == 1 + + +def test_summary_xfail_tb(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + a, b = 1, 2 + assert a == b + """ + ) + result = pytester.runpytest("-rx") + result.stdout.fnmatch_lines([ + "*= XFAILURES =*", + "*_ test_xfail _*", + "* @pytest.mark.xfail*", + "* def test_xfail():*", + "* a, b = 1, 2*", + "> *assert a == b*", + "E *assert 1 == 2*", + "test_summary_xfail_tb.py:6: AssertionError*", + "*= short test summary info =*", + "XFAIL test_summary_xfail_tb.py::test_xfail - assert 1 == 2", + "*= 1 xfailed in * =*" + ]) + + +def test_xfail_tb_line(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + a, b = 1, 2 + assert a == b + """ + ) + result = pytester.runpytest("-rx", "--tb=line") + result.stdout.fnmatch_lines([ + "*= XFAILURES =*", + "*test_xfail_tb_line.py:6: assert 1 == 2", + "*= short test summary info =*", + "XFAIL test_xfail_tb_line.py::test_xfail - assert 1 == 2", + "*= 1 xfailed in * =*" + ]) + + +def test_summary_xpass_reason(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_pass(): + ... + + @pytest.mark.xfail(reason="foo") + def test_reason(): + ... + """ + ) + result = pytester.runpytest("-rX") + expect1 = "XPASS test_summary_xpass_reason.py::test_pass" + expect2 = "XPASS test_summary_xpass_reason.py::test_reason - foo" + result.stdout.fnmatch_lines([expect1, expect2]) + assert result.stdout.lines.count(expect1) == 1 + assert result.stdout.lines.count(expect2) == 1 + + +def test_xpass_output(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_pass(): + print('hi there') + """ + ) + result = pytester.runpytest("-rX") + result.stdout.fnmatch_lines([ + "*= XPASSES =*", + "*_ test_pass _*", + "*- Captured stdout call -*", + "*= short test summary info =*", + "XPASS test_xpass_output.py::test_pass", + "*= 1 xpassed in * =*" + ]) + From b0cb867cc0d5e4d1292b4af6a52467201966b12d Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Fri, 22 Dec 2023 20:44:23 -0800 Subject: [PATCH 06/14] remove some unused variables --- src/_pytest/terminal.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 3278e88be06..df90111dabe 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1182,10 +1182,6 @@ def show_simple(lines: List[str], *, stat: str) -> None: def show_xfailed(lines: List[str]) -> None: xfailed = self.stats.get("xfailed", []) for rep in xfailed: - verbose_word = rep._get_verbose_word(self.config) - markup_word = self._tw.markup( - verbose_word, **{_color_for_type["warnings"]: True} - ) color = _color_for_type.get("xfailed", _color_for_type_default) line = _get_line_with_reprcrash_message( self.config, rep, self._tw, {color: True} From 5d726faad07b7878852e36fd196584b03cb2cfda Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Mon, 25 Dec 2023 16:15:22 -0800 Subject: [PATCH 07/14] remove assert outcome from xfail summary, as it breaks [NOTRUN] functionality --- src/_pytest/terminal.py | 8 +++++--- testing/test_skipping.py | 2 +- testing/test_terminal.py | 10 +++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index df90111dabe..3ffcdfd9153 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1182,10 +1182,12 @@ def show_simple(lines: List[str], *, stat: str) -> None: def show_xfailed(lines: List[str]) -> None: xfailed = self.stats.get("xfailed", []) for rep in xfailed: - color = _color_for_type.get("xfailed", _color_for_type_default) - line = _get_line_with_reprcrash_message( - self.config, rep, self._tw, {color: True} + verbose_word = rep._get_verbose_word(self.config) + markup_word = self._tw.markup( + verbose_word, **{_color_for_type["warnings"]: True} ) + nodeid = _get_node_id_with_markup(self._tw, self.config, rep) + line = f"{markup_word} {nodeid}" reason = rep.wasxfail if reason: line += " - " + str(reason) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index b7e448df366..b2ad4b0cf6d 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -649,7 +649,7 @@ def test_foo(): result.stdout.fnmatch_lines( [ "*test_strict_xfail*", - "XPASS test_strict_xfail.py::test_foo unsupported feature", + "XPASS test_strict_xfail.py::test_foo - unsupported feature", ] ) assert result.ret == (1 if strict else 0) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 4f8d449e7c7..43811bc0f21 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2631,8 +2631,8 @@ def test_xfail_reason(): """ ) result = pytester.runpytest("-rx") - expect1 = "XFAIL test_summary_xfail_reason.py::test_xfail - assert False" - expect2 = "XFAIL test_summary_xfail_reason.py::test_xfail_reason - assert False - foo" + expect1 = "XFAIL test_summary_xfail_reason.py::test_xfail" + expect2 = "XFAIL test_summary_xfail_reason.py::test_xfail_reason - foo" result.stdout.fnmatch_lines([expect1, expect2]) assert result.stdout.lines.count(expect1) == 1 assert result.stdout.lines.count(expect2) == 1 @@ -2660,7 +2660,7 @@ def test_xfail(): "E *assert 1 == 2*", "test_summary_xfail_tb.py:6: AssertionError*", "*= short test summary info =*", - "XFAIL test_summary_xfail_tb.py::test_xfail - assert 1 == 2", + "XFAIL test_summary_xfail_tb.py::test_xfail", "*= 1 xfailed in * =*" ]) @@ -2681,7 +2681,7 @@ def test_xfail(): "*= XFAILURES =*", "*test_xfail_tb_line.py:6: assert 1 == 2", "*= short test summary info =*", - "XFAIL test_xfail_tb_line.py::test_xfail - assert 1 == 2", + "XFAIL test_xfail_tb_line.py::test_xfail", "*= 1 xfailed in * =*" ]) @@ -2724,7 +2724,7 @@ def test_pass(): "*_ test_pass _*", "*- Captured stdout call -*", "*= short test summary info =*", - "XPASS test_xpass_output.py::test_pass", + "XPASS test_xpass_output.py::test_pass*", "*= 1 xpassed in * =*" ]) From afb204218ecf50fd34940b2c384e5d6141876c5a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:16:18 +0000 Subject: [PATCH 08/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- testing/test_terminal.py | 63 ++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 43811bc0f21..23f3d19d972 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2650,19 +2650,21 @@ def test_xfail(): """ ) result = pytester.runpytest("-rx") - result.stdout.fnmatch_lines([ - "*= XFAILURES =*", - "*_ test_xfail _*", - "* @pytest.mark.xfail*", - "* def test_xfail():*", - "* a, b = 1, 2*", - "> *assert a == b*", - "E *assert 1 == 2*", - "test_summary_xfail_tb.py:6: AssertionError*", - "*= short test summary info =*", - "XFAIL test_summary_xfail_tb.py::test_xfail", - "*= 1 xfailed in * =*" - ]) + result.stdout.fnmatch_lines( + [ + "*= XFAILURES =*", + "*_ test_xfail _*", + "* @pytest.mark.xfail*", + "* def test_xfail():*", + "* a, b = 1, 2*", + "> *assert a == b*", + "E *assert 1 == 2*", + "test_summary_xfail_tb.py:6: AssertionError*", + "*= short test summary info =*", + "XFAIL test_summary_xfail_tb.py::test_xfail", + "*= 1 xfailed in * =*", + ] + ) def test_xfail_tb_line(pytester: Pytester) -> None: @@ -2677,13 +2679,15 @@ def test_xfail(): """ ) result = pytester.runpytest("-rx", "--tb=line") - result.stdout.fnmatch_lines([ - "*= XFAILURES =*", - "*test_xfail_tb_line.py:6: assert 1 == 2", - "*= short test summary info =*", - "XFAIL test_xfail_tb_line.py::test_xfail", - "*= 1 xfailed in * =*" - ]) + result.stdout.fnmatch_lines( + [ + "*= XFAILURES =*", + "*test_xfail_tb_line.py:6: assert 1 == 2", + "*= short test summary info =*", + "XFAIL test_xfail_tb_line.py::test_xfail", + "*= 1 xfailed in * =*", + ] + ) def test_summary_xpass_reason(pytester: Pytester) -> None: @@ -2719,12 +2723,13 @@ def test_pass(): """ ) result = pytester.runpytest("-rX") - result.stdout.fnmatch_lines([ - "*= XPASSES =*", - "*_ test_pass _*", - "*- Captured stdout call -*", - "*= short test summary info =*", - "XPASS test_xpass_output.py::test_pass*", - "*= 1 xpassed in * =*" - ]) - + result.stdout.fnmatch_lines( + [ + "*= XPASSES =*", + "*_ test_pass _*", + "*- Captured stdout call -*", + "*= short test summary info =*", + "XPASS test_xpass_output.py::test_pass*", + "*= 1 xpassed in * =*", + ] + ) From 958ba23d96cae61a8afc6aee65e867464b4f7633 Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Tue, 2 Jan 2024 09:27:25 -0800 Subject: [PATCH 09/14] minor cleanup --- test_xfail.py | 22 ---------------------- venv/pyvenv.cfg | 6 ------ xfail/pyproject.toml | 3 --- xfail/test_xfail.py | 32 -------------------------------- 4 files changed, 63 deletions(-) delete mode 100644 test_xfail.py delete mode 100644 venv/pyvenv.cfg delete mode 100644 xfail/pyproject.toml delete mode 100644 xfail/test_xfail.py diff --git a/test_xfail.py b/test_xfail.py deleted file mode 100644 index c99f51d0081..00000000000 --- a/test_xfail.py +++ /dev/null @@ -1,22 +0,0 @@ -import pytest - - -def test_pass(): - ... - - -def test_fail(): - a, b = 1, 2 - assert a == b - - -@pytest.mark.xfail -def test_xfail(): - a, b = 1, 2 - assert a == b - - -@pytest.mark.xfail -def test_xpass(): - a, b = 1, 1 - assert a == b diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg deleted file mode 100644 index df2e9449154..00000000000 --- a/venv/pyvenv.cfg +++ /dev/null @@ -1,6 +0,0 @@ -home = /Library/Frameworks/Python.framework/Versions/3.11/bin -include-system-site-packages = false -version = 3.11.5 -prompt = 'pytest' -executable = /Library/Frameworks/Python.framework/Versions/3.11/bin/python3.11 -command = /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 -m venv --prompt="." /Users/okken/projects/pytest/venv diff --git a/xfail/pyproject.toml b/xfail/pyproject.toml deleted file mode 100644 index 81a978dc6c4..00000000000 --- a/xfail/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[tool.pytest.ini_options] -addopts = "-ra --strict-markers" -#xfail_strict = true diff --git a/xfail/test_xfail.py b/xfail/test_xfail.py deleted file mode 100644 index 46d24dd5f56..00000000000 --- a/xfail/test_xfail.py +++ /dev/null @@ -1,32 +0,0 @@ -import pytest - - -def test_pass(): - print("in test_pass") - - -def test_fail(): - print("in test_fail") - a, b = 1, 2 - assert a == b - - -@pytest.mark.xfail -def test_xfail(): - print("in test_xfail") - a, b = 1, 2 - assert a == b - - -@pytest.mark.xfail(reason="reason 1") -def test_xfail_reason(): - print("in test_xfail") - a, b = 1, 2 - assert a == b - - -@pytest.mark.xfail(reason="reason 2") -def test_xpass(): - print("in test_xpass") - a, b = 1, 1 - assert a == b From f35c5ef0cf18640df282101231f1753c8a364e19 Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:56:17 -0800 Subject: [PATCH 10/14] Refactor `summary_failures()` and `summary_passes()` to handle the `x` variants. Add feature changelog entry. --- changelog/11574.feature.rst | 1 + src/_pytest/terminal.py | 61 +++++++++++-------------------------- 2 files changed, 19 insertions(+), 43 deletions(-) create mode 100644 changelog/11574.feature.rst diff --git a/changelog/11574.feature.rst b/changelog/11574.feature.rst new file mode 100644 index 00000000000..c59480e4594 --- /dev/null +++ b/changelog/11574.feature.rst @@ -0,0 +1 @@ +Report tracebacks for xfailures when ``-rx`` is set. Report captured output for xpasses when ``-rX`` is set. For xpasses, add ``-`` in summary between test name and reason, to match the format of xfail. Addresses issue #11233. \ No newline at end of file diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 3ffcdfd9153..3c7f5417009 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -877,11 +877,11 @@ def pytest_sessionfinish( @hookimpl(wrapper=True) def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() - self.summary_failures() - self.summary_xfailures() + self.summary_failures("failed", "FAILURES") + self.summary_failures("xfailed", "XFAILURES", "x") self.summary_warnings() - self.summary_passes() - self.summary_xpasses() + self.summary_passes("passed", "PASSES", "P") + self.summary_passes("xpassed", "XPASSES", "X") try: return (yield) finally: @@ -1010,27 +1010,16 @@ def collapsed_location_report(reports: List[WarningReport]) -> str: "-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html" ) - def summary_passes(self) -> None: + def summary_passes(self, + which_reports: str, + sep_title: str, + needed_opt: str) -> None: if self.config.option.tbstyle != "no": - if self.hasopt("P"): - reports: List[TestReport] = self.getreports("passed") + if self.hasopt(needed_opt): + reports: List[TestReport] = self.getreports(which_reports) if not reports: return - self.write_sep("=", "PASSES") - for rep in reports: - if rep.sections: - msg = self._getfailureheadline(rep) - self.write_sep("_", msg, green=True, bold=True) - self._outrep_summary(rep) - self._handle_teardown_sections(rep.nodeid) - - def summary_xpasses(self) -> None: - if self.config.option.tbstyle != "no": - if self.hasopt("X"): - reports: List[TestReport] = self.getreports("xpassed") - if not reports: - return - self.write_sep("=", "XPASSES") + self.write_sep("=", sep_title) for rep in reports: if rep.sections: msg = self._getfailureheadline(rep) @@ -1063,30 +1052,16 @@ def print_teardown_sections(self, rep: TestReport) -> None: content = content[:-1] self._tw.line(content) - def summary_failures(self) -> None: - if self.config.option.tbstyle != "no": - reports: List[BaseReport] = self.getreports("failed") - if not reports: - return - self.write_sep("=", "FAILURES") - if self.config.option.tbstyle == "line": - for rep in reports: - line = self._getcrashline(rep) - self.write_line(line) - else: - for rep in reports: - msg = self._getfailureheadline(rep) - self.write_sep("_", msg, red=True, bold=True) - self._outrep_summary(rep) - self._handle_teardown_sections(rep.nodeid) - - def summary_xfailures(self) -> None: + def summary_failures(self, + which_reports: str, + sep_title: str, + needed_opt:str|None = None) -> None: if self.config.option.tbstyle != "no": - if self.hasopt("x"): - reports: List[BaseReport] = self.getreports("xfailed") + if not needed_opt or self.hasopt(needed_opt): + reports: List[BaseReport] = self.getreports(which_reports) if not reports: return - self.write_sep("=", "XFAILURES") + self.write_sep("=", sep_title) if self.config.option.tbstyle == "line": for rep in reports: line = self._getcrashline(rep) From 04555a8bebc42f3ca4a68e58bc33d21fd9ae0c9d Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:04:24 -0800 Subject: [PATCH 11/14] Use Optional instead of | --- src/_pytest/terminal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 3c7f5417009..ae2b3b56a40 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1055,7 +1055,7 @@ def print_teardown_sections(self, rep: TestReport) -> None: def summary_failures(self, which_reports: str, sep_title: str, - needed_opt:str|None = None) -> None: + needed_opt: Optional[str] = None) -> None: if self.config.option.tbstyle != "no": if not needed_opt or self.hasopt(needed_opt): reports: List[BaseReport] = self.getreports(which_reports) From fb6b7ac181fc8ecf2da34e9a18f077dea15983a7 Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Wed, 3 Jan 2024 22:27:19 -0800 Subject: [PATCH 12/14] Change refactor so it doesn't break pytest-sugar --- AUTHORS | 1 + .../{11574.feature.rst => 11233.feature.rst} | 2 +- src/_pytest/terminal.py | 34 ++++++++++++------- 3 files changed, 24 insertions(+), 13 deletions(-) rename changelog/{11574.feature.rst => 11233.feature.rst} (84%) diff --git a/AUTHORS b/AUTHORS index 42cfd0be249..537e40df004 100644 --- a/AUTHORS +++ b/AUTHORS @@ -137,6 +137,7 @@ Erik Hasse Erik M. Bray Evan Kepner Evgeny Seliverstov +Fabian Sturm Fabien Zarifian Fabio Zadrozny Felix Hofstätter diff --git a/changelog/11574.feature.rst b/changelog/11233.feature.rst similarity index 84% rename from changelog/11574.feature.rst rename to changelog/11233.feature.rst index c59480e4594..75f3742ffb1 100644 --- a/changelog/11574.feature.rst +++ b/changelog/11233.feature.rst @@ -1 +1 @@ -Report tracebacks for xfailures when ``-rx`` is set. Report captured output for xpasses when ``-rX`` is set. For xpasses, add ``-`` in summary between test name and reason, to match the format of xfail. Addresses issue #11233. \ No newline at end of file +Report tracebacks for xfailures when ``-rx`` is set. Report captured output for xpasses when ``-rX`` is set. For xpasses, add ``-`` in summary between test name and reason, to match the format of xfail. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index ae2b3b56a40..b91a97221cd 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -877,11 +877,11 @@ def pytest_sessionfinish( @hookimpl(wrapper=True) def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() - self.summary_failures("failed", "FAILURES") - self.summary_failures("xfailed", "XFAILURES", "x") + self.summary_failures() + self.summary_xfailures() self.summary_warnings() - self.summary_passes("passed", "PASSES", "P") - self.summary_passes("xpassed", "XPASSES", "X") + self.summary_passes() + self.summary_xpasses() try: return (yield) finally: @@ -1010,10 +1010,15 @@ def collapsed_location_report(reports: List[WarningReport]) -> str: "-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html" ) - def summary_passes(self, - which_reports: str, - sep_title: str, - needed_opt: str) -> None: + def summary_passes(self) -> None: + self.summary_passes_combined("passed", "PASSES", "P") + + def summary_xpasses(self) -> None: + self.summary_passes_combined("xpassed", "XPASSES", "X") + + def summary_passes_combined( + self, which_reports: str, sep_title: str, needed_opt: str + ) -> None: if self.config.option.tbstyle != "no": if self.hasopt(needed_opt): reports: List[TestReport] = self.getreports(which_reports) @@ -1052,10 +1057,15 @@ def print_teardown_sections(self, rep: TestReport) -> None: content = content[:-1] self._tw.line(content) - def summary_failures(self, - which_reports: str, - sep_title: str, - needed_opt: Optional[str] = None) -> None: + def summary_failures(self) -> None: + self.summary_failures_combined("failed", "FAILURES") + + def summary_xfailures(self) -> None: + self.summary_failures_combined("xfailed", "XFAILURES", "x") + + def summary_failures_combined( + self, which_reports: str, sep_title: str, needed_opt: Optional[str] = None + ) -> None: if self.config.option.tbstyle != "no": if not needed_opt or self.hasopt(needed_opt): reports: List[BaseReport] = self.getreports(which_reports) From 19b37618c9a3d14fe06b98a7c0fe86fea753d71e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 5 Jan 2024 09:46:33 -0300 Subject: [PATCH 13/14] Update changelog/11233.feature.rst --- changelog/11233.feature.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/changelog/11233.feature.rst b/changelog/11233.feature.rst index 75f3742ffb1..78810620809 100644 --- a/changelog/11233.feature.rst +++ b/changelog/11233.feature.rst @@ -1 +1,5 @@ -Report tracebacks for xfailures when ``-rx`` is set. Report captured output for xpasses when ``-rX`` is set. For xpasses, add ``-`` in summary between test name and reason, to match the format of xfail. +Improvements to how ``-r`` for xfailures and xpasses: + +* Report tracebacks for xfailures when ``-rx`` is set. +* Report captured output for xpasses when ``-rX`` is set. +* For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed. From 682478d509e0564e26f07953d501551429a6e06f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:47:13 +0000 Subject: [PATCH 14/14] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/11233.feature.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/11233.feature.rst b/changelog/11233.feature.rst index 78810620809..c465def84ec 100644 --- a/changelog/11233.feature.rst +++ b/changelog/11233.feature.rst @@ -1,5 +1,5 @@ Improvements to how ``-r`` for xfailures and xpasses: -* Report tracebacks for xfailures when ``-rx`` is set. -* Report captured output for xpasses when ``-rX`` is set. +* Report tracebacks for xfailures when ``-rx`` is set. +* Report captured output for xpasses when ``-rX`` is set. * For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed.