导入的 Pytest 环境装置未见 class

Pytest environment fixtures not seen by imported class

我正在尝试设置 pytest,以便每当我 运行 我的测试(本地或 github 操作)时,环境变量都指向我的测试目录中的文件和位置根据用户设置的位置。

问题是,如果我在 test_database 函数中添加一个 ipdb 跟踪并打印 os.getenv('DB_URL'),则夹具更改是可见的,但是断言总是会失败,因为 DataBase 对象始终具有原始的非模拟 url(在 .bash_profile 中设置)。

database.py

import h5py
import os

class DataBase:

    route = os.environ.get('DB_URL')

    def __init__(self):
        self.connected = False

    def connect(self):
        if not connected:
            self.db = h5py.File(self.route, 'r')
            self.connected = True

conftest.py

import os
import pytest

@pytest.fixture(autouse=True)
def mock_test_env(monkeypatch):
    cwd = os.getcwd()
    monkeypatch.setenv('DB_URL', cwd + '/sample_db.hdf5')

test_database.py

import pytest
from repo import DataBase

def test_database():
    db = DataBase()
    import ipdb; ipdb.set_trace()
    '''
    os.getenv('DB_URL') returns cwd + '/sample_db.hdf5'
    db.route returns original database, not the sample one above
    '''
    assert db.connected = False, 'DataBase must be instantiated to connected == False'

如何全局设置环境变量以便所有对象看到相同的环境?

正如其他人在您的评论中提到的那样,class 这个赋值要避免的变量,因为它是一个常量,在扫描导入语句时被赋值。

为了更好地理解这种情况,请尝试将 from repo import DataBase 放在您的方法中

def test_database():

像这样:

import os
import pytest

@pytest.fixture(autouse=True)
def mock_test_env(monkeypatch):
    cwd = os.getcwd()
    monkeypatch.setenv('DB_URL', cwd + '/sample_db.hdf5')

def test_database(mock_test_env):
    from repo import DataBase # <<< This here works
    db = DataBase()
    assert db.route == (os.getcwd() + '/sample_db.hdf5') # Works!

现在,当您将 from repo import Database 放在文件的开头时,pytest 将扫描并开始读取所有导入并开始初始化蓝图并在导入时设置路由器的值。

阅读:

因此,理想的方法是避免可能如此重要的初始化,并在 Database class 的构造函数中对其进行赋值。从而确保它在需要时进行计算。

我觉得,我个人喜欢把它想成 Zen Of Python 中的 Explicit is better than implicit. 并且这样做:

import h5py
import os

class DataBase:

    def __init__(self):
        self.route = os.environ.get('DB_URL')
        self.connected = False

    def connect(self):
        if not connected:
            self.db = h5py.File(self.route, 'r')
            self.connected = True