Skip to content
Closed
12 changes: 11 additions & 1 deletion Doc/library/doctest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ examples of doctests in the standard Python test suite and libraries.
Especially useful examples can be found in the standard test file
:file:`Lib/test/test_doctest/test_doctest.py`.

.. versionadded:: 3.13
Doctest will parse markdown files and accept codeblock delimiters ``````` in
docstrings.

.. _doctest-simple-testmod:

Expand Down Expand Up @@ -340,9 +343,13 @@ but doctest isn't trying to do an exact emulation of any specific Python shell.
single: >>>; interpreter prompt
single: ...; interpreter prompt

.. versionadded:: 3.13
Examples can also be enclosed in markdown codeblocks, although this is
*not required*

Any expected output must immediately follow the final ``'>>> '`` or ``'... '``
line containing the code, and the expected output (if any) extends to the next
``'>>> '`` or all-whitespace line.
``'>>> '``, ``````` or all-whitespace line.

The fine print:

Expand All @@ -351,6 +358,9 @@ The fine print:
blank line, put ``<BLANKLINE>`` in your doctest example each place a blank line
is expected.

* Expected output cannot contain triplebackticks ```````, since such a line is
taken to signal the end of expected output.

* All hard tab characters are expanded to spaces, using 8-column tab stops.
Tabs in output generated by the tested code are not modified. Because any
hard tabs in the sample output *are* expanded, this means that if the code
Expand Down
1 change: 1 addition & 0 deletions Lib/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ class DocTestParser:
\n?
# Want consists of any non-blank lines that do not start with PS1.
(?P<want> (?:(?![ ]*$) # Not a blank line
(?![ ]*```) # Not end of a code block
(?![ ]*>>>) # Not a line starting with PS1
.+$\n? # But any other line
)*)
Expand Down
99 changes: 99 additions & 0 deletions Lib/test/test_doctest/test_doctestmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Test that doctest processes strings where examples are enclosed in
markdown-style codeblocks.
"""

import unittest
import doctest

def dummyfunction_codeblocks():
"""
A dummy function that uses codeblocks in the examples.

It is used like this:
```
>>> 1 == 1
True
```
"""
pass

def dummyfunction_multiplecodeblocks():
"""
A dummy function that uses codeblocks in the examples.

It is used like this:
```
>>> 1 == 1
True
```

Or like this:
```
>>> 1 + 2
3
```
"""
pass

mdfile = r'''
# A Markdown file

Some documentation in an md file which contains codeblocks like this:

```pycon
>>> 1 == 1
True
```

and another one like this:

```pycon
>>> 1 + 2
3
```

and sometimes with multiple cases in one codeblock
```pycon
>>> 2 == 2
True

>>> 2 + 2
4
```

It would be nice if doctest could test them too ...
'''

class TestMarkdownDocstring(unittest.TestCase):
"""Test DocTestFinder processes docstrings including markup codeblocks"""

def test_DocTestFinder_codeblocks(self):
"""A single codeblock in the docstring"""

# DocTestFinder returns a list of tests, we only need the first
test = doctest.DocTestFinder().find(dummyfunction_codeblocks)[0]
results = doctest.DocTestRunner().run(test)
self.assertEqual(results, (0,1))

def test_DocTestFinder_multiplecodeblocks(self):
"""Multiple codeblocks in the docstring"""

# DocTestFinder returns a list of tests, we only need the first
test = doctest.DocTestFinder().find(dummyfunction_multiplecodeblocks)[0]
results = doctest.DocTestRunner().run(test)
self.assertEqual(results, (0,2))

class TestMarkdownFile(unittest.TestCase):
"""Test DocTestParser processes markdown files"""

def test_DocTestParser_getdoctest(self):
parser = doctest.DocTestParser()
tests = parser.get_doctest(
mdfile,
globs=dict(),
name="mdfile",
filename=None,
lineno=None,
)
results = doctest.DocTestRunner().run(tests)
self.assertEqual(results, (0,4))
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Adjusted the regex used in :class:`doctest.DocTestParser` to also consider
triple backticks ``````` to signify the end of an example block
(in addition to a blank line and ``>>>``).