Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/pytest_doctest_docutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,30 @@

import _pytest
from _pytest import outcomes
from _pytest.doctest import DoctestItem
from _pytest.outcomes import OutcomeException

from doctest_docutils import DocutilsDocTestFinder, setup

if TYPE_CHECKING:
from doctest import _Out

from _pytest.doctest import DoctestItem

logger = logging.getLogger(__name__)

# Lazy definition of runner class
RUNNER_CLASS = None


def pytest_configure(config: pytest.Config) -> None:
"""Disable pytest.doctest to prevent running tests twice.

Todo: Find a way to make these plugins cooperate without collecting twice.
"""
if config.pluginmanager.has_plugin("doctest"):
config.pluginmanager.set_blocked("doctest")


def pytest_unconfigure() -> None:
global RUNNER_CLASS

Expand Down Expand Up @@ -170,7 +180,7 @@ def _DocTestRunner__patched_linecache_getlines(


class DocTestDocutilsFile(pytest.Module):
def collect(self) -> Iterable[DoctestItem]:
def collect(self) -> Iterable["DoctestItem"]:
setup()

encoding = self.config.getini("doctest_encoding")
Expand All @@ -189,6 +199,7 @@ def collect(self) -> Iterable[DoctestItem]:
self.config
),
)
from _pytest.doctest import DoctestItem

for test in finder.find(
text,
Expand Down
178 changes: 178 additions & 0 deletions tests/test_pytest_doctest_docutils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import pathlib
import textwrap
import typing as t

import pytest

import _pytest.pytester

FixtureFileDict = t.Dict[str, str]


class PytestDocTestFinderFixture(t.NamedTuple):
# pytest
test_id: str

# Content
files: FixtureFileDict
tests_found: int


FIXTURES = [
#
# Docutils
#
PytestDocTestFinderFixture(
test_id="reST-doctest_block",
files={
"example.rst": textwrap.dedent(
"""
>>> 4 + 4
8
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="reST-doctest_directive",
files={
"example.rst": textwrap.dedent(
"""
.. doctest::

>>> 4 + 4
8
"""
)
},
tests_found=1,
),
#
# Markdown / myst-parser
#
PytestDocTestFinderFixture(
test_id="MyST-doctest_block",
files={
"example.md": textwrap.dedent(
"""
```
>>> 4 + 4
8
```
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="MyST-doctest_block-indented",
files={
"example.md": textwrap.dedent(
"""
Here's a test:

>>> 4 + 4
8
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="MyST-doctest_directive-colons",
files={
"example.md": textwrap.dedent(
"""
:::{doctest}

>>> 4 + 4
8
:::
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="MyST-doctest_directive-backticks",
files={
"example.md": textwrap.dedent(
"""
```{doctest}

>>> 4 + 4
8
```
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="MyST-doctest_directive-eval-rst-colons",
files={
"example.md": textwrap.dedent(
"""
:::{eval-rst}

.. doctest::

>>> 4 + 4
8
:::
"""
)
},
tests_found=1,
),
PytestDocTestFinderFixture(
test_id="MyST-doctest_directive-eval-rst-backticks",
files={
"example.md": textwrap.dedent(
"""
```{eval-rst}

.. doctest::

>>> 4 + 4
8
```
"""
)
},
tests_found=1,
),
]


@pytest.mark.parametrize(
PytestDocTestFinderFixture._fields, FIXTURES, ids=[f.test_id for f in FIXTURES]
)
def test_pluginDocutilsDocTestFinder(
pytester: _pytest.pytester.Pytester,
tmp_path: pathlib.Path,
monkeypatch: pytest.MonkeyPatch,
test_id: str,
files: FixtureFileDict,
tests_found: int,
) -> None:
# Initialize variables
pytester.plugins = ["pytest_doctest_docutils"]
pytester.makefile(".ini", pytest="[pytest]\naddopts=-p no:doctest -vv\n")
tests_path = tmp_path / "tests"
first_test_key = list(files.keys())[0]
first_test_filename = str(tests_path / first_test_key)

# Setup: Files
tests_path.mkdir()
for file_name, text in files.items():
rst_file = tests_path / file_name
rst_file.write_text(
text,
encoding="utf-8",
)

# Test
result = pytester.runpytest(str(first_test_filename))
result.assert_outcomes(passed=tests_found)