目錄html
doctest
模塊doctest是python
內置的一個標準庫,它能夠查找代碼中相似交互式會話形式的註釋,並檢查它們是否正確;python
默認狀況下,pytest
會自動收集全部名稱匹配test*.txt
規則的文件,並調用doctest
執行它們;git
下面,咱們來看一個簡單的例子:github
# src/chapter-9/test_example.txt >>> x = 3 >>> x 3
直接使用pytest
命令就能夠執行它:shell
λ pipenv run pytest src/chapter-9/test_example.txt ====================== test session starts ======================= platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0 rootdir: D:\Personal Files\Projects\pytest-chinese-doc collected 1 item src\chapter-9\test_example.txt . [100%] ======================= 1 passed in 0.03s ========================
咱們也可使用命令行選項--doctest-glob
添加文件名稱的匹配規則;session
例如,匹配rst
格式的文件:測試
pytest --doctest-glob='*.rst'
注意:
--doctest-glob
能夠屢次指定,它們之間是或者的關係,而且依舊支持默認的test*.txt
規則;ui
doctest
文件的默認編碼是UTF-8,你能夠在pytest.ini
中使用doctest_encoding
選項指定新的編碼;例如,使用latin1
編碼:this
[pytest] doctest_encoding = latin1
除了文本文件外,pytest
還支持檢查文檔字符串中的註釋;例如:編碼
# src/chapter-9/test_module.py def something(): '''文檔字符串示例 >>> something() 42 ''' return 42 def test_module(): assert something() == 42
執行時,須要添加--doctest-modules
命令行選項:
λ pipenv run pytest --doctest-modules src/chapter-9/test_module.py ====================== test session starts ======================= platform win32 -- Python 3.7.3, pytest-5.1.3, py-1.8.0, pluggy-0.13.0 rootdir: D:\Personal Files\Projects\pytest-chinese-doc collected 2 items src\chapter-9\test_module.py .. [100%] ======================= 2 passed in 0.03s ========================
--doctest-modules
會查找全部名稱匹配*.py
的文件,收集文檔字符串中相似交互式會話形式的註釋,並把每個文檔字符串做爲一個用例來執行,因此上面咱們執行了兩個測試,其中一個是文檔測試;
若是想讓pytest --doctest-modules
正確收集到相關注釋,需知足如下條件:
*.py
規則,但無需知足test_*.py
或者*_test.py
規則;python
交互式會話形式的註釋;若是你不想每次執行都指定--doctest-modules
選項,能夠考慮在pytest.ini
中添加以下配置:
[pytest] addopts = --doctest-modules
文檔字符串是一個多行字符串,使用
'''
或者"""
包裹;通常推薦形式爲,第一行簡述功能,第二行空行,第三行具體描述;而且,能夠經過
__doc__
屬性訪問它;例如,上面例子的__doc__
屬性爲:>>> print(something.__doc__) 文檔字符串示例 >>> something() 42
doctest
標準庫自帶的選項python
的doctest
標準庫自帶一些選項,用於定義文檔測試的模式,咱們一樣能夠在pytest.ini
中使用這些功能;例如,忽略尾隨的空格:
# src/chapter-9/pytest.ini doctest_optionflags = NORMALIZE_WHITESPACE
另外,你也能夠在行註釋中使能這些選項;
例如,使用# doctest: +NORMALIZE_WHITESPACE
一樣能忽略尾隨的空格:
def something(): '''文檔字符串示例 >>> something() # doctest: +NORMALIZE_WHITESPACE 42 ''' return 42
更多細節能夠參考:https://docs.python.org/3/library/doctest.html#option-flags
pytest
自有的選項ALLOW_BYTES
:在輸出時,剔除字符串的b
前綴;例如,如下文檔測試是成功的:
# src/chapter-9/options.py def str_bytes(): '''返回字節編碼 >>> str_bytes() # doctest: +ALLOW_BYTES 'bytes' ''' return b'bytes'
ALLOW_UNICODE
:類似的,在輸出時,剔除字符串的u
前綴;
NUMBER
:爲了不出現如下致使測試失敗的狀況:
Expected: 3.14 Got: 3.141592653589793
咱們能夠經過配置NUMBER
選項,只比較列出的精度:
# src/chapter-9/options.py def number(): '''浮點數的精度 >>> import math >>> math.pi # doctest: +NUMBER 3.14 ''' return 1
注意:咱們並不建議在全局使能
NUMBER
選項,由於它會修改輸出中全部的浮點數的精度,甚至是在字符串或者列表中;例如,如下文檔測試也是成功的:
# src/chapter-9/options.py def str_number(): '''浮點數字符串的精度 >>> str_number() # doctest: +NUMBER '3.14' ''' return '3.1415'
默認狀況下,對於一個給定的文檔測試,pytest
在遇到第一個失敗點時退出執行;可是,咱們能夠經過--doctest-continue-on-failure
命令行選項,讓其繼續執行;
例如,對於如下文檔字符串,包含兩個測試點,pytest --doctest-continue-on-failure
會報告兩個錯誤(默認只會報告第一個錯誤):
def str_bytes(): '''返回字節編碼 >>> str_bytes() 'bytes' >>> import math >>> math.pi 3.14 ''' return b'bytes'
文檔測試失敗時,你能夠經過如下方式更改測試輸出的格式:
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
更多細節能夠參考:https://docs.python.org/3/library/doctest.html#doctest.REPORT_UDIFF
fixture
經過getfixture
可讓你在文檔字符串中使用fixture
:
>>> tmp = getfixture('tmpdir') >>> ... >>>
doctest_namespace fixture
能夠用於向運行doctest
測試的命名空間中注入一些信息,它是一個標準的字典對象;
例如,咱們在conftest.py
中定義一個方法,注入到doctest
的命名空間中:
# src/chapter-9/conftest.py import pytest def func(): return 42 @pytest.fixture(autouse=True) def add_func(doctest_namespace): doctest_namespace['function'] = func
能夠在文檔字符串中直接使用它:
# src/chapter-9/func.txt >>> function() 42
pytest 4.4
版本新增功能
咱們能夠經過pytest.skip
跳過文檔測試;例如,跳過Windows
系統上的文檔測試:
>>> import sys, pytest >>> if sys.platform.startswith('win'): ... pytest.skip('this doctest does not work on Windows') >>> function() 42