很多团队做前端回归,最后都会陷入两个极端:
- 要么只做单元测试,覆盖不到真实交互链路;
- 要么只做端到端点点点,脚本又脆得像玻璃。
Odoo 的有意思之处在于,它没有把“前端测试”押宝在单一工具上,而是把几层东西拼在了一起:
web_tour描述用户步骤;tour_service管注册、校验与运行入口;- 自动/交互模式分别承担不同用途;
- Hoot 提供底层测试运行和 DOM 辅助;
- recorder 还能反向帮你生成步骤草稿。
更重要的是,Odoo 明确把一个大问题拉到了台面上:
测试脚本能跑,不代表它稳定;真正麻烦的是选择器和触发条件的非确定性。
这也是它比“随便写个 E2E 脚本”更成熟的地方。
一、web_tour 的核心价值是用“步骤”描述用户意图,而不是只写点击脚本
从 addons/web_tour/static/src/js/tour_step.js 能看到,一个 step 至少包含:
trigger- 可选
run - 可选
timeout - 以及对外展示的内容说明
这背后的心智模型很清楚:
- 先定义在什么 UI 条件下这一步算可执行;
- 再决定执行什么动作。
这和很多脆弱自动化脚本的差异很大。后者往往一上来就“找元素然后点”,忽略了“为什么现在应该点它”。
Odoo 把 trigger 作为第一公民,本质上是在强调:测试不是回放鼠标,而是在验证界面是否进入了正确状态。
二、tour_service 把 tour 当成可注册、可校验的运行时能力
tour_service.js 里会给 web_tour.tours registry 加 schema validation,还统一提供启动入口。
这意味着一个 tour 不是随便 export 一个数组,而是:
- 有明确结构;
- 可以被 registry 管理;
- 可以被 debug 菜单与测试运行时发现;
- 运行前先过合法性检查。
这种服务化设计有很大好处:
- 大量 tour 共存时不容易失控;
- 不同 addon 可以自然扩展;
- 调试入口、自动执行入口、记录器都能挂在同一生态上。
三、自动模式与交互模式,其实解决的是不同问题
tour_automatic 和 tour_interactive 不是“同一个东西两个皮肤”。
自动模式
更像 CI 里的回归守门员:
- 发现 trigger;
- 自动执行 run;
- 超时则失败;
- 在日志里输出步骤上下文。
交互模式
更像引导与调试工具:
- 把当前步骤指给人看;
- 允许人工按提示完成;
- 适合 onboarding、功能演示、手动排障。
这两者共用 step 模型,却服务不同场景,正是 Odoo tour 体系强大的地方。
四、最值得夸的是:官方正面处理“非确定性 trigger”
看 tour_step_automatic.js 和相关测试,会发现 Odoo 专门检查 Potential non deterministic behavior。
这件事非常重要,因为前端自动化最隐蔽、最耗人的 bug 不是“语法错”,而是:
- 选择器有时候匹配 A,有时候匹配 B;
- 动画和异步渲染让目标一闪而过;
- modal、overlay、hidden/visible 状态把步骤搞得时好时坏;
- 某些元素在不同 DOM 时序下都可能满足 trigger。
很多团队遇到这种 flaky test,只会不断加:
- sleep
- retry
- 更长 timeout
结果只是把问题藏起来。
Odoo 的态度更对:先怀疑 trigger 是否本身不确定。
这是一种非常难得的测试工程意识。
五、Hoot 让 tour 不只是“浏览器黑盒点击”
在 web 模块里能看到 Hoot 相关 loader、mock 和 DOM 工具;在 web_tour 里还能看到 tour_helpers_hoot.js。
这说明 Odoo 的前端测试栈并不是:
- 一个 tour 系统;
- 外加另一个毫无关系的测试框架。
相反,Hoot 充当的是低层执行与辅助能力,帮助:
- 选择器查询;
- 时间推进;
- 事件模拟;
- DOM 断言;
- 更可控的自动步骤执行。
换句话说,tour 给出“用户过程模型”,Hoot 提供“更可控的执行地基”。
六、tour recorder 的价值不是替代思考,而是降低起稿成本
tour_recorder.js 会记录点击、输入、拖拽,并尝试生成较短选择器。
这很实用,但也很容易被误解。
Recorder 最有价值的地方,不是“自动生成一份完美 tour”,而是:
- 帮你把真实操作转成初稿;
- 暴露出当前页面选择器是否难以稳定表达;
- 让测试作者从空白页起步时少走很多路。
真正可靠的 tour 仍然需要人工判断:
- trigger 是否稳定;
- 文本匹配是否过脆;
- run 动作是否太依赖时序。
七、为什么这套体系比截图回归更适合 Odoo
截图回归当然有用,但它擅长的是:
- 布局变化;
- 样式缺失;
- 明显视觉偏移。
而 Odoo 大量前端问题属于另一类:
- 按钮现在能不能点;
- 搜索面板步骤有没有真正生效;
- modal 前后层级是否正确;
- 一次业务流程的交互链是否还能走通。
这些问题单靠截图很难判断。tour 则更接近“用户任务是否还能完成”。
所以对 ERP 而言,基于步骤与状态的回归保护通常比纯视觉比较更有性价比。
八、二开团队最该吸收的不是工具名,而是方法论
读完这套源码,最值得带走的是三个方法论:
1)先描述状态,再描述动作
一个好 step 先说明“什么时候该做”,而不是急着 click。
2)对 flaky test,不先加 sleep,先查 trigger 稳不稳
这是 Odoo 最成熟的一点。
3)让工具链互相配合
- tour 提供业务流程层;
- Hoot 提供执行与断言层;
- recorder 提供起稿层;
- service/registry 提供组织层。
这比“找一个万能测试框架包打天下”更现实。
九、总结:Odoo 的回归保护,重点不是自动化,而是可重复性
真正好的前端回归系统,目标从来不只是“自动跑起来”,而是同样的用户路径每次都能被可靠地重演。
Odoo 用 web_tour + Hoot + determinism checks + recorder 做到的,就是把“可重复性”作为第一优先级。
这也是为什么它的测试体系值得前端团队认真借鉴:
- 它不迷信单元测试万能;
- 也不迷信端到端脚本越多越好;
- 它关心的,是步骤是否明确、触发条件是否稳定、执行环境是否可控。
说到底,能长期保护复杂 Web Client 的,不是测试数量,而是测试是否真的可重复、可解释、可维护。
DISCUSSION
评论区