pytest 核心功能-運(yùn)行doctests

2022-03-21 10:48 更新

默認(rèn)情況下,所有匹配?test*.txt?模式的文件將通過(guò)python標(biāo)準(zhǔn)?doctest?模塊運(yùn)行。你可以通過(guò)以下命令來(lái)改變模式:

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 =============================

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

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

# 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 =============================

您可以通過(guò)將這些更改放入 ?pytest.ini? 文件中來(lái)使這些更改在您的項(xiàng)目中永久生效,如下所示:

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

編碼

默認(rèn)的編碼是?UTF-8?,但是你可以使用?doctest_encoding ini?選項(xiàng)來(lái)指定這些?doctest?文件的編碼:

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

使用doctest選項(xiàng)

Python的標(biāo)準(zhǔn)?doctest?模塊提供了一些選項(xiàng)來(lái)配置?doctest?測(cè)試的嚴(yán)格性。在pytest中,可以使用配置文件啟用這些標(biāo)志。

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

[pytest]
doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL

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

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

pytest 還引入了新選項(xiàng):

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

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

這避免了由有限的浮點(diǎn)精度引起的誤報(bào),如下所示:

Expected:
    0.233
Got:
    0.23300000000000001

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

繼續(xù)失敗

默認(rèn)情況下,pytest只會(huì)報(bào)告給定?doctest?的第一次失敗。如果你在測(cè)試失敗后仍想繼續(xù)測(cè)試,請(qǐng):

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

輸出格式

通過(guò)在選項(xiàng)中使用標(biāo)準(zhǔn)?doctest?模塊格式之一,可以更改?doctest?失敗時(shí)的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特性

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

使用fixtures

可以使用?getfixture? helper來(lái)使用?fixture?:

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

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

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

‘doctest_namespace’ fixture

?doctest_namespace fixture?可以用來(lái)向運(yùn)行?doctest?的命名空間注入項(xiàng)目。它打算在您自己的?fixture?中使用,以提供與上下文一起使用它們的測(cè)試。

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

# content of conftest.py
import numpy


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

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

# 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?需要位于相同的目錄樹中。在同級(jí)目錄樹中無(wú)法發(fā)現(xiàn)?fixture!

跳過(guò)測(cè)試

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

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

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

    >>> 1 + 1
    2
    """

這將跳過(guò)第一次檢查,但不會(huì)跳過(guò)第二次檢查。

Pytest還允許在?doctests?中使用標(biāo)準(zhǔn)的Pytest函數(shù)?Pytest .skip()?和?Pytest .xfail()?,這可能很有用,因?yàn)槟憧梢愿鶕?jù)外部條件跳過(guò)?xfail?測(cè)試:

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

但是不鼓勵(lì)使用這些函數(shù),因?yàn)樗鼤?huì)降低文檔字符串的可讀性。

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

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)