如何在Pytest中修改测试函数的文件路径?问题排查与优化
问题中的代码片段
config.py
import os from some_file import PROJECT_PATH DATA_FILES = os.getenv("DATA_FILES", f"{PROJECT_PATH}/data/elements")
业务模块示例
def function_1(): file_path = f'{DATA_FILES}/Image_{file_id}_{i + 1}.png' # 假设file_id、i为已定义变量
Pytest测试文件
from project_file import config def test_function(monkeypatch): monkeypatch.setattr(config, "DATA_FILES", f"{PROJECT_PATH}/tests/test_data/file_1") print(config.DATA_FILES) function_1()
问题原因
业务模块中的function_1若通过from config import DATA_FILES方式导入变量,本质是值拷贝:模块加载时会把DATA_FILES的当前值复制到业务模块的命名空间,后续修改config模块中的DATA_FILES,不会同步更新业务模块里的旧值。你看到print(config.DATA_FILES)显示修改成功,是因为直接访问的是config模块本身的变量,但function_1用的是自己命名空间里的静态副本。
改进方案
方案1:动态引用config模块变量
修改业务模块代码,让function_1每次执行时直接读取config模块的最新值:
# 业务模块中导入整个config模块 import config def function_1(): file_path = f'{config.DATA_FILES}/Image_{file_id}_{i + 1}.png'
这样每次调用function_1都会直接访问config模块的DATA_FILES,monkeypatch的修改能直接生效。
方案2:封装配置为可调用对象
把配置改成函数,确保每次获取的都是最新值:
# config.py import os from some_file import PROJECT_PATH def get_data_files(): return os.getenv("DATA_FILES", f"{PROJECT_PATH}/data/elements") # 业务模块 from config import get_data_files def function_1(): file_path = f'{get_data_files()}/Image_{file_id}_{i + 1}.png'
测试时直接monkeypatch这个函数:
def test_function(monkeypatch): monkeypatch.setattr(config, "get_data_files", lambda: f"{PROJECT_PATH}/tests/test_data/file_1") function_1()
更便捷的替代方式
1. 直接修改环境变量
原代码中DATA_FILES从环境变量读取,测试时可直接monkeypatch环境变量(前提是配置为动态读取,比如用方案2的函数封装):
def test_function(monkeypatch): monkeypatch.setenv("DATA_FILES", f"{PROJECT_PATH}/tests/test_data/file_1") function_1()
2. 用Pytest Fixture复用配置修改
把monkeypatch逻辑封装成Fixture,方便多个测试用例复用:
import pytest from project_file import config @pytest.fixture def test_data_files(monkeypatch, PROJECT_PATH): test_path = f"{PROJECT_PATH}/tests/test_data/file_1" monkeypatch.setattr(config, "DATA_FILES", test_path) return test_path def test_function(test_data_files): function_1()
3. 使用配置类管理变量
把配置放到类中,修改类属性更直观:
# config.py import os from some_file import PROJECT_PATH class Config: DATA_FILES = os.getenv("DATA_FILES", f"{PROJECT_PATH}/data/elements") # 业务模块 from config import Config def function_1(): file_path = f'{Config.DATA_FILES}/Image_{file_id}_{i + 1}.png' # 测试代码 def test_function(monkeypatch): monkeypatch.setattr(Config, "DATA_FILES", f"{PROJECT_PATH}/tests/test_data/file_1") function_1()
内容的提问来源于stack exchange,提问作者Mr.Slow
相关产品推荐
相关产品推荐

