"""验证迁移前状态证据采集器只读取 Git 元数据。""" # 导入测试所需的标准库 JSON、路径和子进程结果类型。 import json from pathlib import Path from subprocess import CompletedProcess # 导入 pytest 补丁类型以及待验证的预检工具接口。 from pytest import MonkeyPatch from tools.foundation_migration_preflight import ( collect_workspace_state, run_git, write_preflight_report, ) # 验证未跟踪客服文件会被记录,且采集结果不含环境变量名称或值。 def test_collect_workspace_state_records_untracked_paths_without_environment_values( tmp_path: Path, ) -> None: # 构造确定性的 Git 命令替身,不调用真实 Git 或环境变量。 def fake_git_runner(_worktree: Path, *args: str) -> str: # 为分支查询返回客服功能分支名称。 if args == ("branch", "--show-current"): return "feature/customer-service-rag\n" # 为提交查询返回固定的非敏感提交标识。 if args == ("rev-parse", "HEAD"): return "abc123\n" # 为状态查询返回一个未跟踪客服文件。 if args == ("status", "--short"): return "?? app/service/agent/customer_service_agent.py\n" # 防止测试静默接受未定义的 Git 查询。 raise AssertionError(f"unexpected git arguments: {args}") # 使用替身采集临时工作区的只读状态。 state = collect_workspace_state(tmp_path, runner=fake_git_runner) # 断言采集到预期的分支名称。 assert state["branch"] == "feature/customer-service-rag" # 断言未跟踪客服文件完整保留在状态清单中。 assert state["status"] == ["?? app/service/agent/customer_service_agent.py"] # 断言序列化结果不包含任何环境变量敏感字段。 assert "MYSQL_PASSWORD" not in json.dumps(state) # 验证报告写入器只输出传入的非敏感 Git 状态结构。 def test_write_preflight_report_persists_utf8_json(tmp_path: Path) -> None: # 指定临时报告文件,避免写入任何真实工作目录。 report_path = tmp_path / "preflight.json" # 构造只含安全 Git 元数据的状态条目。 states = [{"path": "D:/workspace", "branch": "develop", "head": "abc123", "status": []}] # 写入迁移前报告。 write_preflight_report(report_path, states) # 以 UTF-8 读取并解析报告正文。 report = json.loads(report_path.read_text(encoding="utf-8")) # 断言报告保留原始状态条目。 assert report == states # 验证每次 Git 查询只信任当前显式工作区,而不写入全局 Git 配置。 def test_run_git_scopes_safe_directory_to_the_requested_worktree( tmp_path: Path, monkeypatch: MonkeyPatch, ) -> None: # 保存被测函数交给子进程层的命令参数。 captured_commands: list[list[str]] = [] # 构造返回固定分支名的无副作用子进程替身。 def fake_run(command: list[str], **_kwargs: object) -> CompletedProcess[str]: # 记录命令以便后续断言安全目录范围。 captured_commands.append(command) # 返回模拟的 Git 成功结果。 return CompletedProcess(command, 0, "develop\n", "") # 让测试不执行真实 Git。 monkeypatch.setattr("tools.foundation_migration_preflight.subprocess.run", fake_run) # 执行一个受限 Git 分支查询。 output = run_git(tmp_path, "branch", "--show-current") # 断言调用仍返回 Git 输出。 assert output == "develop\n" # 断言命令仅为该临时工作区附加安全目录。 assert captured_commands == [[ "git", "-c", f"safe.directory={tmp_path.resolve().as_posix()}", "-C", str(tmp_path.resolve()), "branch", "--show-current", ]]