解決 pytest 的 conftest.py 文件過大問題。
1. 項目目錄結構
project_name
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── project_name
│ ├── __init__.py
│ ├── testing
│ │ ├── __init__.py
│ │ ├── fixture.py
├── tests
│ ├── __init__.py
│ ├── conftest.py
│ ├── fixtures
│ │ ├── __init__.py
│ │ ├── cache.py
│ │ ├── loop.py
│ │ ├── net.py
│ │ ├── request.py
│ │ ├── signal.py
│ │ └── thread.py
2. 使用 pytest_plugins
加載 fixture
在 conftest.py
中添加 pytest_plugins
配置,使用 append_pytest_fixture_plugins
方法加載 fixtures
目錄中的 fixture
,fixtures
目錄下的子目錄也會一起加載。
from pathlib import Pathfrom project_name.testing.fixture import append_pytest_fixture_pluginspath = Path(__file__).parent / "fixtures"
root_path = Path(__file__).parent.parent
pytest_plugins = append_pytest_fixture_plugins(root_path, path)
通過這種方式,可以將 conftest.py
中的 fixtures
拆分到多個文件中,方便維護和管理。拆分的文件如下,
│ ├── fixtures
│ │ ├── __init__.py
│ │ ├── cache.py
│ │ ├── loop.py
│ │ ├── net.py
│ │ ├── request.py
│ │ ├── signal.py
│ │ └── thread.py
3. append_pytest_fixture_plugins
函數實現
from pathlib import Path
from typing import Listimport pytestdef append_pytest_fixture_plugins(root_path: Path, path: Path) -> List[str]:"""添加額外的 fixtures"""def refactor(_path: str) -> str:return _path.strip("/").strip("\\").replace("/", ".").replace("\\", ".").replace(".py", "")paths = []prefix = str(root_path)prefix_len = len(prefix)# 遞歸遍歷目錄下所有文件for path in path.iterdir():if not path.is_file():continuefilename = path.name# 去掉 __init_.pyif filename.startswith("__"):continue# 過濾掉非 python 文件if filename.endswith(".py"):paths.append(refactor(str(path)[prefix_len:]))return paths
單元測試如下
from pathlib import Pathfrom project_name.testing.fixture import append_pytest_fixture_pluginsdef test_append_pytest_fixture_plugins():path = Path(__file__).parent / "fixtures"root_path = Path(__file__).parent.parentactual = append_pytest_fixture_plugins(root_path, path)expect = ["tests.fixtures.thread","tests.fixtures.signal","tests.fixtures.net","tests.fixtures.request","tests.fixtures.cache","tests.fixtures.loop",]assert actual == expect