我们详细讲讲UI自动化测试最佳设计模式POM

news2024/11/14 14:53:05

概念

什么是POM?

POM是PageObjectModule(页面对象模式)的缩写,其目的是为了Web UI测试创建对象库。

在这种模式下,应用涉及的每一个页面应该定义为一个单独的类,类中应该包含此页面上的页面元素对象和处理这些元素对象所需要的方法等。

将流程所关联的页面作为对象,将对象串联起来,形成一个个不同的流程,POM是业内公认最佳的设计模式。

POM的优点:

(1)PO提供了页面元素操作和业务流程相分离的模式,可以使测试的代码结构比之前清晰,可读性强。

(2)更方便地复用对象和方法。

(3)对象库是独立于测试用例的、统一的对象库,可以通过集成不同的工具类来达到不同的测试目的。比如集成UnitTest可以用来做单元测试、自动化/功能测试,同时也可以集成JBehave/Cucumber等来做验收测试。

(4)使得整体自动化测试的优点变得更容易一些,如果有某个页面的元素需要变更,那么就可以直接更改封装好的页面元素类即可,而不用更改调用它的其他测试类/代码。这样整个的代码维护成本也会缩减。

PO的核心就是分层思想,把同属于一个页面的元素都放在一个页面类中。

简要结构设计

逻辑代码:基类,实现所有工具函数封装,类似于关键字驱动设计模式。

页面对象代码:基于系统页面,通过调用工具函数来实现业务的操作,生成对应的页面对象。

测试代码:基于测试需要,组件页面对象,实现核心流程的自动化,执行测试用例。

测试数据:为测试用例的执行提供所需要的测试数据。

POM完整框架

Base层:定义项目需要的基础方法,特别是一些基础操作,如元素click操作、sendkeys操作,调用JavaScript脚本的方法和其他一些与基本浏览器相关的操作。

Common层:包含处理Excel文件的方法,获取项目路径、测试系统URL的信息和框架执行相关日志功能的实现方法。

Data层:存放测试数据,在这里可以维护测试数据,这样存放是为了让项目的可维护性强、整体的条理性强。测试数据有时是自动化测试的驱动因素,因此对Data的管理和维护就显的特别重要。

Logs层:存放项目在运行过程中产生的日志文件。

PageObject层:这里是PO的核心层,该层不但涉及代码技术,还涉及对项目业务的分析,进而对项目的页面进行分析。

Reports层:存放项目执行过程中产生的测试报告文件,测试报告是对测试结果的总结。

TestCase层:管理测试用例和执行测试,相当于测试的总入口。

config.ini:整个项目需要用到的配置项。

项目实战

以百度搜索为例

我们首先新建一个简单的项目结构:base、data、page_object、cases,如下图所示:

在base包下新建一个base_page.py文件,在base_page.py文件下新建一个BasePage类作为基类,提供各个常用的已封装好的函数,便于后续的页面对象类进行调用。

selenium中常用的函数:元素定位、输入、点击、访问URL、等待、关闭等。代码如下:

'''
基类:提供各个常用的已封装好的函数,便于后续的页面对象类进行调用。
selenium中常用的函数:元素定位、输入、点击、访问URL、等待、关闭
'''
from time import sleep
from selenium import webdriver


class BasePage:


    driver = webdriver.Chrome()


    # 访问URL
    def visit(self, url):
        self.driver.get(url)


    # 元素定位
    def locator(self, loc):
        return self.driver.find_element(*loc)


    # 输入
    def input(self, loc, txt):
        self.locator(loc).send_keys(txt)


    # 点击
    def click(self, loc):
        self.locator(loc).click()


    # 等待
    def wait(self, time):
        sleep(time)


    # 关闭
    def close(self):
        self.driver.quit()

(左右滑动查看完整代码)

selenium中常用的函数:元素定位、输入、点击、访问URL、等待、关闭

在page_object包下新建一个search_page.py文件,在该文件下新建一个SearchPage类继承BasePage类,调用基础类中的方法实现页面操作,生成对应的页面对象。代码如下:​​​​​​​

'''
百度查询页面,搜索功能
'''
from selenium.webdriver.common.by import By
from base.base_page import BasePage
from selenium import webdriver


class SearchPage(BasePage):


    url = 'http://www.baidu.com'


    # 定位百度输入框
    search_input = (By.NAME, 'wd')
    # 定位百度一下按钮
    search_button = (By.ID, 'su')


    # 封装实现业务流程的函数
    def search(self, txt):
        self.visit(self.url)
        self.wait(2)
        self.input(self.search_input, txt)
        self.wait(2)
        self.click(self.search_button)

(左右滑动查看完整代码)

在cases包下新建一个testcase.py文件作为测试类,实现在百度中分别搜索selenium、python,代码如下:

'''
测试类
'''
import unittest
from page_object.search_page import SearchPage
from selenium import webdriver


class Case(unittest.TestCase):


    def test_search1(self):
        driver = webdriver.Chrome()
        txt = 'selenium'
        SearchPage(driver).search(txt)
        
    def test_search2(self):
        driver = webdriver.Chrome()
        txt = 'python'
        SearchPage(driver).search(txt)


if __name__ == '__main__':
    unittest.main()

(左右滑动查看完整代码)

运行以上代码发现,因为创建了两次webdriver,所以每运行一次代码都会打开一个Chrome浏览器,同时,代码中也存在冗余。

优化方案:可以增加@classmethod作为前置条件和后置条件,搜索的条件也可以采用数据驱动的方式完成,提高代码的可读性与维护性。

在data包下新建一个searchTXT.yaml文件,存放搜索的内容如下:

 优化之后代码如下:

'''
测试类
'''
import unittest
from page_object.search_page import SearchPage
from selenium import webdriver
import ddt


@ddt.ddt()
class Case(unittest.TestCase):


    @classmethod
    def setUpClass(cls) -> None:
        cls.driver = webdriver.Chrome()
        cls.se = SearchPage(cls.driver)


    @classmethod
    def tearDownClass(cls) -> None:
        cls.driver.quit()


    @ddt.file_data('../data/searchTXT.yaml')
    def test_search(self, txt):
        self.se.search(txt)


if __name__ == '__main__':
    unittest.main()

(左右滑动查看完整代码)

运行以上代码,发现测试用例执行了四次,分别搜索了selenium、python、java、php,如此实现了数据驱动,同时也在一个浏览器中完成了操作。

后记

以上简单的实现了POM的设计模式,完成了基类、页面对象层、数据层、测试层的代码编写,若读者有兴趣,可以完成报告层、日志层等内容的编写,最终实现完整的框架。

如果文章对你有帮助,记得点赞,收藏,加关注。会不定期分享一些干货哦......

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

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

相关文章

【Java校招面试】实战面经(一)

目录 前言一、单链表找三等分点(链表可能有环)二、讲几个熟悉的设计模式三、Spring IoC、AOP是什么,是如何实现的,Spring MVC是什么?四、怎么实现线程安全,各个实现方法有什么区别,synchronized…

Linux防火墙之iptables(下)

目录 一、通用匹配 1)协议匹配 2)地址匹配 3)接口匹配 二、隐含匹配 1)端口匹配 2)TCP标志位的匹配 3)ICMP的类型匹配 ①请求规则设置 ②回显匹配 ②显示目的不可达匹配 三、显示匹配 1 &…

教你精通Java语法之第十三章、反射

目录 一、定义 二、用途 三、反射基本信息 四、反射相关的类 4.1Class类 4.1.1Class类中的相关方法(方法的使用方法在后边的示例当中) ​编辑 4.2反射示例 4.2.1获得Class对象的三种方式 4.2.2反射的使用 五、反射优点和缺点 六、重点总结 一、定义 Java的反射&am…

计算机图形学 | 实验十:几何纹理(法线贴图)

计算机图形学 | 实验十:几何纹理(法线贴图) 计算机图形学 | 实验十:几何纹理(法线贴图)什么是法线贴图为什么需要切线空间加载法线贴图引入切线空间结果 华中科技大学《计算机图形学》课程 MOOC地址&#…

PCB基础~电源和地平面,去耦电容

电源和地平面 • 应该尽可能的使用电源和地平面, Why? – 在设备和电源之间提供一个低阻抗的路径 – 提供屏蔽 – 提供散热 – 降低分布电感 • 一个完整的无破损的平面是最优选择 – 破碎的地平面会在走线的上下层之间 引入寄生电感 • Remember! • 低频时&…

【服务器】利用树莓派搭建 web 服务器-无需公网IP

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 概述 使用 Raspberry Pi Imager 安装 Raspberry Pi OS 设置 Apache Web 服务器 测试 web 站点 安装静态样例站点 将web站点发布到公网 安装 Cpolar内网穿透 cpolar进行tok…

SQL-DDL语句DQL语句

SQL学习笔记 DDL语句--操作数据表 /* 快捷键: insert键 在插入 和 替换模式之间切换 ctrl 字母z 撤销上一步操作 tab 往后缩进(默认4个空格) shift tab 往前缩进(默认4个空格) …

SpringBoot配置文件和日志

目录 SpringBoot配置文件 SpringBoot配置文件的作用 项目中的重要数据写在配置文件当中 降低代码耦合 SpringBoot配置文件的格式 properties配置文件 读取配置文件中的内容(Value注解使用${}格式读取) properties优缺点 yml配置文件 yml特…

ChatGPT官方APP正式发布!附安装使用教程

目录 前言 APP功能演示 1.与机器人聊天,询问问题 2.语音输入,人机交互 3.聊天历史,新建聊天分组 安装教程 1.下载应用 2.登录账号 3.愉快的玩耍吧 总结 写到最后 大家好,我是大侠,AI领域的专业博主 前言 …

Docker安装常用软件-Kafka集群

零、为了方便开发调试,使用kafka部署一套kafka环境,进行功能调试,方便快捷 一、部署zookeeper 1、下载镜像 docker pull wurstmeister/zookeeper 2、运行zookeeper镜像 docker run -d --restartalways --log-driver json-file --log-op…

(转载)从0开始学matlab(第10天)—自顶向下的编程思想

在前面的内容中,我们开发了几个完全运转的 MATLAB 程序。但是这些程序都十分简单,包括一系列的 MATLAB 语句,这些语句按照固定的顺序一个接一个的执行。像这样的程序我们称之顺序结构程序。它首先读取输入,然后运算得到所需结果&a…

QT学习记录(三)绘图

按照下面两个教程学习 QT学习教程(全面)_Strive--顾的博客-CSDN博客_qt学习 天山老妖S的博客_QT开发(3)_51CTO博客 1、绘图 VC项目右键增加QT GUI Class,在QT Designer中编辑DlgDraw.ui 在DlgDraw中重载函数 void DlgDraw::paintEvent(Q…

Flutter控件之图片Image封装

Flutter控件之基类Widget封装 Flutter控件之文本Text封装 为什么要进行繁琐的封装?直接用也挺好啊,这个回答一点毛病没有,大部分视图都可以原生绘制,可在Flutter中偏偏原生的控件,少了很多需要又常用的属性&#xff…

最小生成树—Kruskal算法和Prim算法

1.最小生成树 连通图:在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与顶点v2是连通的。如果图中任 意一对顶点都是连通的,则称此图为连通图。 生成树:一个连通图的最小连通子图称作该图的生成树。有n个顶点的连通…

Java基础-面向对象总结(3)

本篇文章主要讲解Java面向对象的知识点 面向对象的三大特性类的扩展(抽象类,接口,内部类,枚举) 目录 面向对象和面向过程的区别? 面向对象的五大基本原则 面向对象三大特性 继承 怎么理解继承 ? 继承和聚合的区别? 封装 多态 什么是多态 什么是运行时多…

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生

测试员可以先在大厂镀金,以后去中小厂毫无压力,基本不会被卡,事实果真如此吗?但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已,如果面试答得稀烂,人家根本不会要你。况且要不是大厂出来…

MySQL数据库基础4-内置函数

文章目录 日期函数字符串函数数学函数其他函数 日期函数 函数名称描述current date()当前日期current time()当前时间current timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date add(date, interval d_value type)在date中添加日期或时间,interv…

GitHub Actions Error “Waiting for a runner to pick up this job”

GitHub Actions Error “Waiting for a runner to pick up this job” 什么是GitHub Actions GitHub Actions 是一个 CI/CD(持续集成和持续部署)平台,可以让您自动化工作流程并与 GitHub 存储库中的代码集成。使用 GitHub Actions&#xff…

智能排班系统 【数据库设计】

文章目录 数据库设计规范ER图物理模型数据表登录日志表操作日志表菜单表角色表企业表门店表省市区表门店节日表消息表职位表排班规则表排班任务表排班结果存储scheduling_date排班日表scheduling_shift排班班次表shift_user班次员工中间表 定时通知表用户表中间表role_menu角色…

适合小白的网络安全书籍推荐

学习的方法有很多种,看书就是一种不错的方法,但为什么总有人说:“看书是学不会技术的”。 其实就是书籍没选对,看的书不好,你学不下去是很正常的。 一本好书其实不亚于一套好的视频教程,尤其是经典的好书…