sphinx.ext.doctest – 在文件中測試程式碼片段

在文件中包含程式碼片段並展示執行結果通常很有幫助。但重要的是要確保文件與程式碼保持同步更新。

此擴充功能允許您以自然的方式在文件中測試這些程式碼片段。如果您像此處所示標記程式碼區塊,doctest 建構器將會收集它們並作為 doctest 測試執行。

在每個文件中,您可以將每個程式碼片段分配到一個群組。每個群組包含:

  • 零或多個設定程式碼區塊 (例如,匯入要測試的模組)

  • 一個或多個測試區塊

當使用 doctest 建構器建構文件時,會為每個文件收集群組並依序執行,首先執行設定程式碼區塊,然後按照它們在文件中出現的順序執行測試區塊。

有兩種測試區塊

  • doctest 樣式的區塊通過交錯 Python 程式碼 (包括直譯器提示符號) 和輸出,來模擬互動式會話。

  • 程式碼-輸出樣式的區塊包含一段普通的 Python 程式碼,以及可選的,該程式碼的一段輸出。

指令

下面的 group 參數解釋如下:如果為空,則區塊會分配給名為 default 的群組。如果是 *,則區塊會分配給所有群組 (包括 default 群組)。否則,它必須是以逗號分隔的群組名稱列表。

.. testsetup:: [group]

設定程式碼區塊。此程式碼不會在其他建構器的輸出中顯示,但在執行其所屬群組的 doctest 之前執行。

選項

:skipif: condition (text)

如果 python 表達式 condition 為 True,則跳過此指令。請參閱有條件地跳過測試

.. testcleanup:: [group]

清理程式碼區塊。此程式碼不會在其他建構器的輸出中顯示,但在執行其所屬群組的 doctest 之後執行。

在版本 1.1 中新增。

選項

:skipif: condition (text)

如果 python 表達式 condition 為 True,則跳過此指令。請參閱有條件地跳過測試

.. doctest:: [group]

doctest 樣式的程式碼區塊。您可以使用標準 doctest 標記來控制實際輸出與您提供的輸出進行比較的方式。預設標記集由 doctest_default_flags 設定變數指定。

選項

:hide:

在其他建構器中隱藏 doctest 區塊。預設情況下,它顯示為高亮顯示的 doctest 區塊。

:options: doctest flags (comma separated list)

以逗號分隔的 doctest 標記列表,適用於測試中的每個範例。(您仍然可以為每個範例提供明確的標記,使用 doctest 註解,但它們也會在其他建構器中顯示。)

或者,您可以提供內聯 doctest 選項,就像在 doctest 中一樣

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

當測試執行時,它們將被遵守,但預設情況下將從演示輸出中剝離。您可以使用 doctest:no-trim-doctest-flags 選項來防止剝離。

:pyversion: (text)

指定要測試的範例所需的 Python 版本。例如,在以下情況中,範例將僅針對大於 3.12 的 Python 版本進行測試

.. doctest::
   :pyversion: > 3.12

支援以下運算元

  • ~=: 相容版本發佈子句

  • ==: 版本匹配子句

  • !=: 版本排除子句

  • <=, >=: 包含性排序比較子句

  • <, >: 排除性排序比較子句

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

pyversion 選項遵循 PEP-440:版本說明符

在版本 1.6 中新增。

變更於版本 1.7: 支援 PEP-440 運算元和表示法

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

是否修剪移除行尾的 doctest 標記 (看起來像 # doctest: FLAG, ... 的註解) 和 <BLANKLINE> 標記。預設值為 trim-doctest-flags

請注意,與標準 doctest 一樣,您必須使用 <BLANKLINE> 來表示預期輸出中的空白行。<BLANKLINE> 在建構演示輸出 (HTML、LaTeX 等) 時會被移除。

:skipif: condition (text)

如果 python 表達式 condition 為 True,則跳過此指令。請參閱有條件地跳過測試

.. testcode:: [group]

程式碼-輸出樣式測試的程式碼區塊。

選項

:hide:

在其他建構器中隱藏程式碼區塊。預設情況下,它顯示為高亮顯示的程式碼區塊。

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

是否修剪移除行尾的 doctest 標記 (看起來像 # doctest: FLAG, ... 的註解) 和 <BLANKLINE> 標記。預設值為 trim-doctest-flags

:skipif: condition (text)

如果 python 表達式 condition 為 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 flags (comma separated list)

以逗號分隔的 doctest 標記列表。

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

是否修剪移除行尾的 doctest 標記 (看起來像 # doctest: FLAG, ... 的註解) 和 <BLANKLINE> 標記。預設值為 trim-doctest-flags

:skipif: condition (text)

如果 python 表達式 condition 為 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 表達式。如果結果為 true 值,則指令會從測試執行中省略,就像它根本不存在於文件中一樣。

與其重複表達式,不如使用 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
預設:
ELLIPSIS | IGNORE_EXCEPTION_DETAIL | DONT_ACCEPT_TRUE_FOR_1

預設情況下,這些選項已啟用

  • ELLIPSIS,允許您在預期輸出中放置省略符號,以匹配實際輸出中的任何內容;

  • IGNORE_EXCEPTION_DETAIL,導致忽略異常名稱中最左邊冒號後面的所有內容以及任何模組資訊;

  • DONT_ACCEPT_TRUE_FOR_1,拒絕輸出中給出 “1” 時的 “True” – 接受此替換的預設行為是 Python 2.2 之前的遺物。

在版本 1.5 中新增。

doctest_show_successes
類型:
bool
預設:
True

控制是否報告成功。

對於具有許多 doctest 的專案,將其設定為 False 以僅突出顯示失敗可能很有用。

在版本 7.2 中新增。

doctest_path
類型:
Sequence[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
預設:
'default'

如果這是一個非空字串,也將測試標準 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 控制台內容的程式碼區塊中實現這一點。