当前位置: 首页 > news >正文

自动化测试:PO模式介绍及案例

🍅点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快

PO(Page Object)设计模式是一种面向对象( 页面对象)的设计模式,将测试对象及单个的测试步骤封装在每个Page对象以page为单位进行管理。

优点

  1. 可以使代码复用
  2. 降低维护成本
  3. 提高程序可读性和编写效率。
  4. 可以将页面定位和业务操作分开,测试对象(元素对象)和测试脚本(用例脚本)
  5. 提高用例的可维护
非PO模式PO模式
面向过程的线性脚本POM把页面元素定位和业务操作流程分开,实现松耦合
复用性性差UI元素的改变不需要修改业务逻辑代码,只需要找到对应的PO页修改定位即可,数据代码分离
维护性差PO能使代码更具有可读性,高复用性、可维护性

PO三层模式:

主要分三层:

1.base层(对象库层):page页面一些公共的方法。如:初始化、元素定位、点击、输入、获取文本、截图等方法;

2.page层(操作层):封装对元素的操作。将每个涉及的元素操作单独封装一个操作方法,然后根据需求组装操作步骤,如登录方法=输入帐号+输入密码+点击登录三个操作进行组装;

3.scripts层(业务层):导包调用 page页面,使用单元测试框架对业务逻辑进行封装测试。如:实现登录,直接调用page组装的登陆方法即可。

三者的关系:page层继承base层,scripts层调用page层

案例:

项目结构介绍:

创建项目,如下图

1. 构建基础的 BasePage 对象层

创建driver,浏览器驱动封装

# encoding='UTF-8' # 浏览器启动 from selenium import webdriver def browser(): driver=webdriver.Chrome() # driver.get("http://www.baidu.com") return driver

创建myuni.py文件,初始化封装,

定义一个继承自unittest.TestCase的测试用例类

定义setUp和tearDown,这两个方法与junit相同,即如果定义了则会在每个测试case执行前先执行setUp方法,执行完毕后执行tearDown方法。

# encoding='UTF-8' import unittest from driver import * class StartEnd(unittest.TestCase): def setUp(self): self.driver=browser() self.driver.implicitly_wait(10) self.driver.maximize_window() def tearDown(self): self.driver.quit()

创建function.py文件,截图功能

# encoding='UTF-8' import os from selenium import webdriver # 截图 def insert_img(driver,filename): func_path=os.path.dirname(__file__) # print(func_path) base_dir=os.path.dirname(func_path) # print(base_dir) # 将路径转化为字符串 base_dir=str(base_dir) # 对路径的字符串进行替换 base_dir=base_dir.replace("\\","/") # print(base_dir) # 获取项目文件的要目录路径 base=base_dir.split('/Website')[0] # print(base) # 指定截图存放路径(注意路径最后要加/) filepath=base+'/Website/test_report/screnshot/'+filename driver.get_screenshot_as_file(filepath) if __name__=='__main__': driver=webdriver.Chrome() driver.get("http://www.sogou.com")
2. 构建首页的 Page 层(操作层)

创建BasePage.py文件,判断打开的页面是否是预期的页面

# encoding='UTF-8' from time import sleep class Page(): def __init__(self,driver): self.driver=driver self.base_url="http://localhost" self.timeout=10 def _open(self,url): url_=self.base_url+url # print("这个页面url是:%s"%url_) self.driver.maximize_window() self.driver.get(url_) # sleep(2) assert self.driver.current_url==url_,'这不是我们想要的地址' def open(self): self._open(self.url) def find_element(self,*loc): return self.driver.find_element(*loc)

创建LoginPage.py文件,页面元素定位封装

# encoding='UTF-8' from BasePage import * from selenium.webdriver.common.by import By class LoginPage(Page): url='/news/' username_loc=(By.NAME,'username') password_loc=(By.NAME,'password') submit_loc=(By.NAME,'Submit') def type_username(self,username): self.find_element(*self.username_loc).send_keys(username) def type_password(self,password): self.find_element(*self.password_loc).send_keys(password) def type_submit(self): self.find_element(*self.submit_loc).click() def login_action(self,username,password): self.open() self.type_username(username) self.type_password(password) self.type_submit() loginPass_loc=(By.LINK_TEXT,'我的空间') loginErr_loc=(By.LINK_TEXT,'加入收藏') def type_loginPass_hint(self): return self.find_element(*self.loginPass_loc).text def type_loginErr_hit(self): return self.find_element(*self.loginErr_loc).text
3.构建业务层
  • 创建test_login.py文件
  • 导包:function、myunit、LoginPage
  • 创建LoginTest类,继承myunit.StartEnd,初始化方法
  • 定义测试用例,名字以test开头,unittest会自动将test开头的方法放入测试用例集中
  • 实现登录,调用LoginPage组装的登陆方法,输入用户名、密码、点击登录、断言,截图
