test_terminal.py


Overview

`test_terminal.py` is a comprehensive test suite designed to validate the terminal reporting functionality of the `pytest` testing framework. It focuses on how test results, collection statuses, warnings, errors, and other test session events are reported in the terminal output. The file ensures that the terminal reporter behaves correctly under various conditions, including different verbosity levels, output styles, test outcome scenarios (pass, fail, skip, xfail, xpass), and integrations with plugins such as [xdist](/projects/286/67223).

The tests cover both standard and edge cases, including:

This file primarily interacts with the [TerminalReporter](/projects/286/67388) class and related utilities from [_pytest.terminal](/projects/286/67388), as well as pytest core APIs and plugins, to verify their output behavior through `pytester` test runs.


Detailed Documentation

Classes

1. DistInfo (NamedTuple)

2. Option

3. TestTerminal

4. TestCollectonly

5. TestFixtureReporting

6. TestTerminalFunctional

7. TestGenericReporting

8. TestClassicOutputStyle

9. TestProgressOutputStyle

10. TestProgressWithTeardown

11. TestFineGrainedTestCase


Functions

Several standalone test functions exist to verify specific terminal reporter behaviors:


Important Implementation Details and Algorithms


Interaction with Other Parts of the System


Usage Examples

Most usage is through pytest's own testing framework (`pytester`) for running tests and capturing terminal output. Examples include:

def test_pass_skip_fail(self, pytester: Pytester, option: Option) -> None:
    pytester.makepyfile(
        '''
        import pytest
        def test_ok():
            pass
        def test_skip():
            pytest.skip("xx")
        def test_func():
            assert 0
        '''
    )
    result = pytester.runpytest(*option.args)
    # Assertions on terminal output depending on verbosity
    ...

Mermaid Class Diagram

classDiagram
    class DistInfo {
        +str project_name
        +int version
    }
    class Option {
        -int verbosity
        +__init__(verbosity=0)
        +args() list~str~
    }
    class TestTerminal {
        +test_pass_skip_fail(pytester, option)
        +test_console_output_style_times_with_skipped_and_passed(pytester)
        +test_internalerror(pytester, linecomp)
        +test_writeline(pytester, linecomp)
        +test_show_runtest_logstart(pytester, linecomp)
        +test_runtest_location_shown_before_test_starts(pytester)
        +test_report_collect_after_half_a_second(pytester, monkeypatch)
        +test_itemreport_subclasses_show_subclassed_file(pytester)
        +test_itemreport_directclasses_not_shown_as_subclasses(pytester)
        +test_keyboard_interrupt(pytester, fulltrace)
        +test_keyboard_in_sessionstart(pytester)
        +test_collect_single_item(pytester)
        +test_rewrite(pytester, monkeypatch)
        +test_report_teststatus_explicit_markup(monkeypatch, pytester, color_mapping, category)
        +test_verbose_skip_reason(pytester)
        +test_isatty(pytester, monkeypatch, isatty)
    }
    class TestCollectonly {
        +test_collectonly_basic(pytester)
        +test_collectonly_skipped_module(pytester)
        +test_collectonly_displays_test_description(pytester, dummy_yaml_custom_test)
        +test_collectonly_failed_module(pytester)
        +test_collectonly_fatal(pytester)
        +test_collectonly_simple(pytester)
        +test_collectonly_error(pytester)
        +test_collectonly_missing_path(pytester)
        +test_collectonly_quiet(pytester)
        +test_collectonly_more_quiet(pytester)
        +test_collect_only_summary_status(pytester)
    }
    class TestFixtureReporting {
        +test_setup_fixture_error(pytester)
        +test_teardown_fixture_error(pytester)
        +test_teardown_fixture_error_and_test_failure(pytester)
        +test_setup_teardown_output_and_test_failure(pytester)
    }
    class TestTerminalFunctional {
        +test_deselected(pytester)
        +test_deselected_with_hook_wrapper(pytester)
        +test_show_deselected_items_using_markexpr_before_test_execution(pytester)
        +test_selected_count_with_error(pytester)
        +test_no_skip_summary_if_failure(pytester)
        +test_passes(pytester)
        +test_header_trailer_info(monkeypatch, pytester, request)
        +test_no_header_trailer_info(monkeypatch, pytester, request)
        +test_header(pytester)
        +test_header_absolute_testpath(pytester, monkeypatch)
        +test_no_header(pytester)
        +test_no_summary(pytester)
        +test_showlocals(pytester)
        +test_noshowlocals_addopts_override(pytester)
        +test_showlocals_short(pytester)
        +test_verbose_reporting(verbose_testfile, pytester)
        +test_verbose_reporting_xdist(verbose_testfile, monkeypatch, pytester, pytestconfig)
        +test_quiet_reporting(pytester)
        +test_more_quiet_reporting(pytester)
        +test_report_collectionfinish_hook(pytester, params)
        +test_summary_f_alias(pytester)
        +test_summary_s_alias(pytester)
        +test_summary_s_folded(pytester)
        +test_summary_s_unfolded(pytester)
    }
    class TestGenericReporting {
        +test_collect_fail(pytester, option)
        +test_maxfailures(pytester, option)
        +test_maxfailures_with_interrupted(pytester)
        +test_tb_option(pytester, option)
        +test_tb_crashline(pytester, option)
        +test_tb_crashline_pytrace_false(pytester, option)
        +test_pytest_report_header(pytester, option)
        +test_show_capture(pytester)
        +test_show_capture_with_teardown_logs(pytester)
    }
    class TestClassicOutputStyle {
        +test_normal_verbosity(pytester, test_files)
        +test_verbose(pytester, test_files)
        +test_quiet(pytester, test_files)
    }
    class TestProgressOutputStyle {
        +test_zero_tests_collected(pytester)
        +test_normal(many_tests_files, pytester)
        +test_colored_progress(pytester