Skip to content

Commit acf1303

Browse files
authoredNov 25, 2024··
Merge pull request #12975 from jakkdl/short_info_excgroup
display single contained exception in excgroups in test summary
2 parents 2157caf + 6f61360 commit acf1303

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed
 

‎changelog/12943.improvement.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info.

‎src/_pytest/_code/code.py

+17
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,23 @@ def exconly(self, tryshort: bool = False) -> str:
589589
representation is returned (so 'AssertionError: ' is removed from
590590
the beginning).
591591
"""
592+
593+
def _get_single_subexc(
594+
eg: BaseExceptionGroup[BaseException],
595+
) -> BaseException | None:
596+
if len(eg.exceptions) != 1:
597+
return None
598+
if isinstance(e := eg.exceptions[0], BaseExceptionGroup):
599+
return _get_single_subexc(e)
600+
return e
601+
602+
if (
603+
tryshort
604+
and isinstance(self.value, BaseExceptionGroup)
605+
and (subexc := _get_single_subexc(self.value)) is not None
606+
):
607+
return f"{subexc!r} [single exception in {type(self.value).__name__}]"
608+
592609
lines = format_exception_only(self.type, self.value)
593610
text = "".join(lines)
594611
text = text.rstrip()

‎testing/code/test_excinfo.py

+77
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,83 @@ def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None:
17201720
_exceptiongroup_common(pytester, outer_chain, inner_chain, native=False)
17211721

17221722

1723+
def test_exceptiongroup_short_summary_info(pytester: Pytester):
1724+
pytester.makepyfile(
1725+
"""
1726+
import sys
1727+
1728+
if sys.version_info < (3, 11):
1729+
from exceptiongroup import BaseExceptionGroup, ExceptionGroup
1730+
1731+
def test_base() -> None:
1732+
raise BaseExceptionGroup("NOT IN SUMMARY", [SystemExit("a" * 10)])
1733+
1734+
def test_nonbase() -> None:
1735+
raise ExceptionGroup("NOT IN SUMMARY", [ValueError("a" * 10)])
1736+
1737+
def test_nested() -> None:
1738+
raise ExceptionGroup(
1739+
"NOT DISPLAYED", [
1740+
ExceptionGroup("NOT IN SUMMARY", [ValueError("a" * 10)])
1741+
]
1742+
)
1743+
1744+
def test_multiple() -> None:
1745+
raise ExceptionGroup(
1746+
"b" * 10,
1747+
[
1748+
ValueError("NOT IN SUMMARY"),
1749+
TypeError("NOT IN SUMMARY"),
1750+
]
1751+
)
1752+
1753+
def test_nested_multiple() -> None:
1754+
raise ExceptionGroup(
1755+
"b" * 10,
1756+
[
1757+
ExceptionGroup(
1758+
"c" * 10,
1759+
[
1760+
ValueError("NOT IN SUMMARY"),
1761+
TypeError("NOT IN SUMMARY"),
1762+
]
1763+
)
1764+
]
1765+
)
1766+
"""
1767+
)
1768+
# run with -vv to not truncate summary info, default width in tests is very low
1769+
result = pytester.runpytest("-vv")
1770+
assert result.ret == 1
1771+
backport_str = "exceptiongroup." if sys.version_info < (3, 11) else ""
1772+
result.stdout.fnmatch_lines(
1773+
[
1774+
"*= short test summary info =*",
1775+
(
1776+
"FAILED test_exceptiongroup_short_summary_info.py::test_base - "
1777+
"SystemExit('aaaaaaaaaa') [single exception in BaseExceptionGroup]"
1778+
),
1779+
(
1780+
"FAILED test_exceptiongroup_short_summary_info.py::test_nonbase - "
1781+
"ValueError('aaaaaaaaaa') [single exception in ExceptionGroup]"
1782+
),
1783+
(
1784+
"FAILED test_exceptiongroup_short_summary_info.py::test_nested - "
1785+
"ValueError('aaaaaaaaaa') [single exception in ExceptionGroup]"
1786+
),
1787+
(
1788+
"FAILED test_exceptiongroup_short_summary_info.py::test_multiple - "
1789+
f"{backport_str}ExceptionGroup: bbbbbbbbbb (2 sub-exceptions)"
1790+
),
1791+
(
1792+
"FAILED test_exceptiongroup_short_summary_info.py::test_nested_multiple - "
1793+
f"{backport_str}ExceptionGroup: bbbbbbbbbb (1 sub-exception)"
1794+
),
1795+
"*= 5 failed in *",
1796+
]
1797+
)
1798+
1799+
17231800
@pytest.mark.parametrize("tbstyle", ("long", "short", "auto", "line", "native"))
17241801
def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None:
17251802
"""Regression test for #10903."""

0 commit comments

Comments
 (0)
Please sign in to comment.