簡體   English   中英

如何在 conftest.py 中使用 pytest 修補環境?

[英]How to monkeypatch the environment using pytest in conftest.py?

我的主文件中有一個全局對象

# reporter.py

from os import environ
from influxdb import InfluxDBClient

influxdb_client = InfluxDBClient(host=environ['INFLUXCLOUD_HOST'],
                                 username=environ['INFLUXCLOUD_USERNAME'],
                                 password=environ['INFLUXCLOUD_PASSWORD'],
                                 ssl=True,
                                 timeout=4*60)

def foo():
    pass

我正在使用 pytest,我想為這些環境變量設置假值。 我的 conftest.py 中有以下內容:

# conftest.py

import pytest

@pytest.fixture(scope='session', autouse=True)
def setup_env(monkeypatch):
    monkeypatch.setenv('INFLUXCLOUD_HOST', 'host')
    monkeypatch.setenv('INFLUXCLOUD_USERNAME', 'username')
    monkeypatch.setenv('INFLUXCLOUD_PASSWORD', 'password')

然而,當我import reporter在我的測試文件,我得到一個KeyError是INFLUXCLOUD_HOST在ENV失蹤。

為什么pytest不執行setup_env和monkeypatch我的環境? 有沒有辦法這樣做?

這里的問題在於誤解會話范圍的夾具是什么。

要知道哪些測試和自動固定裝置確實存在,pytest需要導入測試文件和conftest插件。 然后它會掃描導入的模塊,並查找夾具和測試函數以及測試類等。這在pytest術語中稱為“集合”。

只有在收集完所有測試之后,pytest才會決定執行它們,並安排執行計划,特別是在准備好燈具時。 會話范圍的裝置首先准備好並在最后進行拆解 - 在任何測試開始之前,並且在所有測試完成之后。

但是,導入測試文件和conftest會假定執行這些模塊 - 導入任何其他與pytest無關的Python模塊。

因此,當您從測試文件中import reporter時,或者即使將該全局變量直接放入測試文件中,也會執行此模塊,並嘗試使用env變量。 但是燈具還沒有被執行(並且pytest還不知道它們的存在)。 因此,它失敗了。

即使您將從測試函數內部import reporter ,這也無濟於事,因為pytest可能會在收集階段之前嘗試導入該reporter.py模塊。 由於缺少測試函數/類,Pytest會將其過濾掉,但導入嘗試將完成並將失敗。

這里最好的解決方案是將客戶端“打包”到一個夾具中並使用該夾具而不是全局變量。

pytest 6.2 開始,您可以直接使用MonkeyPatch對象而不是monkeypatch固定裝置,作為實例或上下文管理器。

(謝爾蓋已經提供了關於“為什么”問題的堅實背景;這試圖解決“如何”。)

上下文管理器(推薦):

因為與monkeypatch固定裝置不同,直接創建的實例不會自動undo() -ed。

# test_reporter.py

from pytest import MonkeyPatch


def test_get_client_username():
    with MonkeyPatch.context() as mp:
        mp.setenv('INFLUXCLOUD_HOST', 'host')
        mp.setenv('INFLUXCLOUD_USERNAME', 'username')
        mp.setenv('INFLUXCLOUD_PASSWORD', 'password')

        from src.reporter import influxdb_client

        assert influxdb_client._username == 'username'

直接使用實例:

# conftest.py

from pytest import MonkeyPatch


mp = pytest.MonkeyPatch()
mp.setenv('INFLUXCLOUD_HOST', 'host')
mp.setenv('INFLUXCLOUD_USERNAME', 'username')
mp.setenv('INFLUXCLOUD_PASSWORD', 'password')

假設文件結構供參考:

src/
    reporter.py
    __init__.py
test/
    conftest.py
    test_reporter.py

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM