【发布时间】:2021-05-25 04:36:05
【问题描述】:
我认为最简单的方法是使用我的软件环境作为“测试”重新加载配置模块。
我的代码有一个 config.py,它用作配置处理代码,我在其中定义每个我想运行的每个环境的所有配置设置。
config.py
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(Config):
DATABASE_URI = 'mysql://user@localhost/foo'
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
TESTING = True
config_lookup = dict(
testing=TestingConfig(),
development=DevelopmentConfig(),
production=ProductionConfig(),
)
config = config_lookup[os.getenv('ENVIRONMENT', 'development')]
一种方法可能是使用重新加载:
在我的conftest.py 上,我想确保我的所有测试都按照TestingConfig 运行。
因此我会做这样的事情:
conftest.py
@pytest.fixture(autouse=True)
def cfg():
# Reload the global 'config' instance.
os.environ["ENVIRONMENT"] = "testing"
importlib.reload(sys.modules["config"])
不幸的是,这种方法似乎无法在所有情况下都按预期工作,因为 importlib.reload() 似乎按预期执行。
importlib.reload()重新加载之前导入的模块。参数必须是一个模块对象,所以它必须之前已经成功导入。 阅读更多:importlib Docs
此解决方案可能在第一个实例中有效,但在使用不同类型的导入时会变得很棘手。(对象与子模块)
一个对象被导入
from app.config import config
print('Environment is:',type(config).__name__)
# Environment is:Development <- Wrong
一个模块被导入
import app.config as _
print('Environment is:',type(_.config).__name__)
# Environment is:Testing <-- correct
另一种方法是确保在执行 pytest 时始终设置环境变量:
ENVIRONMENT=testing python -m pytest tests
这不是可取的,因为您可能会忘记附加您的环境。
相关问题:
difference-between-from-x-import-y-and-import-x-yPython Bug
【问题讨论】:
-
目前尚不清楚这是如何失败或您正在寻找什么行为。您能否请edit 澄清这里的实际问题?
-
@tripleee,谢谢。我添加了更多上下文。事实上,给定的方法有效但不可靠,因为它可能会失败,具体取决于您决定如何导入配置以及不同的开发功能。开发人员可能决定导入
from x import y,这将失败。 -
那么您的问题是
reload不会递归地重新加载模块导入的所有内容?这是一个常见的常见问题解答,然后是重复的。 -
嗯,我已经从我尝试过的一种方法中描述了一个问题,但我的问题只是确保我可以正确设置一个 conftest 以在测试环境下运行。
标签: python pytest python-importlib