UI自动化测试中公认最佳的设计模式-POM

news2024/11/20 13:18:08

一、概念

什么是POM?

POM是PageObjectModule(页面对象模式)的缩写,其目的是为了Web UI测试创建对象库。在这种模式下,应用涉及的每一个页面应该定义为一个单独的类。类中应该包含此页面上的页面元素对象和处理这些元素对象所需要的方法等。将流程所关联的页面作为对象,将对象串联起来,形成一个个不同的流程,POM是业内公认最佳的设计模式。

POM的优点:

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

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

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

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

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

以上概念内容来源于某书籍

二、简要结构设计

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

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

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

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

三、POM完整框架

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

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

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

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

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

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

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

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

四、项目实战

以百度搜索为例

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

image.png

2. 在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()
  1. 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)
  1. 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文件,存放搜索的内容如下:

image.png

优化之后代码如下:

'''
测试类
'''
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的设计模式,完成了基类、页面对象层、数据层、测试层的代码编写,若读者有兴趣,可以完成报告层、日志层等内容的编写,最终实现完整的框架。

 行动吧,在路上总比一直观望的要好,未来的你肯定会感 谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入扣群: 320231853,里面有各种软件测试+开发资料和技术可以一起交流学习哦。

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

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

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

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

相关文章

css 实现排行榜向上滚动

使用动画实现无线向上滚动 复制一层dom&#xff0c;使用动画向上滚动&#xff0c;鼠标hover的时候暂停动画 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthd…

Java调用WebServices接口

当拿到一个WebServices接口时&#xff0c;首先用接口测试工具调用一下接口&#xff0c;看是否可以正常发送请求和获取返回接口&#xff0c;确保接口是没有问题的&#xff0c;可以用SoapUI工具进行测试。 下面以一个免费的天气预报接口为例&#xff0c;记录整个接口的调用过程。…

【echarts】支持根据data中最大的数值来动态计算y轴最大数据以及间隔

以这个图例可以看到Y轴最大显示到250ml&#xff0c;如果超过就会出现有一部分数据看不到了&#xff1a; https://echarts.apache.org/examples/zh/editor.html?cmix-line-bar 那么如何根据这个data数据的最大值&#xff0c;来动态计算y轴最大数据以及间隔呢&#xff1f; 那我…

数组(java)

目录 数组的定义和使用&#xff1a; 数组的初始化&#xff1a; 遍历数组&#xff1a; 数组是引用类型 初始JVM的内存分布 再读引用变量 认识null 数组的应用场景 作为函数的参数 作为函数的返回值 数组练习 数组转字符串 排序 冒泡排序 数组逆序 数组求平均…

伺服驱动器算法入门的一些建议和书籍推荐

希望此篇文章对想从事伺服驱动器的研发工作的一些刚刚入门的同学一些建议。 针对伺服驱动器的研发工作涉及的知识和需要掌握的技能主要分为两部分&#xff0c;第一是原理部分、第二是工程实践部分。原理部分的学习在此主要推荐大家查看一些入门书籍&#xff0c;本文章中也对书籍…

【vue】导入组件

先行知识 用vite创建vue项目 1.导入组件 项目结构 App.vue中&#xff1a; 导入后&#xff0c;App.vue是Header.vue和Footer.vue的父组件 参考 https://www.bilibili.com/video/BV1nV411Q7RX

在js中计算两个时间段重叠的时长问题

文章目录 前言一、过程分析二、实现代码(js)总结 前言 最近遇到一个需求&#xff0c;就是在js中计算两段时间的重叠时长问题&#xff0c;这里记录一下。 一、过程分析 两段时间的重叠问题&#xff0c;一般有3中情况 两段时间完全无重叠&#xff0c;也就是无任何交集两段时间…

08 Php学习:if语句、Switch语句

PHP 条件语句 当您编写代码时&#xff0c;您常常需要为不同的判断执行不同的动作。您可以在代码中使用条件语句来完成此任务。 在 PHP 中&#xff0c;提供了下列条件语句&#xff1a; if 语句 - 在条件成立时执行代码 if…else 语句 - 在条件成立时执行一块代码&#xff0c;…

【树哈希】CF1182D Complete Mirror

CF1182D - Complete Mirror Description 给定一个 n n n 个点的无根树&#xff0c;求一个树根 r o o t root root,使得对于任意两个节点 v 1 , v 2 v_1,v_2 v1​,v2​&#xff0c;若满足 d i s t ( v 1 , r o o t ) d i s t ( v 2 , r o o t ) dist(v_1,root)dist(v_2,ro…

【CSS】SVG图片属性及修改颜色

