用途:把使用 unittest.mock.patch 或 MagicMock 的测试重构为 erk 的 gateway-based fake 模式,核心是让源码通过构造函数(或 Click 上下文)注入网关依赖,测试中改用预置 fake,替代对 shutil.which、subprocess.run 等系统调用的打桩。
主要能力与流程:
一、审计 mock 使用:逐条记录 patch(...) 的目标、系统边界、模拟内容与配置返回值;按测试分组,同一系统边界的多个 mock 宜由单个网关覆盖。
二、网关发现:按“被测行为”而非“被 patch 的函数”识别系统边界,如 shutil.which("claude") 与 subprocess.run(["claude",...]) 归为“与 Claude CLI 交互”,由 PromptExecutor 覆盖。subprocess.run 永远不是正确的网关边界,网关应按工具命名(如 GhCli、CmuxGateway、GitGateway)。先做定向搜索 Grep(pattern="<tool_name>", path="packages/erk-shared/src/erk_shared/gateway/"),再检查已有网关是否已覆盖部分 mock,并核对 fake 是否支持所需返回值、调用记录与 is_available()。
三、规划注入:确认被 mock 代码的调用点、是否已有构造函数参数、生产环境如何装配(通常在 src/erk/core/context.py)。
四、使源码可注入:以关键字参数添加网关(def init(self, *, gateway: GatewayABC)),无默认值,存为 self._gateway,把直接系统调用替换为网关方法调用。Click 命令可用 @click.pass_context 配合 require_github(ctx) 等从上下文取网关。
五、创建新网关(无合适网关时):可选 3 文件(abc、real、fake)或 5 文件(加 dry_run、printing)模式;需完成目录创建、ABC 方法按工具操作命名、real 实现、fake 实现,并在 ErkContext 中加字段、for_test 默认值与生产装配。错误处理上,所有调用方遇错即终止则 raise RuntimeError,部分调用方需分支则返回可判别联合类型。
六、重写测试:移除 patch 导入,构造带预置响应的 fake 并经新构造参数传给被测类,用 fake 属性断言(如 len(executor.prompt_calls) == 1)替代 mock_run.assert_called_once()。pytest 的 monkeypatch.delenv 可保留。
七、验证:运行 uv run pytest <test_file> -v,并对修改的源码做 lint 与类型检查。
限制与注意:勿匹配到错误抽象层级(如只包 subprocess.run 的 ShellRunner、SubprocessGateway、CommandRunner 仍属错误层级);勿忘更新生产装配;一个测试出现多个 patch() 通常提示需要更高层抽象。资料未提供该技能的安装命令、收费信息与支持平台。