sphinx.ext.doctest – 在文档中测试代码片段

在文档中包含代码片段并演示其执行结果通常很有用。但重要的是要确保文档与代码保持同步。

此扩展允许您以自然的方式测试文档中的此类代码片段。如果您像此处所示标记代码块,doctest 构建器将收集它们并将其作为 doctest 测试运行。

在每个文档中,您可以将每个代码片段分配给一个。每个组由

  • 零个或多个设置代码块(例如导入要测试的模块)

  • 一个或多个测试

使用 doctest 构建器构建文档时,会为每个文档收集组并按顺序运行,首先执行设置代码块,然后按文件中的出现顺序执行测试块。

有两种类型的测试块

  • doctest 风格的块通过交错 Python 代码(包括解释器提示符)和输出,模拟交互式会话。

  • 代码输出风格的块由一段普通的 Python 代码组成,并且可选地包含该代码的一段输出。

指令

下面的group参数解释如下:如果为空,则该块被分配给名为default的组。如果是*,则该块被分配给所有组(包括default组)。否则,它必须是逗号分隔的组名列表。

.. testsetup:: [group]

一个设置代码块。此代码不会在其他构建器的输出中显示,但在其所属组的 doctest 之前执行。

选项

:skipif: 条件 (文本)

如果 Python 表达式条件为 True,则跳过该指令。请参阅有条件地跳过测试

.. testcleanup:: [group]

一个清理代码块。此代码不会在其他构建器的输出中显示,但在其所属组的 doctest 之后执行。

版本 1.1 新增。

选项

:skipif: 条件 (文本)

如果 Python 表达式条件为 True,则跳过该指令。请参阅有条件地跳过测试

.. doctest:: [group]

一个 doctest 风格的代码块。您可以使用标准 doctest 标志来控制实际输出与您提供的输出进行比较的方式。默认的标志集由 doctest_default_flags 配置变量指定。

选项

:hide:

在其他构建器中隐藏 doctest 块。默认情况下,它显示为突出显示的 doctest 块。

:options: doctest 标志 (逗号分隔列表)

一个逗号分隔的 doctest 标志列表,适用于测试中的每个示例。(您仍然可以通过 doctest 注释为每个示例提供显式标志,但它们也会显示在其他构建器中。)

或者,您可以提供内联 doctest 选项,就像在 doctest 中一样

>>> datetime.date.now()
datetime.date(2008, 1, 1)

它们在测试运行时将受到尊重,但默认情况下将从演示输出中去除。您可以使用选项 doctest:no-trim-doctest-flags 阻止去除。

:pyversion: (文本)

指定要测试的示例所需的 Python 版本。例如,在以下情况下,该示例将仅在 Python 版本大于 3.12 时进行测试

.. doctest::
   :pyversion: > 3.12

支持以下操作符

  • ~=: 兼容版本子句

  • ==: 版本匹配子句

  • !=: 版本排除子句

  • <=, >=: 包含有序比较子句

  • <, >: 独占有序比较子句

  • ===: 任意相等子句。

pyversion 选项遵循 PEP-0440: 版本说明符

版本 1.6 中新增。

1.7 版中已更改: 支持 PEP-440 运算符和表示法

:trim-doctest-flags:
:no-trim-doctest-flags:

