页面对象模式
自测题
完成以下 3 道题目,检验你的学习成果
问题 1
页面对象模式的核心思想是什么?
解析:页面对象模式的核心思想是把每个页面抽象成一个类,封装该页面的元素定位、操作方法和业务逻辑。测试代码只调用页面对象的方法,不直接操作元素。当页面结构变化时,只需修改页面对象类,测试代码不受影响,大大降低维护成本。
问题 2
页面对象里应该包含断言吗?
解析:页面对象不应该包含断言。页面对象只负责「动作」(元素定位和操作),测试代码负责「验证」(断言)。如果在页面对象里写断言,会导致职责混乱、测试逻辑分散。职责分离让代码清晰、维护简单。页面对象只返回数据供测试代码断言。
问题 3
如何降低页面对象与页面结构的耦合,减少维护成本?
解析:降低维护成本的策略是「稳定选择器」「定位器集中管理」。优先用 data-testid 属性(开发专门为测试添加的稳定属性),其次用语义化标签,避免依赖易变的 xpath。定位器定义在类开头,方便统一查看和修改。要求开发为关键元素添加 data-testid,元素位置变化不影响定位。
测验结果
基础入门
页面对象模式(Page Object Pattern,简称 PO)是 UI 自动化测试的经典设计模式。它的核心思想是:把每个页面抽象成一个类,封装该页面的元素定位、操作方法和业务逻辑。测试代码只调用页面对象的方法,不直接操作元素。这样当页面结构变化时,只需修改页面对象类,测试代码不受影响,大大降低维护成本。页面对象模式的关键优势在于「解耦」——测试逻辑与页面结构解耦、元素定位与操作方法解耦、动作执行与结果验证解耦。面试时能讲清 PO 模式的三大好处(降低维护成本、统一管理定位器、语义化提高可读性),体现你有框架设计能力。
为什么重要
- UI 自动化必问的设计模式:面试官常问「你怎么组织 UI 测试代码」,能讲清 PO 模式的好处和实现才算有框架设计能力。
- 降低维护成本:页面结构变化时只需修改页面对象类,测试代码不受影响,避免修改几十上百个测试用例。
- 元素定位统一管理:每个页面的元素定位器写在页面对象类里,所有测试用例共用同一套定位器,修改一处全部生效。
- 提高代码可读性:页面操作封装成语义化方法名(如 login()、submit_order()),测试代码读起来像业务描述而不是技术细节。
- 职责分离:页面对象做「动作」,测试代码做「验证」,职责分离让代码清晰、维护简单。
相关术语对比
页面对象模式与 Screenplay 模式有什么区别?
Screenplay 模式更强调「用户任务」而非「页面」,以用户视角组织测试代码(如「用户登录」「用户下单」),PO 模式以页面视角组织(如「登录页面对象」「订单页面对象」)。Screenplay 更适合复杂业务流程,PO 更适合页面结构清晰的场景。
页面对象与组件对象有什么区别?
组件对象封装可复用的 UI 组件(如对话框、表单、导航栏),页面对象封装整个页面的结构和操作。组件对象是页面对象的组成部分,一个页面对象可能包含多个组件对象。
页面对象里应该包含断言吗?
不应该。页面对象应该只封装元素定位和操作,断言应该放在测试代码里。\n\n如果在页面对象里写断言,会导致职责混乱、测试逻辑分散。页面对象做「动作」,测试代码做「验证」,职责分离。
实操案例
- 电商项目页面对象实践:按页面划分页面对象(HomePage、LoginPage、ProductPage、CartPage、OrderPage、PaymentPage),每个页面对象包含元素定位器(如 LOGIN_BUTTON、USERNAME_INPUT)、元素操作方法(如 input_username()、click_login())、业务操作方法(如 login(username, password))。测试代码调用页面对象的方法完成操作,然后做断言验证。页面结构变化时只需修改对应页面对象类,测试代码不受影响。
- 金融项目页面对象实践:按业务模块划分页面对象(AccountPage、TransferPage、BillPage),每个页面对象包含稳定的选择器策略(优先用 data-testid 属性,其次用语义化标签,最后才用相对 xpath)。开发协作要求:要求开发为关键元素添加 data-testid 属性,测试用这些属性定位元素,元素位置变化不影响定位。
- 从混乱到规范:原项目测试代码直接操作元素(driver.find_element(By.ID, ‘username’).send_keys(‘user’)),页面变化需要修改几十处。引入 PO 模式后,测试代码调用页面对象方法(login_page.login(‘user’, ‘pass’)),页面变化只需修改页面对象类,维护成本降低 80%。
常见误区
误区 1:在页面对象里写断言
正确做法:页面对象只负责「动作」,测试代码负责「验证」。\n\n如果在页面对象里写断言(如 assert page.get_title() == ‘Home’),会导致职责混乱、测试逻辑分散。断言要放在测试代码里,页面对象只返回数据供测试代码断言。
误区 2:页面对象过度细分或过度聚合
正确做法:按页面或业务模块划分,一个页面对象包含该页面的主要元素和操作。
过度细分(每个按钮一个类)会导致类太多、维护复杂。过度聚合(整个系统一个类)会导致职责不清。
面试时要讲清划分原则。
误区 3:页面对象与页面结构耦合太紧
正确做法:使用稳定的选择器策略(如 data-testid、语义化标签),减少对具体结构的依赖。\n\n如果页面对象直接依赖具体选择器(如 xpath://div[3]/span[2]),页面结构变化会大量失效。面试时要说明选择器稳定性策略。
面试问答
页面对象模式有什么好处?
页面对象模式有三大好处:
第一,测试代码与页面结构解耦,维护成本降低。页面对象把页面元素定位和操作封装成类,测试代码只调用页面对象的方法,不直接操作元素。当页面结构变化时(元素位置变化、元素 ID 变化),只需修改页面对象类的定位器,测试代码不受影响。
第二,元素定位统一管理,减少重复代码。每个页面的元素定位器写在页面对象类里,所有测试用例共用同一套定位器。如果定位器需要修改(元素 ID 变了),只需修改一处,所有测试自动生效。
第三,页面操作语义化,测试代码可读性提高。页面对象把页面操作封装成语义化的方法名(如 login()、submit_order()、click_checkout()),测试代码调用这些方法,读起来像业务描述而不是技术细节。
页面对象里应该包含哪些内容?
页面对象的内容要遵循「职责分离」原则,包含三类内容、不包含一类内容:应该包含的内容:
第一,元素定位器。页面上所有需要操作的元素(输入框、按钮、链接、下拉框)的定位器定义在页面对象里。定位器要用稳定的选择策略(如 data-testid、语义化标签),避免依赖易变的选择器。
第二,元素操作方法。封装元素的基本操作(输入文本、点击、选择下拉框、获取文本)。
第三,业务操作方法。封装页面的业务操作(登录、下单、提交表单),这些方法组合多个元素操作方法完成业务动作。不应该包含的内容:断言逻辑。页面对象只负责「动作」,测试代码负责「验证」。
页面结构变化时怎么维护页面对象?
页面结构变化时维护页面对象的策略是「稳定选择器」「定位器集中管理」「模块化拆分」。
第一,使用稳定的选择器策略。优先用 data-testid 属性(开发专门为测试添加的稳定属性),其次用语义化标签,最后才用相对 xpath。开发协作:要求开发为关键元素添加 data-testid 属性。
第二,定位器集中管理。每个页面对象类把所有定位器定义在类的开头,方便统一查看和修改。
第三,模块化拆分降低影响范围。页面对象按页面或模块拆分,一个页面一个页面对象类,页面变化只影响该页面的页面对象。
自测题
完成以下 3 道题目,检验你的学习成果
问题 1
页面对象模式的核心思想是什么?
解析:页面对象模式的核心思想是把每个页面抽象成一个类,封装该页面的元素定位、操作方法和业务逻辑。测试代码只调用页面对象的方法,不直接操作元素。当页面结构变化时,只需修改页面对象类,测试代码不受影响,大大降低维护成本。
问题 2
页面对象里应该包含断言吗?
解析:页面对象不应该包含断言。页面对象只负责「动作」(元素定位和操作),测试代码负责「验证」(断言)。如果在页面对象里写断言,会导致职责混乱、测试逻辑分散。职责分离让代码清晰、维护简单。页面对象只返回数据供测试代码断言。
问题 3
如何降低页面对象与页面结构的耦合,减少维护成本?
解析:降低维护成本的策略是「稳定选择器」「定位器集中管理」。优先用 data-testid 属性(开发专门为测试添加的稳定属性),其次用语义化标签,避免依赖易变的 xpath。定位器定义在类开头,方便统一查看和修改。要求开发为关键元素添加 data-testid,元素位置变化不影响定位。