模块和测试文件的Doctest集成

默认情况下,所有匹配 test*.txt 模式将通过python标准运行 doctest 模块。您可以通过发出以下命令来更改模式:

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

在命令行上。 --doctest-glob 可以在命令行中多次给定。

如果您有这样的文本文件:

# content of test_example.txt

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

然后你就可以调用 pytest 直接:

$ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
collected 1 item

test_example.txt .                                                   [100%]

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

默认情况下,pytest将收集 test*.txt 文件正在查找doctest指令,但您可以使用 --doctest-glob 选项(允许多个)。

除了文本文件之外,您还可以直接从类和函数的docstrings(包括测试模块)执行doctest:

# 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-6.x.y, py-1.x.y, pluggy-0.x.y
cachedir: $PYTHON_PREFIX/.pytest_cache
rootdir: $REGENDOC_TMPDIR
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选项:

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

使用“doctest”选项

Python 标准 doctest module provides some options 配置doctest测试的严格性。在pytest中,可以使用配置文件启用这些标志。

例如,要使pytest忽略尾随空格并忽略冗长的异常堆栈跟踪,您只需编写:

[pytest]
doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL

或者,可以通过文档测试本身中的内联注释启用选项:

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

pytest还引入了新的选项:

  • ALLOW_UNICODE :启用后, u 在预期的doctest输出中,前缀从unicode字符串中剥离。这使得doctest可以在python2和python3中运行。

  • ALLOW_BYTES :类似地 b 前缀将从预期doctest输出中的字节字符串中剥离。

  • NUMBER :启用时,浮点数只需与在预期doctest输出中写入的精度匹配。例如,以下输出只需要匹配2个小数位:

    >>> math.pi
    3.14
    

    如果你写信 3.1416 那么实际输出需要匹配到小数点后4位,依此类推。

    这样可以避免由于浮点精度有限而导致的误报,例如:

    Expected:
        0.233
    Got:
        0.23300000000000001
    

    NUMBER 还支持浮点数的列表——事实上,它匹配出现在输出中任何地方的浮点数,即使是在字符串中!这意味着在全局范围内启用 doctest_optionflags 在配置文件中。

    5.1 新版功能.

失败时继续

默认情况下,pytest将只报告给定doctest的第一个失败。如果要继续测试,即使出现故障,也要执行以下操作:

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

输出格式

在选项中使用标准doctest模块格式之一,可以在doctest失败时更改doctest的diff输出格式(请参见 doctest.REPORT_UDIFFdoctest.REPORT_CDIFFdoctest.REPORT_NDIFFdoctest.REPORT_ONLY_FIRST_FAILURE ):

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特定功能

提供了一些功能,可以使编写doctest更容易,或者与现有测试套件更好地集成。但是请记住,通过使用这些特性,您的教义将与标准不兼容。 doctests 模块。

使用固定装置

可以使用固定装置 getfixture 帮手:

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

注意,fixture需要在pytest可见的地方定义,例如 conftest.py 文件或插件;包含docstring的普通python文件通常不会扫描fixture,除非由 python_files .

此外, usefixtures 标记和固定装置标记为 autouse 在执行文本doctest文件时支持。

'doctest_namespace'夹具

这个 doctest_namespace fixture可用于将项注入到运行doctest的命名空间中。它旨在在您自己的设备中使用,以提供将它们与上下文一起使用的测试。

doctest_namespace 是一个标准 dict 对象,将要在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 ,在目录树conftest所在的目录中找到这些设备。也就是说,如果将doctest与源代码放在一起,那么相关的conftest.py必须位于同一目录树中。在同级目录树中不会发现设备!

跳过测试

出于同样的原因,人们可能想要跳过普通测试,也可以跳过doctest中的测试。

要跳过doctest中的单个检查,可以使用标准 doctest.SKIP 指令:

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

    >>> 1 + 1
    2
    """

这将跳过第一次检查,但不会跳过第二次。

pytest还允许使用标准pytest函数 pytest.skip()pytest.xfail() 在doctest内部,这可能很有用,因为您可以根据外部条件跳过/xFAIL测试:

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

但是,不鼓励使用这些函数,因为它降低了文档字符串的可读性。

注解

pytest.skip()pytest.xfail() 根据doctest是在Python文件(在docstring中)还是在包含混合了文本的doctest的文本文件中,行为会有所不同:

  • Python模块(文档字符串):函数只作用于该特定文档字符串,让同一模块中的其他文档字符串正常执行。

  • 文本文件:函数跳过/x检查整个文件的睡觉。

选择

虽然内置的pytest支持为使用doctest提供了一组很好的功能,但是如果您广泛使用它们,您可能会对那些添加了更多功能并包括pytest集成的外部包感兴趣:

  • pytest-doctestplus :提供高级文档测试支持,并启用reStruredText(“.rst”)文件的测试。

  • Sybil :提供一种测试文档中的示例的方法,方法是从文档源解析它们,并将分析的示例作为正常测试运行的一部分进行计算。