是否单独修剪行尾和 <BLANKLINE> 标记中的 doctest 标志(看起来像 # doctest: FLAG, ... 的注释)。默认是 trim-doctest-flags

请注意,与标准 doctest 一样,您必须使用 <BLANKLINE> 来表示预期输出中的空行。<BLANKLINE> 在构建演示输出(HTML、LaTeX 等)时会被移除。

:skipif: 条件 (文本)

如果 Python 表达式条件为 True,则跳过该指令。请参阅有条件地跳过测试

.. testcode:: [group]

用于代码输出风格测试的代码块。

选项

:hide:

在其他构建器中隐藏代码块。默认情况下,它显示为突出显示的代码块。

:trim-doctest-flags:
:no-trim-doctest-flags:

是否单独修剪行尾和 <BLANKLINE> 标记中的 doctest 标志(看起来像 # doctest: FLAG, ... 的注释)。默认是 trim-doctest-flags

:skipif: 条件 (文本)

如果 Python 表达式条件为 True,则跳过该指令。请参阅有条件地跳过测试

注意

testcode 块中的代码总是会一次性全部执行,无论它包含多少语句。因此,裸表达式将不会生成输出——请使用 print。示例

.. testcode::

   1+1         # this will give no output!
   print(2+2)  # this will give output

.. testoutput::

   4

另外,请注意,由于 doctest 模块不支持在同一片段中混合常规输出和异常消息,因此这也适用于 testcode/testoutput。

.. testoutput:: [group]

上一个 testcode 块的相应输出或异常消息。

:hide:

在其他构建器中隐藏 doctest 块。默认情况下,它显示为突出显示的 doctest 块。

:options: doctest 标志 (逗号分隔列表)

一个逗号分隔的 doctest 标志列表。

:trim-doctest-flags:
:no-trim-doctest-flags:

是否单独修剪行尾和 <BLANKLINE> 标记中的 doctest 标志(看起来像 # doctest: FLAG, ... 的注释)。默认是 trim-doctest-flags

:skipif: 条件 (文本)

如果 Python 表达式条件为 True,则跳过该指令。请参阅有条件地跳过测试

示例

.. testcode::

   print('Output     text.')

.. testoutput::
   :hide:
   :options: -ELLIPSIS, +NORMALIZE_WHITESPACE

   Output text.

以下是指令用法的示例。doctest 的测试与 testcodetestoutput 的测试是等效的。

The parrot module
=================

.. testsetup:: *

   import parrot

The parrot module is a module about parrots.

Doctest example:

.. doctest::

   >>> parrot.voom(3000)
   This parrot wouldn't voom if you put 3000 volts through it!

Test-Output example:

.. testcode::

   parrot.voom(3000)

This would output:

.. testoutput::

   This parrot wouldn't voom if you put 3000 volts through it!

有条件地跳过测试

skipif 是一个字符串选项,可用于有条件地跳过指令。例如,当需要根据环境(硬件、网络/VPN、可选依赖项或不同版本的依赖项)运行不同的测试集时,这可能很有用。skipif 选项受所有 doctest 指令支持。以下是 skipif 用于不同指令时的典型用例

  • testsetuptestcleanup

    • 有条件地跳过测试设置和/或清理

    • 根据环境自定义设置/清理代码

  • doctest

    • 有条件地跳过测试及其输出验证

  • testcode

    • 有条件地跳过测试

    • 根据环境自定义测试代码

  • testoutput

    • 有条件地跳过已跳过测试的输出断言

    • 根据环境期望不同的输出

skipif 选项的值被评估为 Python 表达式。如果结果为真值,则该指令将从测试运行中省略,就像它根本不存在于文件中一样。

除了重复表达式,还可以使用 doctest_global_setup 配置选项将其分配给一个变量,然后可以使用该变量代替。

这是一个示例,如果未安装 Pandas,则跳过某些测试

conf.py
extensions = ['sphinx.ext.doctest']
doctest_global_setup = '''
try:
    import pandas as pd
except ImportError:
    pd = None
'''
contents.rst
.. testsetup::
   :skipif: pd is None

   data = pd.Series([42])

.. doctest::
   :skipif: pd is None

   >>> data.iloc[0]
   42

.. testcode::
   :skipif: pd is None

   print(data.iloc[-1])

.. testoutput::
   :skipif: pd is None

   42

配置

doctest 扩展使用以下配置值

doctest_default_flags
类型:
int
默认:
省略号 | 忽略异常详细信息 | 不接受真值作为1

默认情况下,这些选项已启用

  • ELLIPSIS,允许您在预期输出中放置省略号,以匹配实际输出中的任何内容;

  • IGNORE_EXCEPTION_DETAIL,导致忽略最左侧冒号之后的所有内容以及异常名称中的任何模块信息;

  • DONT_ACCEPT_TRUE_FOR_1,在输出中拒绝“True”而给出“1”——接受这种替换的默认行为是 Python 2.2 之前的遗留产物。

版本 1.5 新增。

doctest_show_successes
类型:
bool
默认:
True

控制是否报告成功。

对于包含许多 doctest 的项目,将其设置为 False 可能很有用,以便只突出显示失败。

版本 7.2 中新增。

doctest_path
类型:
序列[str]
默认:
()

在使用 doctest 构建器时,将添加到 sys.path 的目录列表。(请确保它包含绝对路径。)

doctest_global_setup
类型:
str
默认:
''

Python 代码,对于所测试的每个文件和每个组,都像被放入 testsetup 指令中一样处理。您可以使用它来例如导入您在 doctest 中总是需要的模块。

0.6 版本新增。

doctest_global_cleanup
类型:
str
默认:
''

Python 代码,对于所测试的每个文件和每个组,都像被放入 testcleanup 指令中一样处理。您可以使用它来例如删除测试留下的任何临时文件。

版本 1.1 新增。

doctest_test_doctest_blocks
类型:
str
默认:
'默认'

如果这是一个非空字符串,标准的 reStructuredText doctest 块也将被测试。它们将被分配到给定的组名。

reStructuredText doctest 块只是放在它们自己的段落中的 doctest,像这样

Some documentation text.

>>> print(1)
1

Some more documentation text.

(请注意,没有使用特殊的 :: 来引入 doctest 块;docutils 从开头的 >>> 识别它们。此外,没有使用额外的缩进,尽管它无害。)

如果此值保留为默认值,则上述代码片段将由 doctest 构建器解释为与以下内容完全相同

Some documentation text.

.. doctest::

   >>> print(1)
   1

Some more documentation text.

此功能使您无需使用特殊指令标记即可轻松测试包含在 autodoc 扩展中的 docstring 中的 doctest。

不过请注意,reStructuredText doctest 块中不能有空行。它们将被解释为一个块结束而另一个块开始。此外,<BLANKLINE># doctest: 选项的移除仅在 doctest 块中有效,尽管您可以设置 trim_doctest_flags 以在所有包含 Python 控制台内容的代码块中实现这一点。

doctest_fail_fast
类型:
bool
默认:
False

遇到第一个失败时退出。

在版本 9.0 中新增。