feat(config): isolate config and database via HAOCODE_CONFIG_FILE override

core/config_paths.py resolves a single override so tests and multiple instances can run against isolated temp config/db without touching user data.
This commit is contained in:
2026-09-17 16:40:02 +08:00
parent a7412824e0
commit ce56c77023
3 changed files with 410 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""tests/_test_env.py —— 自动化测试的统一临时环境(P0-01 新增)
铁律(VERIFICATION.md §凭据与运行数据隔离):
1. 每个测试进程独立临时目录 + 最小临时配置;
2. 在 import 任何可能间接加载 MainWindow 的模块之前设置 HAOCODE_CONFIG_FILE
3. 在 import MainWindow 之前把 core.db_manager._DEFAULT_DB 指向临时数据库;
4. 写入、迁移、附件和截图产物只落到临时目录。
用法(放在测试文件顶部、任何 UI import 之前):
from tests._test_env import isolate
isolate("bashpanel", config={"providers": {}, "mode_switch": True})
说明:
· 临时目录按 进程 pid 隔离,测试进程互不干扰;
· 默认临时配置为最小可启动结构(空 providers + 测试 provider);
· 本模块不 import 任何 PyQt 模块,可在无 GUI 环境中安全调用。
"""
import json
import os
import sys
import tempfile
_TESTS_DIR = os.path.dirname(os.path.abspath(__file__))
_ROOT = os.path.dirname(_TESTS_DIR)
if _ROOT not in sys.path:
sys.path.insert(0, _ROOT)
def default_config() -> dict:
"""最小可启动临时配置(不含任何真实凭据)。"""
return {
"providers": {
"testprov": {
"api_key": "test-key-not-real",
"base_url": "http://127.0.0.1:9/v1",
"models": ["test-model"],
"model_contexts": {"test-model": 100000},
}
},
"default_provider": "testprov",
"default_model": "test-model",
}
def isolate(tag: str = "t", config: dict | None = None) -> dict:
"""创建临时配置 + 临时数据库并完成重定向。必须在 import MainWindow 之前调用。
返回 {"base": 临时目录, "config": 临时配置路径, "db": 临时数据库路径}。
"""
base = os.path.join(tempfile.gettempdir(),
f"haocode_test_{tag}_{os.getpid()}")
os.makedirs(base, exist_ok=True)
cfg_path = os.path.join(base, "config.json")
with open(cfg_path, "w", encoding="utf-8") as f:
json.dump(config if config is not None else default_config(),
f, ensure_ascii=False, indent=2)
db_path = os.path.join(base, "chat_history.db")
for p in (db_path, db_path + "-wal", db_path + "-shm"):
if os.path.exists(p):
os.remove(p)
os.environ["HAOCODE_CONFIG_FILE"] = cfg_path
# P1-03QtWebEngine 独立 profile 重定向到临时目录(源码运行才在 data/webengine/
os.environ.setdefault("HAOCODE_WEBENGINE_PROFILE_DIR", os.path.join(base, "webengine_profile"))
import core.db_manager as _dbm
_dbm._DEFAULT_DB = db_path
return {"base": base, "config": cfg_path, "db": db_path}