五分钟搞懂 POM 筹划模式

打印 上一主题 下一主题

主题 959|帖子 959|积分 2877

大家好,我是测试大圣。
今天,我们来聊聊 Web UI 自动化测试中的 POM 筹划模式。
为什么要用 POM 筹划模式

前期,我们学会了利用 Python+Selenium 编写 Web UI 自动化测试线性脚本
线性脚本(以快递 100 网站登录举栗):
PYTHON
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
复制代码
  1. import time
  2. from selenium import webdriver
  3. from selenium.webdriver.common.by import By
  4. driver = webdriver.Chrome()
  5. driver.get("https://sso.kuaidi100.com/sso/v2/authorize.do")
  6. driver.maximize_window()
  7. driver.find_element(By.ID, 'name').send_keys("***********")
  8. driver.find_element(By.ID, 'password').send_keys("***********")
  9. driver.find_element(By.ID, 'submit').click()
  10. time.sleep(2)
  11. text = driver.find_element(By.PARTIAL_LINK_TEXT, '首页').text
  12. assert text == '首页'
  13. driver.close()
复制代码
利用以上代码,最基础最简单的 Web UI 自动化测试就做起来了,但是,问题也随之而来,线性脚本的缺点也袒露出来了:


  • Web UI 自动化测试,简单来说,就是模拟人在浏览器上的操纵,打开浏览器 - 定位元素 - 操纵元素 - 模拟页面动作 - 断言效果
  • 由于线性脚本中的元素定位、元素操纵细节、测试数据、效果验证(断言)是捆绑在一起的,代码会显得非常冗余、可读性差、不可复用、工作量大且可维护性差
  • 刚开始,少数的测试用例维护起来可能很容易,但随着时间迁徙、产品迭代、测试套件一连增长,脚本也越来越臃肿,可能须要维护几十个页面,且很多页面是公用的,元素的任何改变都会让我们的脚本变得繁琐复杂、耗时易堕落。例如:十几个用例中都用到了 A 元素,某一天 A 元素被前端改成了 B 元素,我们就须要去十几个用到 A 元素的地方,将 A 元素修改为 B 元素
  • 如果可以把公共元素抽取出来,即使元素被前端修改,我们也只需更新元素的定位方式,而不用修改每条测试用例,无论多少用例用到该元素,都只需修改元素定位方式,重新获取元素即可
  • 以是我们引入了 PageObject 这种解决方案,它可以帮我们解决筹划上的问题,可以将 testcase 和 page 分层,形成一个非常好的效果
什么是 POM 筹划模式



  • POM:Page Object Model,页面临象模子的简称
  • 2013 年,由 Martin Fowler提出了Page Object的观点
  • 作者的观点是一种封装思想,旨在为每个待测页面创建一个页面临象,从而将繁琐的定位操纵、操纵细节封装到这个页面临象中,对外只提供须要的操纵接口,在调用的时间只调用提供的接口,不用去调用操纵细节,终极实现步伐的高内聚低耦合,使步伐模块的可重用性、移植性大大增强

  • 在这种模式下,对于应用步伐中的每个页面都应该有相应单独的页面类(例如:login_page、userinfo_page),类中应该包含此页面上的元素对象和操纵这些元素对象所须要的方法
  • 再将流程所关联的页面作为对象,将对象串联起来形成差异的业务流程,例如:在登录页面完成登录操纵后跳转到用户中心页面进行个人信息的修改
Selenium 官方对 PageObject 的引入

历史简介


  • 2015 年,Selenium 官方对 PageObject 进行引入:
  • 2020 年,Selenium 更新文档所在:
PageObject 六大原则



  • The public methods represent the services that the page offers
    用公共方法表示页面提供的服务
    例如:登录页面,有用户名输入框、暗码输入框、登录按钮,于是就可以用 input_username () 代表输入用户名、用 input_password () 代表输入暗码、用 click_submit () 代表点击登录按钮
  • Try not to expose the internals of the page
    尽量不要袒露页面的内部信息
    将操纵细节封装成方法,对外只提供对应的方法供调用
  • Generally don’t make assertions
    一般倒霉用断言
    断言要和 Page 代码分开,不要将断言写在 PageObject 层
  • Methods return other PageObjects
    方法返回其他 PageObjects
    例如:首页有个方法是点击登录图标跳转到登录页面,因此这个方法应该返回 login_page
  • Need not represent an entire page
    不须要表示整个页面
    不须要对页面中的每一个元素进行建模,只须要关注我们须要用到的元素。例如:登录页面除了账号暗码登录,另有快捷登录、手机短信登录、扫码登录等
  • Different results for the same action are modelled as different methods
    同一行为的差异效果可以用差异的方法来模拟
    例如:对一个页面进行操纵,可能出现正确的效果或者错误的效果,可以为这两种差异的效果分别创建两个差异的方法
POM 框架

开源代码请点击文末小卡片获取



  • base:base_page,基类,界说项目所需的基础方法,对 Selenium 一些常用的 api 进行二次封装,如:find_element、click、send_keys、screenshot、调用 JavaScript 脚本的方法以及其他与浏览器相关的操纵
    为什么要有基类?

    • 由于每个页面都会频繁利用这些方法,若单纯利用 Selenium 原始 api,可能遇到一些问题,例如:某个按钮未加载完成,但已触发了点击事件,导致元素定位不到而报错。这时就可以对原始 api 进行二次封装,如:参加等候时间、对非常进行捕获并打印日志等,之后所有的 PageObject 都继承 BasePage 类,后续只须要调用这些封装好的方法,增强复用性
    • 假设以后倒霉用 Selenium 这个框架,就只须要修改 BasePage 中的方法,不用去修改详细的测试用例业务代码

  • pages:page_object,页面临象层,也是 PO 的核心层,继承 BasePage,管理页面元素以及操纵元素的方法(将操纵元素的动作写成方法)
  • cases:测试用例层,用于管理测试用例,这里会用到单元测试框架,如:Pytest、Unittest。
  • data:测试数据层,用于测试数据的管理,数据与脚本分离,降低维护成本,提高可移植性,如:yml 文件数据
  • config:配置文件层,存放整个项目须要用到的配置项,如:URL、数据库信息等
  • utils:CommonUtil,公共模块,将一些公共函数、方法以及通用操纵进行封装,如:日志模块、yaml 操纵模块、时间模块等
  • run.py:批量实行测试用例的主步伐,根据差异需求差异场景进行组装,遵循框架的机动性和扩展性
  • logs:日志模块,用于记录和管理日志,针对不怜悯况,设置差异的日志级别,方便定位问题
  • reports:测试报告层,用于测试报告的天生和管理,如:基于 Allure 天生的定制化报告


尾声

我本身收集啦许多软测资料,希望能够帮到学软件测试的朋友们软件资料分享包罗但不限于:Python自动化测试、性能测试、web测试、APP测试、测试开发、安全测试
测试开发工具包:appuim安装包、fiddler安装包(也有配套视频教程)、eclipse、git、jmeter、loadrunner、monkey、postman、soapul、Xmind等等
 最后感谢每一个阅读我文章的人,一点小心意,虽然不是啥值钱的东西,须要的话点击下方小卡片直接拿走~
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表