提问人:741852963 提问时间:10/25/2023 更新时间:10/25/2023 访问量:54
为什么在 pytest 中未覆盖环境变量?
Why are environment variables not being overridden in pytest?
问:
我正在为一个基本的 flask 应用程序编写一些单元测试。 目前我正在测试 config.py 文件(主要是为了学习,但也是为了测试依赖于环境的数据库配置)。
该文件如下所示:
config.py
from os import environ as env
from dotenv import load_dotenv
load_dotenv()
class Config:
ENVIRONMENT = env['CONFIG_MODE']
SQLALCHEMY_TRACK_MODIFICATIONS = True
SECRET_KEY = env['SECRET_KEY']
# app deployed on Heroku - heroku sets DATABASE_URL to postgres://, SQLALCHEMY needs postgresql://
if ENVIRONMENT == "development":
SQLALCHEMY_DATABASE_URI = env['DEVELOPMENT_DATABASE_URL']
else:
SQLALCHEMY_DATABASE_URI = env.get('DATABASE_URL').replace("://", "ql://", 1)
这将从 .env 文件中提取环境变量
.env 域名
CONFIG_MODE = 'development'
DEVELOPMENT_DATABASE_URL = 'postgresql://usr:pwd@localhost:5432/db'
FLASK_APP=app
SECRET_KEY='XXX'
我设置了一个基本的 pytest 单元测试来检查SQLALCHEMY_DATABASE_URL是否设置正确,具体取决于CONFIG_MODE env 变量是“开发”还是“非开发”。
test_config.py
import os
class TestConfigDev:
development_database_url = 'development_database_url'
os.environ['DEVELOPMENT_DATABASE_URL'] = development_database_url
os.environ['CONFIG_MODE'] = 'development'
from service_authentication.api.config import Config
config = Config
def test_sqlalchemy_track_modifications(self):
"""
GIVEN: SQLALCHEMY_TRACK_MODIFICATIONS variable exists
WHEN: it is queried
THEN: it is True
"""
self.sqlalchemy_track_modifications = self.config.SQLALCHEMY_TRACK_MODIFICATIONS
assert self.sqlalchemy_track_modifications
def test_sqlalchemy_database_uri_dev(self):
"""
GIVEN: CONFIG_MODE is development
AND GIVEN: DEVELOPMENT_DATABASE_URL is set
AND GIVEN: SQLALCHEMY_DATABASE_URI variable exists
WHEN: it is queried
THEN: it returns the DEVELOPMENT_DATABASE_URL
"""
self.sqlalchemy_database_uri = self.config.SQLALCHEMY_DATABASE_URI
assert self.sqlalchemy_database_uri == self.development_database_url
class TestConfigNotDev:
database_url = 'postgres://database_url'
os.environ['DATABASE_URL'] = database_url
os.environ['CONFIG_MODE'] = 'not_development'
from service_authentication.api.config import Config
config = Config
def test_sqlalchemy_database_uri_not_dev(self):
"""
GIVEN: CONFIG_MODE is not development
AND GIVEN: DATABASE_URL is set
AND GIVEN: SQLALCHEMY_DATABASE_URI variable exists
WHEN: it is queried
THEN: it returns the modified DATABASE_URL
"""
self.sqlalchemy_database_uri = self.config.SQLALCHEMY_DATABASE_URI
self.database_url = self.database_url.replace("://", "ql://", 1)
assert self.config.ENVIRONMENT == 'not_development'
assert self.sqlalchemy_database_uri == self.database_url
TestConfigDev 测试通过,没有问题。
TestConfigNotDev 测试失败 - 尽管 ENVIRONMENT 变量在类定义中被重写为“not_development”,但仍设置为“development”。
我已将CONFIG_MODE作为 .env 中的变量集删除 - 将其实例化隔离到 test_config.py 文件中。问题仍然存在。
我尝试将它们分成两个测试文件(test_config_dev.py 和 test_config_not_dev.py)。以先运行者为准,设置 ENVIRONMENT 变量。
考虑到问题是 env 变量是在运行时设置的,我尝试在覆盖 env 变量之前和之后在 TestConfigNotDev 类中使用,但它仍然失败,因为 ENVIRONMENT 变量保持为“开发”。import os
importlib.reload(os)
奇怪的是,DEVELOPMENT_DATABASE_URL变量在 TestConfigDev 中被重写。
这意味着环境变量的设置方式正在发生其他事情,而我忽略了这一点。鉴于环境变量的基本情况,在我进一步讨论之前,我想先了解这里发生了什么。
答:
来自 MrBean Bremen 的评论:
“您不是在测试期间更改环境变量,而是在加载时更改环境变量。你需要把它们设置在一个类范围的固定装置中(可能使用monkeypatch.setenv())。
评论
monkeypatch.setenv()
monkeypatch.setenv()