目錄:
- 安裝及入門
- 使用和調(diào)用方法
- 原有TestSuite使用方法
- 斷言的編寫和報告
- Pytest fixtures:清晰 模塊化 易擴(kuò)展
- 使用Marks標(biāo)記測試用例
- Monkeypatching/對模塊和環(huán)境進(jìn)行Mock
- 使用tmp目錄和文件
- 捕獲stdout及stderr輸出
- 捕獲警告信息
- 模塊及測試文件中集成doctest測試
- skip及xfail: 處理不能成功的測試用例
- Fixture方法及測試用例的參數(shù)化
- 緩存: 使用跨執(zhí)行狀態(tài)
- unittest.TestCase支持
- 運(yùn)行Nose用例
- 經(jīng)典xUnit風(fēng)格的setup/teardown
- 安裝和使用插件
- 插件編寫
- 編寫鉤子(hook)方法
- 運(yùn)行日志
- API參考
- 優(yōu)質(zhì)集成實(shí)踐
- 片狀測試
- Pytest導(dǎo)入機(jī)制及sys.path/PYTHONPATH
- 配置選項
- 示例及自定義技巧
- Bash自動補(bǔ)全設(shè)置
使用pip安裝包
對于開發(fā),我們建議你將venv用于虛擬環(huán)境(或者用于Python 2.7的virtualenv),并使用 pip來安裝應(yīng)用程序和任何依賴項,以及pytest包本身。這可確保你的代碼和依賴項與系統(tǒng)Python安裝隔離。
接下來,setup.py使用以下最低內(nèi)容將文件放在包的根目錄中:
from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())
PACKAGENAME包裹的名稱在哪里。然后,你可以通過從同一目錄運(yùn)行,以“可編輯”模式安裝程序包:
pip install -e .
它允許你更改源代碼(測試和應(yīng)用程序)并隨意重新運(yùn)行測試。這與運(yùn)行類似,或者使用符號鏈接將你的包安裝到開發(fā)代碼中。python setup.py develop``conda develop
Python測試發(fā)現(xiàn)的約定
pytest 實(shí)現(xiàn)以下標(biāo)準(zhǔn)測試發(fā)現(xiàn):
- 如果未指定參數(shù),則從
testpaths(如果已配置)或當(dāng)前目錄開始收集。或者,命令行參數(shù)可以用于目錄,文件名或節(jié)點(diǎn)ID的任意組合。 - 遞歸到目錄,除非它們匹配
norecursedirs。 - 在這些目錄,搜索
test_*.py或*_test.py文件,由他們進(jìn)口的測試包名。 - 從這些文件中收集測試項目:
-
test在課堂之外的前綴測試函數(shù)或方法 -
test前綴測試Test類中的前綴測試函數(shù)或方法(沒有__init__方法)
-
有關(guān)如何自定義測試發(fā)現(xiàn)的示例更改標(biāo)準(zhǔn)(Python)測試發(fā)現(xiàn)。
在Python模塊中,pytest還使用標(biāo)準(zhǔn)的unittest.TestCase子類化技術(shù)發(fā)現(xiàn)測試 。
選擇測試布局/導(dǎo)入規(guī)則
pytest 支持兩種常見的測試布局:
在應(yīng)用程序代碼外測試
如果你有許多功能測試,或者出于其他原因希望將測試與實(shí)際應(yīng)用程序代碼分開(通常是個好主意),那么將測試放入實(shí)際應(yīng)用程序代碼之外的額外目錄可能會很有用:
setup.py
mypkg/
__init__.py
app.py
view.py
tests/
test_app.py
test_view.py
...
這有以下好處:
- 執(zhí)行后,你的測試可以針對已安裝的版本運(yùn)行。
pip install . - 執(zhí)行后,你可以使用可編輯安裝對本地副本運(yùn)行測試。
pip install --editable . - 如果你沒有
setup.py文件并且依賴于默認(rèn)情況下Python將當(dāng)前目錄放入sys.path以導(dǎo)入你的包,則可以執(zhí)行直接對本地副本執(zhí)行測試,而不使用。python -m pytest``pip
注意
有關(guān)調(diào)用和 調(diào)用之間差異的更多信息,請參閱pytest導(dǎo)入機(jī)制和sys.path / PYTHONPATH。pytest``python -m pytest
請注意,使用此方案時,你的測試文件必須具有唯一的名稱,因?yàn)?code>pytest將它們作為頂級模塊導(dǎo)入,因?yàn)?沒有包來從中獲取完整的包名稱。換句話說,在上面的示例中的試驗(yàn)文件將被導(dǎo)入為test_app和test_view通過加入頂層模塊tests/到 sys.path。
如果需要具有相同名稱的測試模塊,可以將__init__.py文件添加到 tests文件夾和子文件夾,并將其更改為包:
setup.py
mypkg/
...
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py
現(xiàn)在pytest將加載模塊,tests.foo.test_view并tests.bar.test_view允許你使用相同名稱的模塊。但是現(xiàn)在這引入了一個微妙的問題:為了從tests目錄中加載測試模塊,pytest將存儲庫的根目錄sys.path添加到 ,這增加了現(xiàn)在mypkg也可導(dǎo)入的副作用。如果你使用像tox這樣的工具在虛擬環(huán)境中測試程序包,則會出現(xiàn)問題,因?yàn)槟阋獪y試程序包的已安裝版本,而不是存儲庫中的本地代碼。
在這種情況下,強(qiáng)烈建議使用src應(yīng)用程序根包位于根目錄的子目錄中的布局:
setup.py
src/
mypkg/
__init__.py
app.py
view.py
tests/
__init__.py
foo/
__init__.py
test_view.py
bar/
__init__.py
test_view.py
這種布局可以防止許多常見的陷阱,并且有很多好處,這在IonelCristianM?rie?的優(yōu)秀博客文章中有更好的解釋 。
測試作為應(yīng)用程序代碼的一部分
如果測試和應(yīng)用程序模塊之間存在直接關(guān)系并希望將它們與應(yīng)用程序一起分發(fā),則將測試目錄內(nèi)聯(lián)到應(yīng)用程序包中非常有用:
setup.py
mypkg/
__init__.py
app.py
view.py
test/
__init__.py
test_app.py
test_view.py
...
在此方案中,使用以下--pyargs選項可以輕松運(yùn)行測試:
pytest --pyargs mypkg
pytest將發(fā)現(xiàn)mypkg安裝位置并從那里收集測試。
請注意,此布局也與src上一節(jié)中提到的布局一起使用。
注意
你可以為你的應(yīng)用程序使用Python3命名空間包(PEP420),但pytest仍將根據(jù)文件的存在執(zhí)行測試包名稱發(fā)現(xiàn)__init__.py。如果你使用上面兩個推薦的文件系統(tǒng)布局中的一個,但是__init__.py 從你的目錄中刪除它們,那么它應(yīng)該適用于Python3.3及更高版本。但是,從“內(nèi)聯(lián)測試”開始,你將需要使用絕對導(dǎo)入來獲取應(yīng)用程序代碼。
注意
如果pytest在遞歸到文件系統(tǒng)時找到“a / b / test_module.py”測試文件,它將確定導(dǎo)入名稱,如下所示:
- 確定
basedir:這是第一個“向上”(朝向根)目錄,不包含__init__.py。如果如兩者a并b包含一個__init__.py文件,然后父目錄a將成為basedir。 - 執(zhí)行以使測試模塊可以在完全限定的導(dǎo)入名稱下導(dǎo)入。
sys.path.insert(0, basedir) -
import a.b.test_module其中路徑是通過將路徑分隔符/轉(zhuǎn)換為“?!弊址麃泶_定的。這意味著你必須遵循將目錄和文件名直接映射到導(dǎo)入名稱的約定。
這種有點(diǎn)進(jìn)化的導(dǎo)入技術(shù)的原因在于,在較大的項目中,多個測試模塊可能相互導(dǎo)入,因此導(dǎo)出規(guī)范的導(dǎo)入名稱有助于避免出現(xiàn)意外情況,例如測試模塊導(dǎo)入兩次。
TOX
一旦完成了你的工作并希望確保你的實(shí)際軟件包通過所有測試,你可能需要查看tox,virtualenv測試自動化工具及其pytest支持。tox幫助你使用預(yù)定義的依賴項設(shè)置virtualenv環(huán)境,然后使用選項執(zhí)行預(yù)配置的測試命令。它將針對已安裝的軟件包運(yùn)行測試,而不是針對源代碼檢查,從而有助于檢測包裝故障。
與setuptools集成
你可以使用pytest-runner插件將測試運(yùn)行集成到基于setuptools的項目中。
將此添加到setup.py文件:
from setuptools import setup
setup(
# ...,
setup_requires=["pytest-runner", ...],
tests_require=["pytest", ...],
# ...,
)
并在setup.cfg文件中創(chuàng)建一個別名:
[aliases]
test=pytest
如果你現(xiàn)在輸入:
python setup.py test
這將使用執(zhí)行你的測試pytest-runner。因?yàn)檫@是一個獨(dú)立版本,pytest無需事先安裝,無論如何都需要調(diào)用test命令。你還可以使用其他參數(shù)傳遞給pytest,例如測試目錄或其他選項--addopts。
你還可以setup.cfg通過將文件放入以下[tool:pytest]部分來指定文件中的其他pytest-ini選項:
[tool:pytest]
addopts = --verbose
python_files = testing/*/*.py
手動整合
如果由于某種原因你不想/不能使用pytest-runner,你可以編寫自己的setuptools測試命令來調(diào)用pytest。
import sys
from setuptools.command.test import test as TestCommand
class PyTest(TestCommand):
user_options = [("pytest-args=", "a", "Arguments to pass to pytest")]
def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = ""
def run_tests(self):
import shlex
# import here, cause outside the eggs aren't loaded
import pytest
errno = pytest.main(shlex.split(self.pytest_args))
sys.exit(errno)
setup(
# ...,
tests_require=["pytest"],
cmdclass={"pytest": PyTest},
)
現(xiàn)在,如果你運(yùn)行:
python setup.py test
這將pytest在需要時下載,然后按照你的預(yù)期運(yùn)行測試。你可以使用--pytest-args或-a命令行選項傳遞單個參數(shù)字符串。例如:
python setup.py test -a "--durations=5"
相當(dāng)于運(yùn)行 pytest --durations=5