引言
在UI测试自动化领域,页面对象模型(Page Object Model,POM)几乎已经是行业标准。它被广泛认为是UI自动化测试领域的最佳实践,对于提高可维护性和可扩展性,几乎是不二之选。
笔者在实际工作中,组织搭建过的UI自动化框架虽然大部分也是遵循了个这个模型,但隐隐也确实觉得这个更多是个开发实践而不是应用实践。是OOP(面向对象)思想在自动化测试实施种的体现。
现偶然看到一篇国外博主的 Shubham Sharma
的文章 《Beyond the Page Object Model-A Functional Approach to Test Automation》,对POM模型进行了思考,并提出了一个函数化方法模型。(文末阅读原文可跳转原文)
虽然不知具体实践成效如何,但兼听则明,开拓下思路总是没错的。
以下基于原博文内容翻译整理而来(help by Gemini)
关于POM
POM的核心思想是将页面元素和浏览器交互封装到整洁、可重用的对象中。
它的方法很简单:为每个页面或组件创建一个类,包含定位器(locators)和操作这些元素的方法。
虽然POM相比那些充满硬编码元素的脆弱脚本是一个进步,但它本质上也是一个有缺陷的抽象。它将面向对象原则应用到一个本质上过程化和行为驱动的问题领域,导致测试套件难以理解、与状态紧密耦合且扩展困难。
POM问题
以一个典型的登录流程POM实现为例:
|
|
在测试中的使用:
|
|
乍一看,这看起来很整洁。但在表面之下,它引入了几个严重问题:
隐藏状态和紧密耦合
对象存储了对驱动程序(page
)的引用,创建了隐式依赖。这使得页面类无法独立测试,并将其行为和浏览器的运行时状态进行了锁定。
分散的用户逻辑
像"登录、进入设置、更改密码" 这样的用户旅程变成了跨多个页面对象的方法调用链。工作流被分割——而不是一个连贯的、可测试的单元。
僵化和膨胀
一些新的流程(如SSO登录),则被迫添加更多方法(违反单一职责原则)或创建新类(导致重复)。随着时间的推移,你的页面对象要么膨胀,要么分裂。
POM将页面作为抽象单位。但页面只是背景。
真正重要的是用户操作。
替代方案:函数式模型,可组合的工作流
函数式模型颠覆了这一脚本。它将用户行为,而非UI结构作为主要抽象。
第一步:分离数据(定位器)
将选择器保持为普通的、不可变的数据——没有方法,没有状态:
|
|
第二步:编写无状态交互函数
不要将方法绑定到类,而是编写可重用的无状态函数:
|
|
这些可以在整个应用中重用,易于独立测试,并且可以集中改进(例如添加重试、等待、日志记录)。
第三步:以声明方式组合用户工作流
将真正的用户旅程构建为一等函数:
|
|
现在你的测试读起来就像一个故事:
|
|
为什么推荐这种方法
真正的可组合性
你不仅仅是在调用方法,而是在构建工作流。login()
函数可以组合到changePassword()
工作流中,或者与导航步骤结合。函数成为有意义的可测试单元。
改进的清晰度
测试不再是逐步执行UI操作的命令式脚本。相反,它们成为用户意图的声明式管道,更易于阅读、编写和理解。
集中化维护
修复不稳定的选择器或改进点击行为发生在一个地方,并传播到所有地方。不再需要在分散在文件中的类方法中寻找。
测试的范式转变
页面对象模型反映了一个遗留范式:面向对象编程,其中所有事物都被建模为具有状态和行为的"事物"。但UI测试不是关于事物,而是关于流程。
通过拥抱函数式思维,我们将测试建模为用户行为的可组合管道,而不是僵化的对象。这些工作流具有以下特点:
- 无状态
- 隔离
- 声明式
- 易于测试
- 易于更改
- 易于组合
核心要点
停止问:“我这里需要什么页面对象?”
开始问:“我想要描述的用户工作流是什么?”
答案将引导你构建一个更简单、更清洁、更接近真实用户体验的测试套件,它不是建立在继承和隐藏状态之上,而是建立在纯函数和可组合流程之上。这不仅仅是一种编码风格,它是测试的更好心智模型。
结论:迈向更自然的测试方式
页面对象模型曾经是UI测试自动化的重要进步,但随着测试复杂度的增加和软件开发理念的发展,它的局限性日益明显。函数式方法为我们提供了一个更自然、更灵活的替代方案。
通过将关注点从页面结构转向用户行为,从对象状态转向工作流程,我们能够创建更贴近真实用户体验的测试。这种方法不仅提高了代码的可维护性和可读性,更重要的是,它改变了我们对测试本质的理解。
在快速变化的软件开发现代中,我们需要能够适应变化的测试策略。函数式测试方法正是这样一种策略——它灵活、可组合、易于维护,能够随着应用的发展而演进。