PO设计模式详解(Python+selenium+unittest)

news2024/9/21 2:44:38

一、什么是PO设计模式(Page Object Model)

1、Page Object是一种设计模式,它主要体现在对界面交互细节的封装上,使测试用例更专注于业务的操作,从而提高测试用例的可维护性。

2、一般PO设计模式有三层

第一层:

  • 对Selenium 进行二次封装,定义一个所有页面都继承的 BasePage ,
  • 封装 Selenium 基本方法 例如:元素定位,元素等待,导航页面 ,
  • 不需要全部封装,用到多少方法就封装多少方法。

第二层:

  • 页面元素进行分离,每个元素只定位一次,隔离定位,如果页面改变,只需要改变相应的元素定位;
  • 业务逻辑分离 或 操作元素动作分离

第三层:

使用单元测试框架对业务逻辑进行测试

同时,我也准备了一份软件测试视频教程(含接口、自动化、性能等),需要的可以直接在下方观看,或者直接关注VX公众号:互联网杂货铺,免费领取

软件测试视频教程观看处:

2023完整版阿里大牛7天软件测试零基础速成内部教程,从基础到项目实战学完即入职。

二、为什么要使用PO设计模式

  • 页面频繁变化,(页面html结构等变化)导致页面UI元素频繁变动,元素定位改变
  • 传统线性自动化(面向过程开发),用例中需要反复的定位同一个元素
  • 每当页面发生变化的时候,需要在用例中寻找变动的部分,工作量大,容易产生遗漏,不容易维护

三、PO设计模式的六大原则

  • 公共方法代表页面提供的服务
  • 不要暴露细节
  • 不要在封装的框架中做断言
  • 方法可以return到新打开的页面
  • 不要对所有元素建模,仅对自己关注的元素建模
  • 相同的行为会产生不同的结果,可以封装不同的结果

四、PO设计模式实例

以公司的统一登录作为项目例子,用PO设计模式实现登陆:

1、手工用例

2、用PO模式实现自动化用例

项目目录

Base.py

login_page.py

from Page import Base
 
# 创建LoginPage类继续BasePage类
class LoginPage(Base.BasePage):
    '''统一平台登录Page层,登录页面封装操作到的元素'''
    '''第二层:页面元素进行分离,每个元素只定位一次,操作元素动作分离'''
    # 定义url变量,供父类中的open()方法使用
    url ="https://test01....cn/#/login"
    # 用户名输入框定位
    def form_username(self,user_name):
        return self.by_id("name").send_keys(user_name) # 使用了父类的self.by_id()方法定位元素,简洁了不少
    # 密码输入框定位
    def form_password(self,pass_word):
        return self.by_id("password").send_keys(pass_word)
    # 登录按钮定位
    def button_login(self):
        return self.by_xpath("//*[text()='登录']").click()

test_login.py

from Page import login_page
import unittest
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
from CommonMethod import LogUtil
 
logger = LogUtil.logs() # 调用封装的日志方法,将日志输出到控制台以及写入文件
 
class LoginCase(unittest.TestCase):
    '''第三层:用单元测试框架对业务逻辑进行测试'''
    '''使用LoginPage类及它所继承的父类中的方法'''
    @classmethod
    def setUpClass(cls):
        # 实例化webdriver,俗称:打开浏览器
        cls.driver = webdriver.Firefox(executable_path='E:\\UI test\\UnittestProject\\Driver\\geckodriver.exe')
        cls.driver.implicitly_wait(10)
    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()
    def test_login_success(self):
        page = login_page.LoginPage(self.driver) # 需要用到哪个Page类时,只需要将它传入浏览器驱动,就可以使用该类中提供的方法了
        page.open()
        page.form_username("XXX")
        page.form_password("123456")
        page.button_login()
        sleep(2)
        self.assertEqual(page.get_current_url(), "https://test01....cn/#/home")
        print("登录成功,用例执行结果通过,当前的url为"+ page.get_current_url())
        sleep(1)
    def test_login_fail(self):
        page = login_page.LoginPage(self.driver)
        page.open()
        page.form_username("XXX11")
        page.form_password("123456")
        page.button_login()
        self.assertNotEqual(page.get_current_url(), "https://test01....cn/#/home")
        print("登录失败,用例执行结果通过,当前的url为"+ page.get_current_url())
        page.form_username(Keys.CONTROL+'a') # 输入组合键Ctrl+a,全选输入框内容
        page.form_username(Keys.BACK_SPACE) # 删除键,删除选中的内容
        page.form_password(Keys.CONTROL + 'a')
        page.form_password(Keys.BACK_SPACE)
        sleep(1)
if __name__ == '__main__':
    unittest.main(verbosity=2)

执行结果

在test_login.py中有调用封装的日志方法,这里把封装的日志附上,在CommonMethod目录下的LogUtil.py

五、其他补充

1、相同的行为会产生不同的结果,可以封装不同的结果:在login_page针对【登录】按钮封装了2个方法

