Pytest官方教程-23-優質集成實踐

目錄:

  1. 安裝及入門
  2. 使用和調用方法
  3. 原有TestSuite使用方法
  4. 斷言的編寫和報告
  5. Pytest fixtures:清晰 模塊化 易擴展
  6. 使用Marks標記測試用例
  7. Monkeypatching/對模塊和環境進行Mock
  8. 使用tmp目錄和文件
  9. 捕獲stdout及stderr輸出
  10. 捕獲警告信息
  11. 模塊及測試文件中集成doctest測試
  12. skip及xfail: 處理不能成功的測試用例
  13. Fixture方法及測試用例的參數化
  14. 緩存: 使用跨執行狀態
  15. unittest.TestCase支持
  16. 運行Nose用例
  17. 經典xUnit風格的setup/teardown
  18. 安裝和使用插件
  19. 插件編寫
  20. 編寫鉤子(hook)方法
  21. 運行日志
  22. API參考
    1. 方法(Functions)
    2. 標記(Marks)
    3. 鉤子(Hooks)
    4. 裝置(Fixtures)
    5. 對象(Objects)
    6. 特殊變量(Special Variables)
    7. 環境變量(Environment Variables)
    8. 配置選項(Configuration Options)
  23. 優質集成實踐
  24. 片狀測試
  25. Pytest導入機制及sys.path/PYTHONPATH
  26. 配置選項
  27. 示例及自定義技巧
  28. Bash自動補全設置

使用pip安裝包

對于開發,我們建議你將venv用于虛擬環境(或者用于Python 2.7的virtualenv),并使用 pip來安裝應用程序和任何依賴項,以及pytest包本身。這可確保你的代碼和依賴項與系統Python安裝隔離。

接下來,setup.py使用以下最低內容將文件放在包的根目錄中:

from setuptools import setup, find_packages

setup(name="PACKAGENAME", packages=find_packages())

PACKAGENAME包裹的名稱在哪里。然后,你可以通過從同一目錄運行,以“可編輯”模式安裝程序包:

pip install -e .

它允許你更改源代碼(測試和應用程序)并隨意重新運行測試。這與運行類似,或者使用符號鏈接將你的包安裝到開發代碼中。python setup.py develop``conda develop

Python測試發現的約定

pytest 實現以下標準測試發現:

  • 如果未指定參數,則從testpaths (如果已配置)或當前目錄開始收集。或者,命令行參數可以用于目錄,文件名或節點ID的任意組合。
  • 遞歸到目錄,除非它們匹配norecursedirs
  • 在這些目錄,搜索test_*.py*_test.py文件,由他們進口的測試包名
  • 從這些文件中收集測試項目:
    • test 在課堂之外的前綴測試函數或方法
    • test前綴測試Test類中的前綴測試函數或方法(沒有__init__方法)

有關如何自定義測試發現的示例更改標準(Python)測試發現

在Python模塊中,pytest還使用標準的unittest.TestCase子類化技術發現測試 。

選擇測試布局/導入規則

pytest 支持兩種常見的測試布局:

在應用程序代碼外測試

如果你有許多功能測試,或者出于其他原因希望將測試與實際應用程序代碼分開(通常是個好主意),那么將測試放入實際應用程序代碼之外的額外目錄可能會很有用:

setup.py
mypkg/
    __init__.py
    app.py
    view.py
tests/
    test_app.py
    test_view.py
    ...

這有以下好處:

  • 執行后,你的測試可以針對已安裝的版本運行。pip install .
  • 執行后,你可以使用可編輯安裝對本地副本運行測試。pip install --editable .
  • 如果你沒有setup.py文件并且依賴于默認情況下Python將當前目錄放入sys.path以導入你的包,則可以執行直接對本地副本執行測試,而不使用。python -m pytest``pip

注意

有關調用和 調用之間差異的更多信息,請參閱pytest導入機制和sys.path / PYTHONPATHpytest``python -m pytest

請注意,使用此方案時,你的測試文件必須具有唯一的名稱,因為pytest將它們作為頂級模塊導入,因為 沒有包來從中獲取完整的包名稱。換句話說,在上面的示例中的試驗文件將被導入為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

