母工作流二次开发测试与回归¶
本篇用于指导二次开发者为当前 Workflow Builder 母工作流编写、选择和运行测试。Workflow Builder 的模型流程耗时较高,因此母代码修改应优先由确定性回归发现协议错误,再用少量真实业务运行验证母 Agent行为和生成产物。不能把每次完整生成当成最基本的单元测试。
二次开发目标¶
开发者应能根据修改责任域选择最小回归、为缺陷建立先失败后通过的 fixture、把新脚本接入 regression Makefile,并记录范围外既有失败。测试重点是证明母模块的输入、输出、边界和兼容,不是通过人工修复测试工作区获得绿色返回码。
母工作流修改入口¶
测试入口是根 make regression 与 regression/Makefile。各脚本直接调用母生成器或评估控制 core,在临时 workspace 中检查产物。涉及 UCAgent import 的测试必须使用项目 venv;真实流程验证则新建独立业务根,以监督策略观察母工作流是否能自行生成正确结果。
回归入口¶
regression/ 中的脚本覆盖构建设计、交付契约、写入边界、评估拆分、增量控制、控制台和生成器行为。开发者应根据修改范围先运行最相关脚本,再运行总入口。
分层测试¶
- 语法测试:Python 编译、YAML/JSON 解析、Makefile dry run。
- 单元测试:纯函数、schema 校验、路径处理、状态转换和序列化。
- 组件回归:用固定 test_data 运行某个生成器并检查产物。
- 协议回归:工具、Checker、GuideDoc、config 和环境设施之间的一致性。
- 真实工作区验证:选择一个小业务运行关键阶段,观察重试、耗时和最终产物。
测试数据原则¶
fixture 应小、稳定、单一错误。不要依赖网络、模型随机输出、当前用户名或绝对路径。负向样例一次只破坏目标规则。需要外部命令时使用白名单和可检测的跳过条件,并在报告中区分“未安装”与“测试失败”。
文档回归¶
文档检查应验证规定文件存在、Markdown 相对链接和图片存在、必要标题和命令出现。它不能只统计字数,也不能把代码块重复内容算成详细度证明。QuickStart 中的 Make 目标必须在当前 Makefile 中存在。
修改后的最小测试集合¶
| 修改区域 | 最小验证 |
|---|---|
| Makefile 或 setup.py | 配置 dry-run、check、变量覆盖、Make help |
| Tool 生成器 | 工具组件回归、注册测试、总回归 |
| Checker 生成器 | 实例化、正反 fixture、阶段注册、总回归 |
| GuideDoc/config | YAML 解析、引用存在性、阶段检查回归 |
| 评估控制 | 报告 CRUD、聚合、审批状态、权限边界 |
| 增量部署 | run 隔离、候选复制、备份、原子替换、恢复 |
| 控制台 | API 测试、结构编辑、过滤、删除、端口冲突 |
真实运行验收¶
真实运行时记录每阶段开始结束、失败次数、Checker 消息和产物变化。若阶段很慢,先确认是否仍在产生有效工具调用;只有确定母工作流问题时才修改规则。监督 Agent 不应直接代写子工作流产物,否则运行结果失去检验价值。
完成后检查 git diff,确保没有把工作区产物、.ucagent 历史、tmp/、本地配置或浏览器 profile 提交到母仓库。
regression Makefile 代码分析与结构¶
regression/Makefile 把每类协议测试定义为独立 target,再由 all 聚合。根 Makefile 的 regression 目标显式传入 UCAgent 虚拟环境 Python,避免系统 Python 版本和依赖与项目不一致。
每个 target 都从 Workflow Builder 根运行,使相对 test_data 和模块路径一致。新增回归脚本后要加入 .PHONY 和 all,否则开发者只跑 make regression 时不会执行。依赖 UCAgent 模块的脚本必须使用传入的 venv Python;纯文档脚本可以用同一解释器以保持一致。
delivery contract 回归¶
run_delivery_contract_regression.py 是范围最大的确定性测试。它构造 workflow build 数据、生成完整工作流,并检查固定交付物、Make 目标、config、环境、文档、工具、Checker 和运行契约。适合发现新增模板破坏整体结构,但断言多,失败时要定位到具体契约而不是盲目更新预期字符串。
当前该脚本存在一个既有断言,要求初始任务包含“禁止调用不存在的 ListFiles”。如果源码规则已经变化而测试未同步,应单独审查究竟是实现回归还是陈旧断言。本轮文档扩充只记录它,不借机修改母任务语义。
stability 与 living plan 回归¶
run_builder_stability_regression.py 验证重复构建、已有文件策略和生成结果稳定性。对于基于哈希的工具生成状态,第一次与第二次运行应产生可解释的 created/skipped,而不是每次无条件重写。
run_living_plan_regression.py 验证实现计划的阶段标记、追加行为和前序内容保护。新增阶段名或标记语法时必须增加相应 fixture,确保后阶段不能覆盖前阶段“问题与处理”。
Checker 与 requirements 回归¶
run_checker_description_regression.py 生成 Checker 后 import 类并检查 description/docstring,能发现“源码存在但 UCAgent 报 No description”的问题。运行它必须使用项目虚拟环境,否则系统 Python 可能因 typing.NotRequired 或依赖版本失败,这属于测试环境错误而非 Checker 业务失败。
run_requirement_template_contract_regression.py 验证用户需求模板能表达可复用模板、工具、Checker、环境和文档要求。修改 guide 模板或 manifest schema 时,应增加新字段的正向示例和缺失字段负向示例。
写入边界与评估拆分回归¶
run_write_boundary_regression.py 检查工作区初始化、history 权限恢复、tmp 清理和禁止越界写入。新增清理逻辑时必须证明不会删除 eval/、res/、input/、当前 inc run 或 change history。
run_evaluation_split_regression.py 验证 tools/checkers/flow/env 职责、JSON store、审批、增量 run、候选部署和报告聚合。它不应启动昂贵真实模型流程,而用固定工作区和工具直接调用证明控制逻辑。
控制台回归代码模式¶
run_review_ui_regression.py 在临时端口启动本地服务,通过 HTTP 请求检查 meta、state、设计文件、结构编辑、审批、建议、历史恢复和删除。测试还主动请求符号链接和 ../ 越界路径,预期返回 400。
控制台测试应在退出时关闭服务器和浏览器 profile。tmp 中 lock 被浏览器并发删除时,清理器要容忍 FileNotFoundError;但服务线程未停止、端口仍监听则必须失败。
如何编写单一变量 fixture¶
先构造最小合法基线,再复制并只改变目标字段。例如测试 reference 不能是目录时,valid spec 使用 reports/result.json,invalid spec 只把它改为 reports/。不要同时删除 stage name、改错 template 和加入绝对路径,否则失败可能来自任意规则。
每个负向测试要断言稳定错误码或关键字段,不只断言“抛了异常”。正向测试还要检查实际文件内容、注册或哈希,不能只看函数没有抛错。
源码模式:regression/run_write_boundary_regression.py 等脚本采用临时工作区、显式调用和断言。
临时目录隔离机器状态并在结束后清理;测试同时断言应创建和绝不应创建的文件,才能证明写入边界。需要保留失败产物调试时,可由显式环境变量选择保留目录,默认回归不应污染仓库。
Tool 测试设计¶
Tool 至少需要 spec validation、source compile/import、参数模型、正常调用、边界调用、失败结构、路径逃逸和重复运行。涉及外部程序时使用可控小命令、超时和临时 cwd。网络获取工具应把下载器与业务解析分开,用本地响应 fixture 测试,不在回归中依赖公网。
对生成器测试还要验证 config 注册和 generation state。修改已有文件后再次生成,断言 preserve/replace 策略符合设计。多个工具批量生成时检查注册没有丢项或重复。
Checker 测试设计¶
Checker 每项业务规则都要有正向和单一负向证据。先测试类可 import、继承 Checker、description/docstring 非空和构造参数匹配,再调用 check。异常输入应返回 (False, evidence),而不是让 runner 崩溃。
命令 Checker测试白名单拒绝、预期返回码、非预期返回码和超时。文件 Checker 测试相对路径、绝对路径、..、符号链接和缺失文件。结构 Checker 测试顶层类型、字段类型、缺字段和边界值。
GuideDoc 与 config 测试设计¶
GuideDoc 测试显式 section id、旧标题映射、缺失章节、重复章节、marker、有效正文和注册。用户文档的代码块不能计入正文长度。生成后读取 Markdown,确认命令和路径与实际 Makefile/config 一致。
config 测试未知 placeholder、双花括号、循环覆盖、父流程路径泄漏、目录 file contract、未来 reference、未知 Checker、参数不匹配和阶段衔接。YAML 可解析只是第一层,最终还应执行静态 config checker。
增量与版本管理测试设计¶
在临时 workspace 初始化 eval 文件和两个正式文件,创建批准、启动 run、stage 候选并部署。断言正式哈希、backup 哈希、applied changes、run id 和 approval mapping。然后模拟第二个文件替换失败,确认第一个回滚。最后测试恢复会保存当前版本,删除只移除目标记录。
部署后回归失败的状态机测试必须证明流程不会停在 pending 或重复同一命令。可以用固定失败/成功脚本和 attempt 计数模拟两次修复。
从缺陷到回归的完整例子¶
问题:config generator 允许 reference_files: [docs/]。先写最小 invalid spec 并确认旧代码错误通过;在 _file_contract_errors() 增加具体文件判断;断言错误包含字段位置;再加入 valid 文件路径确保没有误报。随后运行 config component、delivery contract、evaluation split 和真实生成工作流 make check。
文档同步说明为什么目录不能作为 reference、如何列出确定存在文件,以及未知未来文件不能提前引用。这样回归保护机制,文档指导 Agent,评估规则还能发现历史产物。
性能与真实性¶
确定性回归应尽可能在秒级完成,不调用模型。真实业务测试用于观察 Agent 是否理解任务、是否连续失败和产物质量,两者不能互相替代。为了加快真实流程可以批量生成后检查、限制读取和并行独立工具,但不能由监督者手工生成结果。
测试报告需记录命令、解释器、返回码和已知失败。若完整回归在既有问题提前停止,应单独运行剩余 target,并明确哪些通过,不能笼统写“回归失败”或“全部通过”。
回归扩展规则¶
新增组件时优先把测试加入现有责任 target;只有形成独立协议、运行成本或依赖边界时才新增 target。新 target 必须进入 all,使用传入解释器,隔离工作区,并在 README说明它保护的行为。删除功能时同时删除已经失去对象的断言,不能让陈旧测试迫使实现保留无意义文字。
现有回归脚本完整目录¶
下表以 regression/run_*regression.py 的真实文件为准。二次开发者应先把缺陷放入责任最相近的脚本,只有无法归属时才建新脚本。
| 脚本 | 保护的母工作流契约 | 扩展方法 |
|---|---|---|
run_builder_runtime_directory_regression.py | Builder 创建的子工作流运行目录、Python package/import 骨架和基本路径归属 | 新增固定运行目录或 package 时,在临时 workspace 构建并 import 真实生成类,不只查文件名。 |
run_builder_stability_regression.py | 限制命令、计划追加、GuideDoc 契约、Tool 生成安全和重复构建稳定性 | 对 preserve/replace、哈希、路径或详细度算法的修改,增加首次/第二次/文件漂移三组对照。 |
run_checker_description_regression.py | 生成 Checker 的类 description、方法 docstring、import 和基本运行协议 | 新增 renderer/rule type 时生成该类型并真实 import,防止再出现 No description provided 运行失败。 |
run_delivery_contract_regression.py | 从中心设计到完整子工作流的广泛交付契约:骨架、config、Tool、Checker、GuideDoc、docs、Make 和迁移 | 只增加真正的跨组件不变量;单模块细节放入组件脚本,避免陈旧提示字符串成为伪契约。 |
run_documentation_regression.py | 本 docs/ 信息架构、链接/图片、开发文档详细度、源码分析与动态组件清单 | 新文档加入 REQUIRED;新 stage/UCTool/Checker/GuideDoc/regression 应通过动态盘点要求对应开发文档出现类名或文件名。 |
run_environment_setup_regression.py | Workflow Builder 根 setup.py、.workflow_builder/local.mk、交互/非交互配置、命令行覆盖和秘密边界 | 为每个新环境字段测试默认、持久化、show/check、非法值和旧配置兼容。 |
run_evaluation_split_regression.py | 五类评估拆分、JSON store、审批新鲜度、inc run 隔离、候选、部署、备份恢复和报告聚合 | 新 JSON 类型、批准动作、状态转移或 deploy mapping 优先加在这里,必须断言持久化结果与文件哈希。 |
run_living_plan_regression.py | workflow_implementation_plan.md 阶段 marker、必需章节、追加幂等与前序不覆盖 | 新阶段或计划章节要有正常追加、同阶段重试、缺 marker、重复 marker 和覆盖前序负例。 |
run_requirement_template_contract_regression.py | requirements manifest/输入 guide 模板对 Tool、Checker、环境、文档、模板和需求追踪的表达能力 | 新需求类别增加正向最小映射与单字段缺失负例,不把某业务名当通用必需项。 |
run_review_ui_regression.py | 控制台 HTTP API、报告筛选/审批/建议/删除、构建设计阅读编辑、工作流树、进度、历史恢复/删除和路径安全 | 前端变化不能只测 DOM;请求 API 后重新读 JSON/YAML/目标文件,同时覆盖 revision 冲突和越界路径 400。 |
run_write_boundary_regression.py | 母 Agent、评估、增量、history 权限守护和 tmp/ 清理的可写范围 | 新工具可写根或清理规则必须增加允许正例和 ../绝对路径/符号链接/无关目录不受影响负例。 |
当前 regression Makefile 与显式运行¶
regression/Makefile 的 all 当前聚合 contract、stability、checker descriptions、requirement templates、living plan、write boundaries、evaluation split、review UI、documentation 和 environment setup。二次开发时不能只看目录中有脚本就假定它已被 make regression 执行;run_builder_runtime_directory_regression.py 必须确认是否已接入目前 Makefile,未接入时应显式运行:
如果一份脚本是必需交付门禁,正确修改是在 regression/Makefile 增 target 并加入 all,同时更新本清单;不是仅在文档告诉用户永远手动多跑一条命令。对昂贵、依赖网络/模型或专用硬件的测试,则应保留显式 target 并清楚标注不进入确定性 all 的原因。
新增回归的代码模式¶
每份脚本使用 tempfile.TemporaryDirectory() 或同等隔离,通过公开 core/UCTool 创建真实产物,再读回文件断言。下面的结构是最小模式,实际脚本应对错误码和持久化状态做具体断言:
如果项目没有使用 pytest,保持现有脚本的纯 assert/main() 风格,不要为一个用例引入新测试框架。子进程必须传参数数组、cwd、timeout、text/capture_output,断言 return code 并在失败消息中保留有限 stdout/stderr。线程、HTTP server 或浏览器进程必须在 finally 中关闭,不得留下端口和 profile lock。
二次开发验收顺序¶
- 先运行修改模块的
py_compile与 YAML/JSON 解析,排除低成本语法失败。 - 运行上表中责任最接近的一到三份回归,确认新负例旧实现会失败、新实现会通过。
- 运行
make regression,如已知失败使all提前终止,记录精确断言并单独运行后续 target。 - 生成一个全新且规模可控的业务工作流,用监督策略观察失败次数、产物时间戳和上下文压缩,不替 Agent 生成子产物。
- 对生成的子工作流运行自身
make check,然后选择对应评估和增量闭环,确认母修改没有只让静态回归通过。
继续阅读¶
完成母工作流修改后,开发者还需要知道“生成的子工作流中哪些组件应怎样继续开发”。请继续阅读工作流产物二次开发指南。