2、方法可以return到新打开的页面:在login_page针对【登录】按钮封装,封装了之后要return新页面或其他信息。test_login调用时命名变量来接收这个函数就行了,比如indexurl = page.button_login_success(),在后面断言可以用indexurl变量来跟预期的url断言

 # 登录失败封装
    def button_login_fail(self):
        self.by_xpath("//span[text()='登录']").click()
        toast = self.by_xpath("//p[text()='账号或密码错误!']").text
        return toast
 
    # 登录成功封装
    def button_login_success(self):
        self.by_xpath("//span[text()='登录']").click()
        sleep(2)
        windows = self.driver.window_handles# 获取打开的多个窗口句柄
        self.driver.switch_to.window(windows[-1])# 切换到当前最新打开的窗口
        indexurl = self.get_current_url()
        return indexurl

3、断言:可以通过url、页面标题、text来断言

'''断言跳转的地址,通过try except语句块来进行测试断言,在实际自动化测试脚本开发中,经常要用到处理异常'''
        try:
            self.assertEqual(indexurl,"https://qa-xxxt/add")
            print("点击创建,正确跳转到新页面" + indexurl)
        except AssertionError as msg:
            print("没有跳转到正确页面,当前跳转的地址为"+addurl+"\n报错信息如下"+format(msg))
            '''当断言失败时会抛出异常测试用例执行失败,输出提示信息后重新将异常抛出,即raise,
            若不重新抛出,用例则永远是显示执行成功的,因为它把异常处理掉了'''
            raise msg
  try:
            self.assertEqual(toast, "账号或密码错误!")
            print("登录失败用例场景执行通过,正确弹出提示信息为:" + toast)
        except AssertionError as msg:
            print("错误提示语与预期结果不一致,请检查"+ format(msg))
            raise msg
  try:
            self.assertEqual(toast, "账号或密码错误!")
            print("登录失败用例场景执行通过,正确弹出提示信息为:" + toast)
        except AssertionError as msg:
            print("错误提示语与预期结果不一致,请检查"+ format(msg))
            raise msg

六、写在最后

PS:这套软件测试的自学教程合集。对于在测试行业发展的小伙伴们来说应该会很有帮助。全套内容已经打包到网盘,内容总量接近500个G。如需要软件测试学习资料,关注公众号(互联网杂货铺),后台回复1,整理不易,给个关注点个赞吧,谢谢各位大佬!

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1202785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

芯片设计工程师必备基本功——《设计与验证:Verilog HDL》

Verilog HDL 作为两大硬件描述语言之一,拥有很大的用户群。据调查,目前美国有 90%左右的 IC 设计人员使用 Verilog. 在中国,大概再 50% 左右的人在使用 Verilog 。 大量高校毕业生和部分软件设计人员正在不断涌入这个领域。要想尽快在 IC设计…

智能设备管理软件有什么用?如何让工厂设备维修管理更高效?

在当今这个数字化、智能化的时代,企业的生存与发展离不开高效、有序的管理。特别是在制造业中,设备报修与维修管理是关系到企业生产效益、安全和持续发展的关键环节。今天,我们就来聊聊如何通过智能化的设备管理软件,让工厂设备的…

Outlook无法显示阅读窗格

Outlook无法显示阅读窗格 故障现象 Outlook主界面不显示阅读窗格 故障截图 故障原因 阅读窗格被关闭 解决方案 1、打开Outlook - 视图 – 阅读窗格 2、选择“靠右”或者“底部”,正常显示阅读窗格

开发vue3 UI组件库,并且发布到NPM

目录 1.创建vue3工程 2.创建package文件 3.编写组件,并且导出 4.编写package.json 5.npm账号注册登录并发布 6.从npm安装使用 7.注意事项 1.创建vue3工程 (1)初始化Vue项目 cnpm create vite (2)进入文件夹…

【每日一题】307. 区域和检索 - 数组可修改-2023.11.13

题目: 307. 区域和检索 - 数组可修改 给你一个数组 nums ,请你完成两类查询。 其中一类查询要求 更新 数组 nums 下标对应的值另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 &#xff0c…

软件启动故障:msvcr100.dll丢失的解决方法,修复程序启动问题

在计算机技术日益发展的今天,我们经常会遇到各种各样的问题。其中,“msvcr100.dll是什么”这个问题,相信很多人都曾经遇到过。那么,msvcr100.dll究竟是什么呢?它又有什么作用呢?本文将从以下几个方面来探讨…

域名及网络地址

域名系统 可以通过 ping 命令查看域名对应的 IP 地址。 查看本机的默认 DNS 域名服务器地址可以使用 nslookup 命令。 IP地址和域名之间的转换 程序中有必要使用域名是很有必要的,系统随时可能会因为各种原因导致 IP 地址变更。而域名则比 IP 地址稳定得多&#…

力扣周赛371复盘(总结与进步)

