test_doctest.py


Overview

`test_doctest.py` is a comprehensive test suite designed to validate the functionality and robustness of pytest's doctest integration. The file contains numerous test cases that exercise different facets of doctest collection, execution, reporting, and interaction with pytest fixtures and configuration options.

Pytest's doctest support allows users to embed tests in docstrings or text files and run them as part of the test suite. This file ensures that pytest can correctly discover, run, and report doctests from various sources, handle edge cases such as Unicode, whitespace, skipping, failure continuation, and support advanced features like fixture injection and doctest-specific option flags.


Detailed Explanation of Classes and Tests

Class: TestDoctests

This class contains tests focused on the collection and execution of doctests from both text files and Python modules. It verifies that doctests are correctly discovered, executed, and reported by pytest.


Class: TestLiterals

Tests related to literal output handling in doctests, focusing on Unicode and bytes literals, and the [NUMBER](/projects/286/67223) option flag that allows approximate number matching.


Class: TestDoctestSkips

Focuses on the behavior of skipped tests within doctests, ensuring that:


Class: TestDoctestAutoUseFixtures

Tests the integration of pytest's autouse fixtures with doctests, including:


Class: TestDoctestNamespaceFixture

Verifies that fixtures injecting variables into the doctest namespace work correctly for both text file doctests and Python module docstring doctests across different fixture scopes.


Class: TestDoctestReportingOption

Tests different doctest diff reporting styles supported by pytest when showing doctest failures:

Also tests invalid reporting option handling.


Standalone Tests


Important Implementation Details and Algorithms


Interaction with Other Parts of the System


Usage Examples

Example: Running a simple doctest in a text file and checking failure

def test_simple_doctestfile(self, pytester: Pytester):
    p = pytester.maketxtfile(
        test_doc="""
        >>> x = 1
        >>> x == 1
        False
    """
    )
    reprec = pytester.inline_run(p)
    reprec.assertoutcome(failed=1)

This test creates a `.txt` file with a failing doctest (`x == 1` expected to be `False`) and asserts that pytest detects the failure.

Example: Testing fixture injection into doctest namespace

def test_namespace_doctestfile(self, pytester, scope):
    pytester.makeconftest(
        f"""
        import pytest
        import contextlib

        @pytest.fixture(autouse=True, scope="{scope}")
        def add_contextlib(doctest_namespace):
            doctest_namespace['cl'] = contextlib
    """
    )
    p = pytester.maketxtfile(
        """
        >>> print(cl.__name__)
        contextlib
    """
    )
    reprec = pytester.inline_run(p)
    reprec.assertoutcome(passed=1)

This test ensures that a fixture injecting `contextlib` under the name `cl` into the doctest namespace works correctly in a text file doctest.


Mermaid Class Diagram

classDiagram
    class TestDoctests {
        +test_collect_testtextfile(pytester)
        +test_collect_module_empty(pytester)
        +test_collect_module_single_modulelevel_doctest(pytester)
        +test_collect_module_two_doctest_one_modulelevel(pytester)
        +test_simple_doctestfile(pytester)
        +test_importmode(pytester)
        +test_new_pattern(pytester)
        +test_multiple_patterns(pytester)
        +test_encoding(pytester, test_string, encoding)
        +test_doctest_unexpected_exception(pytester)
        +test_doctest_outcomes(pytester)
        +test_docstring_partial_context_around_error(pytester)
        +test_docstring_full_context_around_error(pytester)
        +test_doctest_linedata_missing(pytester)
        +test_doctest_linedata_on_property(pytester)
        +test_doctest_no_linedata_on_overridden_property(pytester)
        +test_doctest_unex_importerror_only_txt(pytester)
        +test_doctest_unex_importerror_with_module(pytester)
        +test_doctestmodule(pytester)
        +test_doctest_cached_property(pytester)
        +test_doctestmodule_external_and_issue116(pytester)
        +test_txtfile_failing(pytester)
        +test_txtfile_with_fixtures(pytester)
        +test_txtfile_with_usefixtures_in_ini(pytester)
        +test_doctestmodule_with_fixtures(pytester)
        +test_doctestmodule_three_tests(pytester)
        +test_doctestmodule_two_tests_one_fail(pytester)
        +test_ignored_whitespace(pytester)
        +test_non_ignored_whitespace(pytester)
        +test_ignored_whitespace_glob(pytester)
        +test_non_ignored_whitespace_glob(pytester)
        +test_contains_unicode(pytester)
        +test_ignore_import_errors_on_doctest(pytester)
        +test_junit_report_for_doctest(pytester)
        +test_unicode_doctest(pytester)
        +test_unicode_doctest_module(pytester)
        +test_print_unicode_value(pytester)
        +test_reportinfo(pytester)
        +test_valid_setup_py(pytester)
        +test_main_py_does_not_cause_import_errors(pytester)
        +test_invalid_setup_py(pytester)
        +test_setup_module(pytester)
    }

    class TestLiterals {
        +test_allow_unicode(pytester, config_mode)
        +test_allow_bytes(pytester, config_mode)
        +test_unicode_string(pytester)
        +test_bytes_literal(pytester)
        +test_number_re()
        +test_number_precision(pytester, config_mode)
        +test_number_non_matches(pytester, expression, output)
        +test_number_and_allow_unicode(pytester)
    }

    class TestDoctestSkips {
        +test_one_skipped(pytester, makedoctest)
        +test_one_skipped_failed(pytester, makedoctest)
        +test_all_skipped(pytester, makedoctest)
        +test_vacuous_all_skipped(pytester, makedoctest)
        +test_continue_on_failure(pytester)
        +test_skipping_wrapped_test(pytester)
    }

    class TestDoctestAutoUseFixtures {
        +test_doctest_module_session_fixture(pytester)
        +test_fixture_scopes(pytester, scope, enable_doctest)
        +test_fixture_module_doctest_scopes(pytester, scope, autouse, use_fixture_in_doctest)
        +test_auto_use_request_attributes(pytester, scope)
        +test_auto_use_defined_in_same_module(pytester, scope)
    }

    class TestDoctestNamespaceFixture {
        +test_namespace_doctestfile(pytester, scope)
        +test_namespace_pyfile(pytester, scope)
    }

    class TestDoctestReportingOption {
        +_run_doctest_report(pytester, format)
        +test_doctest_report_udiff(pytester, format)
        +test_doctest_report_cdiff(pytester)
        +test_doctest_report_ndiff(pytester)
        +test_doctest_report_none_or_only_first_failure(pytester, format)
        +test_doctest_report_invalid(pytester)
    }

    TestDoctests <|-- TestLiterals
    TestLiterals <|-- TestDoctestSkips
    TestDoctestSkips <|-- TestDoctestAutoUseFixtures
    TestDoctestAutoUseFixtures <|-- TestDoctestNamespaceFixture
    TestDoctestNamespaceFixture <|-- TestDoctestReportingOption

Summary

`test_doctest.py` is a critical component of pytest's test suite that validates the doctest plugin's capabilities across a wide range of scenarios. It ensures that doctests are robustly collected, executed, and reported, including with advanced pytest features like fixtures, option flags, encoding support, and custom reporting formats. The file also guards against regressions related to import errors, Unicode handling, and test skipping logic.

This file interacts closely with pytest's core testing and fixture system and serves as an essential guardrail for maintaining the quality and functionality of pytest's doctest integration.


End of Documentation for test_doctest.py