# encoding='UTF-8' import unittest from model import function,myunit from page_object.LoginPage import * from time import sleep class LoginTest(myunit.StartEnd): def test_login1_normal(self): print("test_login1_normal测试开始") po=LoginPage(self.driver) po.login_action("yuruyi","12345678") sleep(5) self.assertEqual(po.type_loginPass_hint(),'我的空间') function.insert_img(self.driver,"login_normal.png") print("test_login1_normal执行结束") def test_login2_PasswdError(self): print("test_login2_PasswdError测试开始") po=LoginPage(self.driver) po.login_action("yuruyi","1234567") sleep(5) self.assertEqual(po.type_loginErr_hit(),'加入收藏') function.insert_img(self.driver,"login_Err.png") print("test_login2_PasswdError执行结束") def test_login3_empty(self): print("test_login3_empty测试开始") po = LoginPage(self.driver) po.login_action("", "") sleep(5) self.assertEqual(po.type_loginErr_hit(), '加入收藏') function.insert_img(self.driver, "login_empty.png") print("test_login3_empty执行结束") if __name__=='__main__': unittest.main()

常用断言方法:

4. 构建用例集,执行文件,输出自动化测试报告

在测试用例、测试文件比较多的时候,使用统一的主测试执行文件进行测试用例的执行非常方便,这就需要结合discover方法和TextTestRunner进行。

# encoding='UTF-8' import unittest # 测试报告模板 from HTMLTestRunnerCN import HTMLTestRunner import time report_dir='./test_report' test_dir='./test_case' print("start run test case") discover=unittest.defaultTestLoader.discover(test_dir,pattern="test_login.py") now=time.strftime("%Y-%m-%d %H_%M_%S") report_name=report_dir+'/'+now+'result.html' print("start write report..") #使用runner运行器运行测试集 with open(report_name,'wb')as f: runner=HTMLTestRunner(stream=f,title="Test Report",description="localhost login test") runner.run(discover) f.close() print("Test end")

测试报告模板

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

http://www.jsqmd.com/news/648009/

相关文章:

  • Centos7系统中cmake3.25的高效编译与自动化部署指南
  • 从Gaussian Splatting到‘像素级’镜面:手把手拆解延迟着色如何让3DGS学会精准反射
  • Compose跨平台新版本来了!测试 API 全废弃,iOS 崩溃集中修复
  • 迈向下一代RAG,通义VimRAG用了这个方案
  • 2026年3月做得好的进口流量计企业推荐,进口流量计/进口涡轮流量计/进口蒸汽流量计,进口流量计源头厂家推荐 - 品牌推荐师
  • 基于Raspberry Pi和OpenCV的家庭智能监控系统
  • 从‘飞线’到‘倒装’:一文看懂WBCSP和FCCSP封装该怎么选(附内存与处理器封装实战解析)
  • 别只会复制代码了!手把手带你拆解51单片机点灯程序的硬件电路与寄存器操作
  • 横河 Yokogawa 便携式无纸记录仪 GP10/GP20系列
  • 彻底疯狂,Claude居然要你上传身份证!
  • 5分钟解锁微信网页版:wechat-need-web插件完全使用指南
  • 瑞芯微开发板避坑指南:yolov5s模型在RK3566上的帧率优化实战
  • PyCharm 2023.3.2专业版安装避坑指南:学生认证+Anaconda环境配置全流程
  • Agilent E5100A 高速网络分析仪
  • 763.划分字母区间
  • 江城智造,共赴盛会!AICA数智创新公开课·武汉专场圆满举办
  • HakcMyVM-Quick4
  • 从CALCE到BMS开发:如何利用公开电池数据集训练你的第一个SOC预测模型
  • 在Ubuntu 22.04上配置Frappe-Bench:从环境准备到成功启动
  • 盘点:四种基于SAM的域适应与弱监督分割技术演进
  • AI产品经理崛起!转型AI,你需要掌握的核心能力与职业规划全解析!
  • Genshin FPS Unlocker:三步解锁《原神》60帧限制,畅享高刷游戏体验
  • 横河 GX90XA-10-U2N-CC无纸记录仪采集模块 适用于GP10,GP20
  • 影视站模板进行‌泛目录(泛站/泛页面)二次开发‌,以实现SEO优化、站群搭建、自动采集、内容伪原创等功能。根据2026年4月的最新公开资料
  • 2026年吊挂灯箱实力厂商亲测复盘:亮欣广告灯箱为何成为行业优选解决方案
  • 丝杆升降机多久润滑一次最合适?
  • AI OPC 每日资讯(4月15日)|《全球人工智能治理科技社团倡议》发布
  • ELK日志分析系统实战:从零搭建到可视化监控(含Filebeat配置)
  • 电子爱好者必看:5分钟掌握三极管工作状态的实战判断技巧
  • 大量TIME_WAIT状态的连接问题