最近的开发中遇到了SVG不能修改颜色的问题&#xff0c;以前是直接用&#xff0c;没有研究过&#xff0c;现在搞个笔记记录下 SVG的属性&#xff1a; width:设置最终SVG图片的宽度height:设置最终SVG图片的高度viewbox&#xff1a;视区&#xff0c;在svg上截取一块&#xff0c…

C++--用list容器处理约瑟夫环问题

约瑟夫环 约瑟夫环问题是一个经典的数学问题&#xff0c;描述如下&#xff1a; 假设有 n 个人站成一圈&#xff0c;编号从 1 到 n。从第一个人开始报数&#xff0c;报到 m 的人出列&#xff0c;然后下一个人继续从 1 开始报数&#xff0c;直到所有人都出列为止。问最后留下的…

013:vue3 Pinia详解使用详解

文章目录 1. Pinia 是什么2. Pinia 功能作用3. 手动添加Pinia到Vue项目4. Pinia基础使用5. getters实现6. action异步实现7. storeToRefs工具函数8. Pinia的调试9. 总结 1. Pinia 是什么 Pinia 是 Vue 的专属的 最新状态管理库是 Vuex 状态管理工具的替代品和 Vuex 一样为 Vue…

ESP-IDF移植lvgl 驱动 ST7789

文章目录 1 前言2 准备3 移植LVGL3.1 工程准备3.2 修改 CMakeLists.txt文件编译 LVGL3.3 编译LVGL 4 编译 ST7789 LCD驱动5 发现问题 1 前言 本教程开始学习 LVGL的&#xff0c;开始之前要把环境配置好&#xff0c;首先就需要移植 lvgl&#xff0c;使用的是 esp32 环境&#xf…

计算机网络——ARP协议

前言 本博客是博主用于复习计算机网络的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 这篇博客是在B站掌芝士zzs这个UP主的视频的总结&#xff0c;讲的非常好。 可以先去看一篇视频&#xff0c;再来参考这篇笔记&#xff08;或者说直接偷走&#xff09;。 …

Javaweb监听器(Listener)

一、概念 1.Listener表示监听器。是Javaweb三大组件&#xff08;Servlet、Filter、Listener&#xff09;之一 2.优先级为监听器>过滤器>servlet 3.监听器可以监听就是在application&#xff0c;session&#xff0c;request三个对象创建、销毁或者往其中添加修改删除属性…

MySQ数据库: MySQL数据库的安装配置 ,图文步骤详细,一篇即可完成安装完成! MySQL数据库如何与客户端连接

LiuJinTao&#xff1a; 2024年4月14日 文章目录 MySQL的安装配置1. 下载2. 安装 三、 MySQL 启动与停止1. 第一种 方式&#xff1a;2. 第二种方式&#xff1a; 四、MySQL 客户端连接2. 方式二&#xff1a; MySQL的安装配置 1. 下载 官方下载网址&#xff1a;https://www.mysq…

2024蓝桥杯省赛C++软件算法研究生组题解+游记

A题 给你一个音游的游戏记录log.txt&#xff0c;判断玩家的最高连击数 题解 水题&#xff0c;但是要小心&#xff0c;miss的键需要重置k0&#xff0c;超时但正确的键重置k1 个人答案是9 B题 计算1~2024041331404202中有多少个数x满足x! - x*(x1)/2能被100整除 题解 首先…

数字乡村创新实践探索农业现代化与乡村振兴新路径:科技赋能农村全面振兴与农民幸福新篇章

随着信息技术的飞速发展&#xff0c;数字乡村成为推动农业现代化与乡村振兴的重要战略举措。科技赋能下的数字乡村创新实践&#xff0c;不仅提升了农业生产的智能化水平&#xff0c;也为乡村治理和农民生活带来了翻天覆地的变化。本文旨在探讨数字乡村创新实践在农业现代化与乡…

【vue】Vue3开发中常用的VSCode插件

Vue - Official&#xff1a;vue的语法特性&#xff0c;如代码高亮&#xff0c;自动补全等 Vue VSCode Snippets&#xff1a;自定义一些代码片段 v3单文件组件vdata数据vmethod方法 别名路径跳转 参考 https://www.bilibili.com/video/BV1nV411Q7RX

Java+vue2+springboot智慧班牌系统源码,支持PC端、移动客户端、电子班牌端,SaaS模式部署

智慧班牌作为一个班级的标识&#xff0c;也是班级空间日常管理的载体&#xff0c;作为班级文化展示交流窗口与学科教学、德育管理&#xff0c;以及学校信息収布等有机结合起来&#xff0c;作为学生展示的平台&#xff0c;又可应用于普及教育安全知识和科学文化&#xff0c;拓展…