test_excinfo.py
Overview
[test_excinfo.py](/projects/286/67543) is a comprehensive test suite for the exception handling and traceback reporting functionality in the `pytest` framework, primarily focusing on the `_pytest._code` module's `ExceptionInfo`, `FormattedExcinfo`, and related classes. It validates that exceptions are correctly captured, represented, filtered, and formatted in various scenarios, including simple exceptions, chained exceptions, recursion errors, source code retrieval, and Python 3.11+ native `ExceptionGroup` support.
The file ensures that `pytest`'s mechanisms for introspecting exceptions, tracebacks, and formatting error output for terminal display work correctly and robustly across different Python versions and edge cases, such as missing source code or hidden traceback entries.
Key Classes and Functions
TestTraceback_f_g_h (Class)
Purpose: Tests the traceback entries generated from nested function calls
f(),g(), andh()where exceptions are raised and traceback filtering is exercised.Setup:
Calls
h(), which internally callsg(), which callsf()(which raisesValueError).Captures the exception info in
self.excinfo.
Tests:
test_traceback_entries: Verifies the traceback includes expected frames.test_traceback_entry_getsource: Checks the source code retrieval for traceback entries.test_traceback_entry_getsource_in_construct: Tests source retrieval when source contains syntax constructs.test_traceback_cut: Tests trimming (cut) of traceback to specific code regions.test_traceback_cut_excludepath: Verifies excluding paths from traceback.test_traceback_filterandtest_traceback_filter_selective: Tests filtering of traceback entries based on conditions like__tracebackhide__.test_traceback_recursion_index: Detects recursion in tracebacks.test_traceback_only_specific_recursion_errors: Ensures recursion detection is specific.Additional tests for recursion handling and representation of traceback crashes.
TestGroupContains (Class)
Purpose: Tests the behavior of ExceptionInfo.group_contains() method for
ExceptionGroupexceptions.Tests:
Checks if
group_containscorrectly identifies exception types and messages within nested or shallow exception groups.Tests matching by exception type, regex match on messages, and depth control for searching inside nested groups.
TestFormattedExcinfo (Class)
Purpose: Tests the
FormattedExcinfoclass, responsible for formatting exception info and tracebacks for terminal output.Fixtures:
importasmod: Helper fixture to dynamically create and import temporary Python modules for testing.
Tests:
Source code representation with proper indentation and flow markers.
Handling of missing or partial source code.
Representation of locals, including error handling in
repr().Argument truncation and formatting in function call frames.
Different traceback styles: long, short, no, line, native, and value.
Proper formatting of chained exceptions and suppression of chained exceptions.
Recursion detection in traceback formatting.
Unicode handling in formatted output.
Terminal output correctness and formatting details.
Tests for internal bugs and corner cases (e.g., filtering errors).
Utility Functions and Fixtures
limited_recursion_depth()(fixture): Temporarily sets Python recursion limit to 150 during tests and restores it after, used for recursion-related tests.add_note(err: BaseException, msg: str) -> None: Adds a note to an exception instance, compatible with Python versions before and after 3.11.Various test functions for:
Simple exception capturing via
ExceptionInfoconstructors.Matching exception messages with regex.
Handling exceptions without source code.
Proper formatting and filtering of tracebacks.
Testing exception group handling (both backport and native).
Regression tests for reported issues.
Ensuring hidden traceback entries (
__tracebackhide__) are respected.Tests for notes attached to exceptions and their verification.
Important Implementation Details and Algorithms
Uses pytest.raises() context manager extensively to capture exceptions and obtain
ExceptionInfo.ExceptionInfo instances are created from current exceptions, exception tuples, and exceptions themselves, verifying proper traceback association.
Traceback filtering respects special variables like
__tracebackhide__which mark frames to be hidden in tracebacks.Recursion detection in tracebacks is performed via comparing frames to identify repeated frames indicating recursion.
Formatting of tracebacks uses styles such as "long", "short", "no", "line", and "value" to customize the representation.
Exception groups (Python 3.11+ feature and backport) are tested for containment and correct reporting in pytest.
Tests include mocking and monkeypatching to simulate edge cases such as missing source files or errors in local variable representation.
The file uses the pytest Pytester utility for creating temporary test modules and running pytest on them to test integration and output formatting.
Uses LineMatcher to verify output lines against expected patterns.
Interaction with Other System Parts
Interacts heavily with the
_pytest._codemodule, specifically:ExceptionInfo: encapsulates exception information and tracebacks.FormattedExcinfo: formats exception info for terminal display.TracebackandTracebackEntry: represent and manipulate traceback frames.
Uses
pytestfixtures, utilities like Pytester and MonkeyPatch for test environment management.Uses exceptiongroup backport or native Python 3.11+
ExceptionGroupfor multi-exception handling.Reads and manipulates source code via _pytest._code.Source and Code objects.
Writes formatted output using
_pytest._io.TerminalWriter.
Usage Examples
Capturing a simple exception:
def test_excinfo_simple() -> None:
try:
raise ValueError
except ValueError:
info = _pytest._code.ExceptionInfo.from_current()
assert info.type == ValueError
Filtering a traceback hiding frames with __tracebackhide__:
def test_traceback_filter_selective():
def f():
raise ValueError
def g():
__tracebackhide__ = True
f()
def h():
g()
excinfo = pytest.raises(ValueError, h)
filtered_tb = excinfo.traceback.filter(excinfo)
# filtered_tb excludes frames marked with __tracebackhide__ = True
Checking if an exception group contains a specific exception type:
def test_group_contains():
exc_group = ExceptionGroup("", [RuntimeError()])
with pytest.raises(ExceptionGroup) as exc_info:
raise exc_group
assert exc_info.group_contains(RuntimeError)
Formatting exception info with locals and truncated args:
p = FormattedExcinfo(showlocals=True, truncate_args=True)
repr_excinfo = p.repr_excinfo(excinfo)
repr_excinfo.toterminal(tw_mock)
Mermaid Class Diagram
This diagram shows the main test classes and their key methods, reflecting the structure and focus areas of the test file.
classDiagram
class TestTraceback_f_g_h {
+setup_method(method)
+test_traceback_entries()
+test_traceback_entry_getsource()
+test_traceback_entry_getsource_in_construct()
+test_traceback_cut()
+test_traceback_cut_excludepath(pytester)
+test_traceback_filter()
+test_traceback_filter_selective(tracebackhide, matching)
+test_traceback_recursion_index()
+test_traceback_only_specific_recursion_errors(monkeypatch)
+test_traceback_no_recursion_index()
+test_traceback_messy_recursion()
+test_getreprcrash()
+test_getreprcrash_empty()
}
class TestGroupContains {
+test_contains_exception_type()
+test_doesnt_contain_exception_type()
+test_contains_exception_match()
+test_doesnt_contain_exception_match()
+test_contains_exception_type_unlimited_depth()
+test_contains_exception_type_at_depth_1()
+test_doesnt_contain_exception_type_past_depth()
+test_contains_exception_type_specific_depth()
+test_contains_exception_match_unlimited_depth()
+test_contains_exception_match_at_depth_1()
+test_doesnt_contain_exception_match_past_depth()
+test_contains_exception_match_specific_depth()
}
class TestFormattedExcinfo {
+test_repr_source()
+test_repr_source_out_of_bounds()
+test_repr_source_excinfo()
+test_repr_source_not_existing()
+test_repr_many_line_source_not_existing()
+test_repr_source_failing_fullsource(monkeypatch)
+test_repr_local()
+test_repr_local_with_error()
+test_repr_local_with_exception_in_class_property()
+test_repr_local_truncated()
+test_repr_args_not_truncated(importasmod)
+test_repr_tracebackentry_lines(importasmod)
+test_repr_tracebackentry_lines2(importasmod, tw_mock)
+test_repr_tracebackentry_lines_var_kw_args(importasmod, tw_mock)
+test_repr_tracebackentry_short(importasmod)
+test_repr_traceback_entry_short_carets(importasmod)
+test_repr_tracebackentry_no(importasmod)
+test_repr_traceback_tbfilter(importasmod)
+test_traceback_short_no_source(importasmod, monkeypatch)
+test_repr_traceback_and_excinfo(importasmod)
+test_repr_traceback_with_invalid_cwd(importasmod, monkeypatch)
+test_repr_excinfo_addouterr(importasmod, tw_mock)
+test_repr_excinfo_reprcrash(importasmod)
+test_repr_traceback_recursion(importasmod)
+test_reprexcinfo_getrepr(importasmod)
+test_reprexcinfo_unicode()
+test_toterminal_long(importasmod, tw_mock)
+test_toterminal_long_missing_source(importasmod, tmp_path, tw_mock)
+test_toterminal_long_incomplete_source(importasmod, tmp_path, tw_mock)
+test_toterminal_long_filenames(importasmod, tw_mock, monkeypatch)
+test_toterminal_value(importasmod, tw_mock)
+test_format_excinfo(reproptions)
+test_traceback_repr_style(importasmod, tw_mock)
+test_exc_chain_repr(importasmod, tw_mock)
+test_exc_repr_chain_suppression(importasmod, mode, tw_mock)
+test_exc_chain_repr_without_traceback(importasmod, reason, description)
+test_exc_chain_repr_cycle(importasmod, tw_mock)
+test_exec_type_error_filter(importasmod)
}
Summary
test_excinfo.py is a detailed test suite validating exception capturing, traceback representation, and formatting in pytest.
It covers simple exceptions, exception chaining, recursion detection, exception groups, and formatting styles.
Uses pytest's testing facilities (
raises, fixtures, Pytester) and internal_pytest._codeAPIs.Ensures robustness and correctness of traceback filtering, source retrieval, and terminal output generation.
Includes regression tests for previously reported issues and corner cases.
Supports Python versions pre-3.11 (with backported exceptiongroup) and 3.11+ native exception groups.
This file is critical for maintaining the quality and correctness of the pytest exception reporting mechanism.