pytest 核心功能-運行doctests

2022-03-21 10:48 更新

默認情況下,所有匹配?test*.txt?模式的文件將通過python標(biāo)準?doctest?模塊運行。你可以通過以下命令來改變模式:

pytest --doctest-glob="*.rst"

--doctest-glob 可以在命令行中輸入多次。

如果您有這樣的文本文件:

# content of test_example.txt

hello this is a doctest
>>> x = 3
>>> x
3

然后你可以直接調(diào)用pytest:

$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item

test_example.txt .                                                   [100%]

============================ 1 passed in 0.12s =============================

默認情況下,pytest 將收集 ?test*.txt? 文件以查找 ?doctest指令,但您可以使用 ?--doctest-glob? 選項傳遞其他 glob。

除了文本文件,你也可以直接從你的類和函數(shù)的文檔字符串執(zhí)行?doctests?,包括從測試模塊:

# content of mymodule.py
def something():
    """a doctest in a docstring
    >>> something()
    42
    """
    return 42
$ pytest --doctest-modules
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 2 items

mymodule.py .                                                        [ 50%]
test_example.txt .                                                   [100%]

============================ 2 passed in 0.12s =============================

您可以通過將這些更改放入 ?pytest.ini? 文件中來使這些更改在您的項目中永久生效,如下所示:

# content of pytest.ini
[pytest]
addopts = --doctest-modules

編碼

默認的編碼是?UTF-8?,但是你可以使用?doctest_encoding ini?選項來指定這些?doctest?文件的編碼:

# content of pytest.ini
[pytest]
doctest_encoding = latin1

使用doctest選項

Python的標(biāo)準?doctest?模塊提供了一些選項來配置?doctest?測試的嚴格性。在pytest中,可以使用配置文件啟用這些標(biāo)志。

例如,要讓pytest忽略后面的空白和忽略冗長的異常堆棧跟蹤,你可以這樣寫:

[pytest]
doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL

另外,也可以通過文檔測試本身的內(nèi)聯(lián)注釋來啟用選項:

>>> something_that_raises()  # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValueError: ...

pytest 還引入了新選項:

  • ?ALLOW_UNICODE?:當(dāng)啟用時,在預(yù)期的doctest輸出中,?u?前綴將從unicode字符串中剝離。這使得文檔測試可以在Python 2和Python 3中運行。
  • ?ALLOW_BYTES?:類似地,?b?前綴從預(yù)期doctest輸出的字節(jié)字符串中剝離。
  • ?NUMBER?:當(dāng)啟用時,浮點數(shù)只需要匹配預(yù)期?doctest?輸出中所寫的精度。例如,下面的輸出只需要匹配小數(shù)點后兩位:
>>> math.pi
3.14

如果您寫的是3.1416,那么實際的輸出將需要匹配小數(shù)點后4位。

這避免了由有限的浮點精度引起的誤報,如下所示:

Expected:
    0.233
Got:
    0.23300000000000001

?NUMBER?還支持浮點數(shù)列表——事實上,它匹配出現(xiàn)在輸出中的任何位置的浮點數(shù),甚至在字符串中!這意味著在配置文件中全局啟用?doctest_optionflags?可能是不合適的。

繼續(xù)失敗

默認情況下,pytest只會報告給定?doctest?的第一次失敗。如果你在測試失敗后仍想繼續(xù)測試,請:

pytest --doctest-modules --doctest-continue-on-failure

輸出格式

通過在選項中使用標(biāo)準?doctest?模塊格式之一,可以更改?doctest?失敗時的diff輸出格式

pytest --doctest-modules --doctest-report none
pytest --doctest-modules --doctest-report udiff
pytest --doctest-modules --doctest-report cdiff
pytest --doctest-modules --doctest-report ndiff
pytest --doctest-modules --doctest-report only_first_failure

pytest-specific特性

提供了一些特性,使編寫文檔測試更容易,或者與現(xiàn)有的測試套件更好地集成。但是請記住,通過使用這些特性,您將使您的?doctests?與標(biāo)準?doctests?模塊不兼容。

使用fixtures

可以使用?getfixture? helper來使用?fixture?:

# content of example.rst
>>> tmp = getfixture('tmp_path')
>>> ...
>>>

請注意,?fixture?需要定義在pytest可見的地方,例如,?conftest.py?文件或插件;包含文檔字符串的普通python文件通常不會掃描?fixture?,除非由?python_files?顯式配置。

此外,當(dāng)執(zhí)行文本?doctest?文件時,也支持?usefixtures?標(biāo)記和?fixtures?標(biāo)記為?autuse?。

‘doctest_namespace’ fixture

?doctest_namespace fixture?可以用來向運行?doctest?的命名空間注入項目。它打算在您自己的?fixture?中使用,以提供與上下文一起使用它們的測試。

?Doctest_namespace?是一個標(biāo)準?dict?對象,你可以將你想要出現(xiàn)在?doctest?命名空間中的對象放入其中:

# content of conftest.py
import numpy


@pytest.fixture(autouse=True)
def add_np(doctest_namespace):
    doctest_namespace["np"] = numpy

然后可以直接在您的文檔測試中使用:

# content of numpy.py
def arange():
    """
    >>> a = np.arange(10)
    >>> len(a)
    10
    """
    pass

注意,與普通的?conftest.py?一樣,?fixture?是在?conftest?所在的目錄樹中發(fā)現(xiàn)的。這意味著,如果您將?doctest?與源代碼放在一起,那么相關(guān)的?conftest.py?需要位于相同的目錄樹中。在同級目錄樹中無法發(fā)現(xiàn)?fixture!

跳過測試

出于同樣的原因,人們可能希望跳過普通測試,也可以跳過 ?doctests中的測試。

要跳過 ?doctest中的單個檢查,您可以使用標(biāo)準 ?doctest.SKIP? 指令:

def test_random(y):
    """
    >>> random.random()  # doctest: +SKIP
    0.156231223

    >>> 1 + 1
    2
    """

這將跳過第一次檢查,但不會跳過第二次檢查。

Pytest還允許在?doctests?中使用標(biāo)準的Pytest函數(shù)?Pytest .skip()?和?Pytest .xfail()?,這可能很有用,因為你可以根據(jù)外部條件跳過?xfail?測試:

>>> import sys, pytest
>>> if sys.platform.startswith('win'):
...     pytest.skip('this doctest does not work on Windows')
...
>>> import fcntl
>>> ...

但是不鼓勵使用這些函數(shù),因為它會降低文檔字符串的可讀性。

?pytest.skip()?和?pytest.xfail()?的行為不同,取決于文檔測試是在Python文件(文檔字符串)中,還是包含混雜文本的文檔測試的文本文件中:

  • Python模塊(?docstrings?):這些函數(shù)只在特定的文檔字符串中起作用,讓同一模塊中的其他文檔字符串正常執(zhí)行。
  • 文本文件:函數(shù)將跳過?xfail?檢查整個文件的其余部分。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號