Pytest官方教程-23-優(yōu)質(zhì)集成實(shí)踐

目錄:

  1. 安裝及入門
  2. 使用和調(diào)用方法
  3. 原有TestSuite使用方法
  4. 斷言的編寫和報告
  5. Pytest fixtures:清晰 模塊化 易擴(kuò)展
  6. 使用Marks標(biāo)記測試用例
  7. Monkeypatching/對模塊和環(huán)境進(jìn)行Mock
  8. 使用tmp目錄和文件
  9. 捕獲stdout及stderr輸出
  10. 捕獲警告信息
  11. 模塊及測試文件中集成doctest測試
  12. skip及xfail: 處理不能成功的測試用例
  13. Fixture方法及測試用例的參數(shù)化
  14. 緩存: 使用跨執(zhí)行狀態(tài)
  15. unittest.TestCase支持
  16. 運(yùn)行Nose用例
  17. 經(jīng)典xUnit風(fēng)格的setup/teardown
  18. 安裝和使用插件
  19. 插件編寫
  20. 編寫鉤子(hook)方法
  21. 運(yùn)行日志
  22. API參考
    1. 方法(Functions)
    2. 標(biāo)記(Marks)
    3. 鉤子(Hooks)
    4. 裝置(Fixtures)
    5. 對象(Objects)
    6. 特殊變量(Special Variables)
    7. 環(huán)境變量(Environment Variables)
    8. 配置選項(Configuration Options)
  23. 優(yōu)質(zhì)集成實(shí)踐
  24. 片狀測試
  25. Pytest導(dǎo)入機(jī)制及sys.path/PYTHONPATH
  26. 配置選項
  27. 示例及自定義技巧
  28. 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_apptest_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_viewtests.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。如果如兩者ab包含一個__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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容