pytest 核心功能-运行doctests
默认情况下,所有匹配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-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。
除了文本文件,你也可以直接从你的类和函数的文档字符串执行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的标准doctest
模块提供了一些选项来配置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
:当启用时,在预期的doctest输出中,u
前缀将从unicode字符串中剥离。这使得文档测试可以在Python 2和Python 3中运行。 -
ALLOW_BYTES
:类似地,b
前缀从预期doctest输出的字节字符串中剥离。 -
NUMBER
:当启用时,浮点数只需要匹配预期doctest
输出中所写的精度。例如,下面的输出只需要匹配小数点后两位:
>>> math.pi
3.14
如果您写的是3.1416,那么实际的输出将需要匹配小数点后4位。
这避免了由有限的浮点精度引起的误报,如下所示:
Expected:
0.233
Got:
0.23300000000000001
NUMBER
还支持浮点数列表——事实上,它匹配出现在输出中的任何位置的浮点数,甚至在字符串中!这意味着在配置文件中全局启用doctest_optionflags
可能是不合适的。
继续失败
默认情况下,pytest只会报告给定doctest
的第一次失败。如果你在测试失败后仍想继续测试,请:
pytest --doctest-modules --doctest-continue-on-failure
输出格式
通过在选项中使用标准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特性
提供了一些特性,使编写文档测试更容易,或者与现有的测试套件更好地集成。但是请记住,通过使用这些特性,您将使您的doctests
与标准doctests
模块不兼容。
使用fixtures
可以使用getfixture
helper来使用fixture
:
# content of example.rst
>>> tmp = getfixture('tmp_path')
>>> ...
>>>
请注意,fixture
需要定义在pytest可见的地方,例如,conftest.py
文件或插件;包含文档字符串的普通python文件通常不会扫描fixture
,除非由python_files
显式配置。
此外,当执行文本doctest
文件时,也支持usefixtures
标记和fixtures
标记为autuse
。
‘doctest_namespace’ fixture
doctest_namespace fixture
可以用来向运行doctest
的命名空间注入项目。它打算在您自己的fixture
中使用,以提供与上下文一起使用它们的测试。
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
一样,fixture
是在conftest
所在的目录树中发现的。这意味着,如果您将doctest
与源代码放在一起,那么相关的conftest.py
需要位于相同的目录树中。在同级目录树中无法发现fixture
!
跳过测试
出于同样的原因,人们可能希望跳过普通测试,也可以跳过 doctests
中的测试。
要跳过 doctest
中的单个检查,您可以使用标准 doctest.SKIP
指令:
def test_random(y):
"""
>>> random.random() # doctest: +SKIP
0.156231223
>>> 1 + 1
2
"""
这将跳过第一次检查,但不会跳过第二次检查。
Pytest还允许在doctests
中使用标准的Pytest函数Pytest .skip()
和Pytest .xfail()
,这可能很有用,因为你可以根据外部条件跳过xfail
测试:
>>> import sys, pytest
>>> if sys.platform.startswith('win'):
... pytest.skip('this doctest does not work on Windows')
...
>>> import fcntl
>>> ...
但是不鼓励使用这些函数,因为它会降低文档字符串的可读性。
pytest.skip()
和pytest.xfail()
的行为不同,取决于文档测试是在Python文件(文档字符串)中,还是包含混杂文本的文档测试的文本文件中:
- Python模块(
docstrings
):这些函数只在特定的文档字符串中起作用,让同一模块中的其他文档字符串正常执行。 - 文本文件:函数将跳过
xfail
检查整个文件的其余部分。
更多建议: