百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

PO设计模式全攻略,在 UI 自动化中的实践总结(以企业微信为例)

ztj100 2025-07-28 01:29 4 浏览 0 评论

一、什么是PO设计模式?

PO(PageObject)设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个 Page 类,即一个py文件,并以页面为单位来写测试用例,实现页面对象和测试用例的分离,若元素发生变化,只需要进入对应的Page类,更新元素定位即可,不用修改用例。



二、在什么样的场景下使用PO设计模式?

随着时间的推移,需要维护的页面越来越多时,如果使用传统的设计模式把测不同页面上的所有步骤写在同一个模块里面,会显得笨重。如果页面发生了改变,对应的脚本也要发生改变,难以维护就可以体现出来了,所以使用的PO设计模式会方便很多。

三、PO模式的六大原则

(1)一个 public 方法代表一个公共的服务。就是说一个方法代替页面上的某个操作(公共方法表示页面提供的服务)

(2)PageObject 中的方法细节不可暴露在外,通过提供公共服务接口的形式提供给外部(不要暴露页面的细节)

(3)一般不需要在 PageObject 中断言(Page设计中不要出现断言,应该写在测试用例类中)

(4)当有页面跳转的操作时候,执行这个方法时应该在方法结束返回时能够跳转到另一个页面中(方法应该返回其他的Page对象)

(5)我们只需要对页面中我们需要的重要的内容进行封装(不要去代表整个page,如果一个页面中有很多功能,只需要对重点功能封装方法即可)

(6)页面中相同的组件,但是不同的操作应该要被拆成不同的方法进行封装(不同的结果返回不同的方法,不同的模式)

四、PO 模式页面层级

PO模式可以把一个页面分为二个层级:对象操作层、业务层。

(1)对象操作层:封装定位元素,封装对元素的操作。

(2)业务层:将一个或多个操作组合起来完成一个业务功能。

五、PO模式实战

以下是以企业微信-添加成员为例-最终打印成员列表

传统的web自动化脚本

(1)传统的web脚本,把driver实例化、对象操作以及业务逻辑全部写进一个模块里面;这次举例的测试用例只是涉及到两个页面,如果遇到到更加复杂的测试用例时,把全部的代码写进同一个模块里,这样就显得很臃肿;当有上百个用例,几十个页面的时候,我们会在测试用例中重复的使用到页面当中的元素和操作。当其中的页面发生变化时,我们需要在多个用例中去修改。这种情况下,代码多且乱,维护成本也不低。

(2)使用PO设计模式编写测试用例时,通过分层将测试代码和页面元素分开,有效的命名模块名称可以更加清晰知道所操作功能模块以及操作的UI元素,哪个页面的数据发生改变时,就在对应的页面进行修改即可;

'''测试用例'''

class TestDemo:

def setup(self):

self.driver = webdriver.Chrome()

self.driver.implicitly_wait(5)

self.driver.maximize_window()

def teardown(self):

self.driver.quit()

def test_add_mumber(self):

# 扫码登录界面

self.driver.get("https://work.weixin.qq.com/wework_admin/loginpage_wx")

# 创建data.yaml文件,设置编码

path = os.path.dirname(os.path.abspath(__file__))

data_file = os.sep.join([path, "../data/data.yaml"])

with open(data_file, encoding="UTF-8") as f:

# 获取数据

yaml_data = yaml.safe_load(f)

# 遍历

for cookie in yaml_data:

# 设置cookie

self.driver.add_cookie(cookie)

# 访问首页

self.driver.get("https://work.weixin.qq.com/wework_admin/frame")

#点击添加成员

self.driver.find_element_by_xpath("//*[@id='_hmt_click']/div[1]/div[4]/div[2]/a[1]/div/span[2]").click()

time.sleep(3)

#输入用户名

self.driver.find_element_by_id("username").send_keys("haha")

#输入别名

self.driver.find_element_by_id("memberAdd_english_name").send_keys("哈哈哈")

#输入账号

self.driver.find_element_by_id("memberAdd_acctid").send_keys("haha001")

# self.driver.find_element_by_xpath("//*[@id='js_contacts72']/div/div[2]/div/div[4]/div/form/div[2]/div[1]/div[3]/div[2]/label[2]/input").click()

#选择性别为“女”

self.driver.find_element_by_css_selector("#js_contacts72 > div > div.member_colRight > div > div:nth-child(4) > div > form > div.member_edit_formWrap > div:nth-child(1) > div.member_edit_item.member_edit_item_Radios > div.member_edit_item_right > label:nth-child(2) > input").click()

#输入手机号码

self.driver.find_element_by_id("memberAdd_phone").send_keys("15676006789")

#输入座机

self.driver.find_element_by_id("memberAdd_telephone").send_keys("0770851")

#输入邮箱

self.driver.find_element_by_id("memberAdd_mail").send_keys("1234@qq.com")

#输入地址

self.driver.find_element_by_id("memberEdit_address").send_keys("xxx")

#点击保存

self.driver.find_element_by_css_selector("#js_contacts72 > div > div.member_colRight > div > div:nth-child(4) > div > form > div:nth-child(3) > a.qui_btn.ww_btn.js_btn_save").click()

time.sleep(2)

PO项目目录结构:

clipboard.png

(1)项目开始前,拿到一份需求时,需要做需求分析,划分模块,编写测试用例。此次测试用例的流程,进入主页(MainPage),点击添加成员,进入添加成员页面,点击添加,点击保存,显示所有的成员列表,最后做断言,验证测试用例执行是否成功。

(2)编写测试用例开始之前,建立时序图,便于思考,时序图如下图所示:

clipboard.png

(3)测试用例的要素:

  • 前置条件
  • 执行步骤
  • 数据检查及断言
'''

添加成员测试用例

'''

class TestAddMumber:

def setup(self):

# 实例化

self.main_page = MainPage()

# 实现测试数据和页面对象分离

@pytest.mark.parametrize("username,accid,phone", [("hxc2", "862", "15676000002")])

def test_add_mumber(self, username, accid, phone):

# 1.跳转到添加成员页面 2.添加成员 3.获取成员列表

name_list = self.main_page.goto_add_number().add_member(username, accid, phone).get_contact_list()

assert username in name_list

(2)main_page.py该模块就是相当于该测试的首页,该成员页面有添加成员、导入通讯录、打卡等功能,以下以点击“添加成员”为例,点击“添加成员”之后进入到通讯录页面,添加成员所在的页面和通讯录不在同一个页面上,当有页面跳转的操作时候,在函数后面需要返回要跳转页面的实例化对象,如下图代码中的AddMumberPage。

class MainPage(BasePage):

'''使用公共方法代表UI所提供的功能'''

def goto_add_number(self):

#点击添加成员

self.driver.find_element(By.CSS_SELECTOR,".ww_indexImg_AddMember").click()

'''

跳转到添加成员页面

:return:

'''

#返回要跳转页面的实例化对象

return AddMumberPage(self.driver)

(3)添加成员,在该模块中定义add_mumber接口,把定位元素以及对应的操作封装在add_member里,使用时调用add_mumber接口即可。PO中的方法细节不可暴露在外,通过提供公共服务接口的形式提供给外部

#调用时要注意格式(元组),self.driver.find_element需要*号将元组解包。

class AddMumberPage(BasePage):

# 设定为元祖

#__是私有,页面元素不需要让业务了解,所以要加私有

#元素定位

__ele_username = (By.ID, "username")

ele_accid = (By.ID, "memberAdd_acctid")

ele_phone = (By.ID, "memberAdd_phone")

webdriver.Firefox()

#元素对象

def add_member(self, username, accid, phone):

'''

*是解元祖,self.driver.find_element(*self.ele_username)等同于self.driver.find_element(By.ID, "username")

'''

# 填写用户名

self.find(*self.__ele_username).send_keys(username)

# 填写账号

self.driver.find_element(*self.ele_accid).send_keys(accid)

# 填写手机号

self.driver.find_element(*self.ele_phone).send_keys(phone)

# 点击保存

self.driver.find_element(By.CSS_SELECTOR, ".js_btn_save").click()

'''

页面的return分成两个部分

1.其他页面的实例

2.用例所需要的断言

注意:不要写成ContactPage,这个是类

:return:

'''

# 返回通讯实例对象

return ContactPage(self.driver)

相关推荐

Python 操作excel的坑__真实的行和列

大佬给的建议__如何快速处理excelopenpyxl库操作excel的时候,单个表的数据量大一些处理速度还能接受,如果涉及多个表甚至多个excel文件的时候速度会很慢,还是建议用pandas来处理,...

Python os.path模块使用指南:轻松处理文件路径

前言在Python编程中,文件和目录的操作是非常重要的一部分。为了方便用户进行文件和目录的操作,Python标准库提供了os模块。其中,os.path子模块提供了一些处理文件路径的函数和方法。本文主要...

Python常用内置模块介绍——文件与系统操作详解

Python提供了多个强大的内置模块用于文件和系统操作,下面我将详细介绍最常用的几个模块及其核心功能。1.os模块-操作系统交互...

Python Flask 建站框架实操教程(flask框架网页)

下面我将带您从零开始构建一个完整的Flask网站,包含用户认证、数据库操作和前端模板等核心功能。##第一部分:基础项目搭建###1.创建项目环境```bash...

为你的python程序上锁:软件序列号生成器

序列号很多同学可能开发了非常多的程序了,并且进行了...

PO设计模式全攻略,在 UI 自动化中的实践总结(以企业微信为例)

一、什么是PO设计模式?PO(PageObject)设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个Page类,即一个py文件,并以页面为单位来写测试用例,实现页面对象和测试用例的...

这种小工具居然也能在某鱼卖钱?我用Python一天能写...

前两天在某鱼闲逛,本来想找个二手机械键盘,结果刷着刷着突然看到有人在卖——Word批量转PDF小工具...

python打包成exe,程序有图标,但是任务栏和窗口都没有显示图标

代码中指定图标信息#设置应用ID,确保任务栏图标正确显示ifsys.platform=="win32":importctypesapp_id=...

使用Python构建电影推荐系统(用python做推荐系统)

在日常数据挖掘工作中,除了会涉及到使用Python处理分类或预测任务,有时候还会涉及推荐系统相关任务。...

python爬取并分析淘宝商品信息(python爬取淘宝商品数据)

python爬取并分析淘宝商品信息背景介绍一、模拟登陆二、爬取商品信息1.定义相关参数2.分析并定义正则3.数据爬取三、简单数据分析1.导入库2.中文显示3.读取数据4.分析价格分布5.分析销售...

OpenCV入门学习基础教程(从小白变大神)

Opencv是用于快速处理图像处理、计算机视觉问题的工具,支持多种语言进行开发如c++、python、java等,下面这篇文章主要给大家介绍了关于openCV入门学习基础教程的相关资料,需要的朋友可以...

python图像处理-一行代码实现灰度图抠图

抠图是ps的最基本技能,利用python可以实现用一行代码实现灰度图抠图。基础算法是...

从头开始学python:如何用Matplotlib绘图表

Matplotlib是一个用于绘制图表的库。如果你有用过python处理数据,那Matplotlib可以更直观的帮你把数据展示出来。直接上代码看例子:importmatplotlib.pyplot...

Python爬取爱奇艺腾讯视频 250,000 条数据分析为什么李诞不值得了

在《Python爬取爱奇艺52432条数据分析谁才是《奇葩说》的焦点人物?》这篇文章中,我们从爱奇艺爬取了5万多条评论数据,并对一些关键数据进行了分析,由此总结出了一些明面上看不到的数据,并...

Python Matplotlib 库使用基本指南

简介Matplotlib是一个广泛使用的Python数据可视化库,它可以创建各种类型的图表、图形和可视化效果。无论是简单的折线图还是复杂的热力图,Matplotlib提供了丰富的功能来满足我们...

取消回复欢迎 发表评论: