我需要一种方法来生成一个字典,其中包含给定目录中每个 pytest 模块/文件的唯一路径。在运行任何测试来定义文件路径之前,它需要可访问:
TEST_DIRS = {}
path1 = TEST_DIRS['path']
path2 = TEST_DIRS['input']
def test_something():
target = path1 / 'input_file'
....
def test_another_thing():
....
还应该有像conftest这样的目录配置文件来执行每个模块所需的生成操作。生成器将根据测试名称创建目录。
我尝试使用
conftest.py
文件和
pytest_collection_modify_items
但它仍然使 TEST_DIRS 仅在测试函数内部而不是在它们之前工作。
def pytest_collection_modifyitems(items):
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
for item in items:
module_name = item.module.__name__
test_paths = {
key: value.format(test_name=module_name, timestamp=timestamp)
for key, value in BASE_TEST_DIRS.items()
}
test_paths = {
key: home / Path(value)
for key, value in test_paths.items()
}
for key, path in test_paths.items():
if key.startswith('output'):
if not os.path.exists(path):
os.makedirs(path)
item.module.TEST_DIRS = test_paths
可以通过多种方式使用
pytest
为每个模块生成和加载字典。以下是两种方法:
方法 1:使用 pytest Fixtures
这种方法使用
pytest
fixtures 来生成字典并将其作为参数传递给测试函数。这种方法的好处是它更明确,并且更容易理解每个测试函数中发生了什么。
import pytest
from pathlib import Path
BASE_TEST_DIRS = {
"path": "tests/{test_name}/path",
"input": "tests/{test_name}/input",
}
@pytest.fixture(scope="module")
def test_dirs(request):
"""为每个测试模块生成一个唯一的测试目录字典."""
module_name = request.module.__name__
test_paths = {
key: value.format(test_name=module_name)
for key, value in BASE_TEST_DIRS.items()
}
test_paths = {
key: Path(value)
for key, value in test_paths.items()
}
for key, path in test_paths.items():
if key.startswith('output'):
path.mkdir(parents=True, exist_ok=True)
return test_paths
def test_something(test_dirs):
target = test_dirs['path'] / 'input_file'
# ... your test logic here ...
def test_another_thing(test_dirs):
# ... your test logic here ...
方法 2:使用 pytest hooks 和 monkeypatch
这种方法使用
pytest
hooks 在测试收集阶段修改模块的全局命名空间。 虽然这种方法更隐蔽,但它可能更难调试。
# conftest.py
from pathlib import Path
BASE_TEST_DIRS = {
"path": "tests/{test_name}/path",
"input": "tests/{test_name}/input",
}
def pytest_collection_modifyitems(items):
"""为每个测试模块生成一个唯一的测试目录字典."""
for item in items:
module_name = item.module.__name__
test_paths = {
key: value.format(test_name=module_name)
for key, value in BASE_TEST_DIRS.items()
}
test_paths = {
key: Path(value)
for key, value in test_paths.items()
}
for key, path in test_paths.items():
if key.startswith('output'):
path.mkdir(parents=True, exist_ok=True)
# 使用 monkeypatch 将字典添加到模块的全局命名空间中
monkeypatch.setattr(item.module, "TEST_DIRS", test_paths)
# test_module.py
def test_something():
target = TEST_DIRS['path'] / 'input_file'
# ... your test logic here ...
def test_another_thing():
# ... your test logic here ...
这两种方法都将为每个测试模块生成一个唯一的
TEST_DIRS
字典。 选择最适合的项目结构和编码风格的方法。