导入的 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
我正在尝试设置 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