比赛结果 第一题 2932. 找出强数对的最大异或值 I - 力扣&#xff08;LeetCode&#xff09; 这个由于是简单题&#xff0c;暴力for循环即可 通过结果如下&#xff1a; class Solution {public int maximumStrongPairXor(int[] nums) {int ans0;for(int i 0;i<nums.length;…

Minecraft开服教程:使用MCSM面板一键搭建我的世界服务器并实现远程联机

文章目录 前言1.Mcsmanager安装2.创建Minecraft服务器3.本地测试联机4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射内网端口 5.远程联机测试6. 配置固定远程联机端口地址6.1 保留一个固定TCP地址6.2 配置固定TCP地址 7. 使用固定公网地址远程联机 前言 MCSManager是一个…

微信开发者工具如何使用

首先是下载微信开发者工具 链接: https://pan.baidu.com/s/1ri-fRCUQsz9vLxbTqtdPUQ 提取码: 8rhn 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 安装完打开就是以下界面 接下来进入正题 第一步新建或导入 新建 获取AppID 第一步&#xff1a;通过微信公众平…

STM32GPIO——上拉、下拉电阻

如上两个图所示&#xff0c;标号2都为上拉、下拉电阻部分&#xff0c;阻值约为30k~50k欧&#xff0c;通过对应开关进行控制&#xff0c;开关由寄存器控制。 当引脚外部的器件没有干扰引脚的电压时&#xff0c;即没有外部的上、下拉电压&#xff0c;引脚的电平由引脚内部上、下…

Qt 线程串口

文章目录 ui设置创建线程函数初始串口run函数接收发送数据读取数据处理读取的数据写入数据写入启动的命令 主线程 ui设置 创建线程函数 #include <QObject> #include <QThread> #include <QSerialPort> #include <QSerialPortInfo>class SerialPort :…

电容隔离型±10V输入度隔离放大器:ISOC 124P

度模拟电压信号隔离器。50KHz (-3dB)高带宽与ISO 124P隔离器Pin-Pin兼容。ISOC 124P模拟电压信号隔离放大器是一种采用电容耦合隔离的混合集成电路&#xff0c;该放大器采用了全新的调制-解调电容耦合隔离技术。模块中信号以数字的形式通过电容隔离层进行传输&#xff0c;通过数…

【python自动化】Playwright基础教程(八)鼠标操作

【python自动化】Playwright基础教程(八)鼠标操作 本文目录 文章目录 【python自动化】Playwright基础教程(八)鼠标操作playwright系列回顾前文代码click模拟鼠标点击dblclick模拟鼠标双击down模拟鼠标按下move模拟鼠标移动up模拟鼠标释放wheel模拟鼠标滚动鼠标长按常用实战引…

Day02_《MySQL索引与性能优化》

文章目录 一、SQL执行顺序二、索引简介1、关于索引2、索引的类型Btree 索引Btree 索引 三、Explain简介四、Explain 详解1、id2、select_type3、table4、type5、possible_keys6、key7、key_len8、ref9、rows10、Extra11、小案例 五、索引优化1、单表索引优化2、两表索引优化3、…

react使用wx-open-launch-weapp的方法

index.html中加载 <script src"https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> ios浏览器中,建议直接在app.js中触发 wx.config,其中openTagList写上wx-open-launch-weapp 因为微信需要根据网址计算签名,iosreact中会以根目录为有效网址 …

淘宝开放平台订单接口免申请审核接入规则

大家都知道&#xff0c;想要实现自动化批量获取淘宝的商品订单数据&#xff0c;离不开淘宝开放平台API接口。想要获取API调用权限&#xff0c;需要经过淘宝开放平台的严苛审核流程。并且&#xff0c;现在平台基本不开放新的应用权限了。像很多做ERP的公司&#xff0c;他们的客户…

用Java开发一个扫雷游戏

以下是用Java开发一个扫雷游戏的基本步骤&#xff1a; 创建一个窗口和画布&#xff0c;用来显示游戏界面。 创建一个游戏逻辑类&#xff0c;包含一些基本的操作&#xff0c;如生成地雷、计算周围地雷数量、打开方格等。 在画布上绘制游戏界面&#xff0c;包括格子、数字、地雷…

华为ensp:边缘端口并启动BUDU保护

如上图前提是三个交换机都做了rstp&#xff0c;则在边缘的地方做 边缘端口并启动BUDU保护&#xff0c;也就是我用绿色圈出来的地方 边缘1 进入交换机的系统视图 interface e0/0/3 进入接口 stp edged-port enable quit 再退回系统视图 stp bpdu-protection 这样就可以了…

前端工具nvm实现node自由

node的自由之路 前言 大家使用vue框架开发的朋友可能会遇到首次运行公司项目环境的时候&#xff0c;会出现使用npm install命令安装依赖包的时候出现各种各样的问题&#xff0c;其中很重要的一个错误原因就是因为你的nodejs版本和当时搭建环境的版本不一致造成的。今天就来给…