現在pytest將加載模塊,tests.foo.test_viewtests.bar.test_view允許你使用相同名稱的模塊。但是現在這引入了一個微妙的問題:為了從tests目錄中加載測試模塊,pytest將存儲庫的根目錄sys.path添加到 ,這增加了現在mypkg也可導入的副作用。如果你使用像tox這樣的工具在虛擬環境中測試程序包,則會出現問題,因為你要測試程序包的已安裝版本,而不是存儲庫中的本地代碼。

在這種情況下,強烈建議使用src應用程序根包位于根目錄的子目錄中的布局:

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?的優秀博客文章中有更好的解釋 。

測試作為應用程序代碼的一部分

如果測試和應用程序模塊之間存在直接關系并希望將它們與應用程序一起分發,則將測試目錄內聯到應用程序包中非常有用:

setup.py
mypkg/
    __init__.py
    app.py
    view.py
    test/
        __init__.py
        test_app.py
        test_view.py
        ...

在此方案中,使用以下--pyargs選項可以輕松運行測試:

pytest --pyargs mypkg

pytest將發現mypkg安裝位置并從那里收集測試。

請注意,此布局也與src上一節中提到的布局一起使用。

注意

你可以為你的應用程序使用Python3命名空間包(PEP420),但pytest仍將根據文件的存在執行測試包名稱發現__init__.py。如果你使用上面兩個推薦的文件系統布局中的一個,但是__init__.py 從你的目錄中刪除它們,那么它應該適用于Python3.3及更高版本。但是,從“內聯測試”開始,你將需要使用絕對導入來獲取應用程序代碼。

注意

如果pytest在遞歸到文件系統時找到“a / b / test_module.py”測試文件,它將確定導入名稱,如下所示:

  • 確定basedir:這是第一個“向上”(朝向根)目錄,不包含__init__.py。如果如兩者ab包含一個__init__.py文件,然后父目錄a將成為basedir
  • 執行以使測試模塊可以在完全限定的導入名稱下導入。sys.path.insert(0, basedir)
  • import a.b.test_module其中路徑是通過將路徑分隔符/轉換為“。”字符來確定的。這意味著你必須遵循將目錄和文件名直接映射到導入名稱的約定。

這種有點進化的導入技術的原因在于,在較大的項目中,多個測試模塊可能相互導入,因此導出規范的導入名稱有助于避免出現意外情況,例如測試模塊導入兩次。

TOX

一旦完成了你的工作并希望確保你的實際軟件包通過所有測試,你可能需要查看tox,virtualenv測試自動化工具及其pytest支持。tox幫助你使用預定義的依賴項設置virtualenv環境,然后使用選項執行預配置的測試命令。它將針對已安裝的軟件包運行測試,而不是針對源代碼檢查,從而有助于檢測包裝故障。

與setuptools集成

你可以使用pytest-runner插件將測試運行集成到基于setuptools的項目中。

將此添加到setup.py文件:

from setuptools import setup

setup(
    # ...,
    setup_requires=["pytest-runner", ...],
    tests_require=["pytest", ...],
    # ...,
)

并在setup.cfg文件中創建一個別名:

[aliases]
test=pytest

如果你現在輸入:

python setup.py test

這將使用執行你的測試pytest-runner。因為這是一個獨立版本,pytest無需事先安裝,無論如何都需要調用test命令。你還可以使用其他參數傳遞給pytest,例如測試目錄或其他選項--addopts

你還可以setup.cfg通過將文件放入以下[tool:pytest]部分來指定文件中的其他pytest-ini選項:

[tool:pytest]
addopts = --verbose
python_files = testing/*/*.py

手動整合

如果由于某種原因你不想/不能使用pytest-runner,你可以編寫自己的setuptools測試命令來調用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},
)

現在,如果你運行:

python setup.py test

這將pytest在需要時下載,然后按照你的預期運行測試。你可以使用--pytest-args-a命令行選項傳遞單個參數字符串。例如:

python setup.py test -a "--durations=5"

相當于運行 pytest --durations=5

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容