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

一、概念

什么是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、等待、关闭等。代码如下:

  1. '''

  2. 基类:提供各个常用的已封装好的函数,便于后续的页面对象类进行调用。

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

  4. '''

  5. from time import sleep

  6. from selenium import webdriver

  7. class BasePage:

  8. driver = webdriver.Chrome()

  9. # 访问URL

  10. def visit(self, url):

  11. self.driver.get(url)

  12. # 元素定位

  13. def locator(self, loc):

  14. return self.driver.find_element(*loc)

  15. # 输入

  16. def input(self, loc, txt):

  17. self.locator(loc).send_keys(txt)

  18. # 点击

  19. def click(self, loc):

  20. self.locator(loc).click()

  21. # 等待

  22. def wait(self, time):

  23. sleep(time)

  24. # 关闭

  25. def close(self):

  26. self.driver.quit()

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

  3. 百度查询页面,搜索功能

  4. '''

  5. from selenium.webdriver.common.by import By

  6. from base.base_page import BasePage

  7. from selenium import webdriver

  8. class SearchPage(BasePage):

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

  10. # 定位百度输入框

  11. search_input = (By.NAME, 'wd')

  12. # 定位百度一下按钮

  13. search_button = (By.ID, 'su')

  14. # 封装实现业务流程的函数

  15. def search(self, txt):

  16. self.visit(self.url)

  17. self.wait(2)

  18. self.input(self.search_input, txt)

  19. self.wait(2)

  20. self.click(self.search_button)

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

  3. 测试类

  4. '''

  5. import unittest

  6. from page_object.search_page import SearchPage

  7. from selenium import webdriver

  8. class Case(unittest.TestCase):

  9. def test_search1(self):

  10. driver = webdriver.Chrome()

  11. txt = 'selenium'

  12. SearchPage(driver).search(txt)

  13. def test_search2(self):

  14. driver = webdriver.Chrome()

  15. txt = 'python'

  16. SearchPage(driver).search(txt)

  17. if __name__ == '__main__':

  18. unittest.main()

运行以上代码发现,因为创建了两次webdriver,所以每运行一次代码都会打开一个Chrome浏览器,同时,代码中也存在冗余。优化方案:可以增加@classmethod作为前置条件和后置条件,搜索的条件也可以采用数据驱动的方式完成,提高代码的可读性与维护性。

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

image.png

优化之后代码如下:

  1. '''

  2. 测试类

  3. '''

  4. import unittest

  5. from page_object.search_page import SearchPage

  6. from selenium import webdriver

  7. import ddt

  8. @ddt.ddt()

  9. class Case(unittest.TestCase):

  10. @classmethod

  11. def setUpClass(cls) -> None:

  12. cls.driver = webdriver.Chrome()

  13. cls.se = SearchPage(cls.driver)

  14. @classmethod

  15. def tearDownClass(cls) -> None:

  16. cls.driver.quit()

  17. @ddt.file_data('../data/searchTXT.yaml')

  18. def test_search(self, txt):

  19. self.se.search(txt)

  20. if __name__ == '__main__':

  21. unittest.main()

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

五、后记

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

 感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

L14.【LeetCode笔记】返回倒数第k个节点

目录 1.题目 2.分析 思路 代码 提交结果 1.题目 面试题 02.02. 返回倒数第 k 个节点 实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 注意:本题相对原题稍作改动 示例: 输入: 1->2->3->4->5 和 …

linux-进程间通信

进程的通信是两个或多个进程实现数据的交互,让不同的进程看到同一份资源,而这份资源是由操作系统创建管理的。如果让其中一个进程来提供的话会破坏该进程的独立性,因为这个进程内部的数据可以被其他进程看到,那这个独立性就遭到了…

基于阿里云服务器部署静态的website

目录 一:创建服务器实例并connect 二:本地文件和服务器share 三:关于IIS服务器的安装预配置 四:设置安全组 五:建站流程 六:关于备案 一:创建服务器实例并connect 创建好的服务器实例在云…

Java算法OJ(10)哈希表练习

目录 1.前言 2.正文 2.1俩数之和 2.2无重复字符的最长子串 2.3罗马数字转整数 2.4整数转罗马数字 3.小结 1.前言 哈喽大家好吖,今天来分享几道哈希表相关的练习题,操作比较基础但是思想比较重要,另外有许多思路与解法都是学习参照题解…

二叉树:堆的建立和应用

在建立堆之前,我们要知道什么是树和二叉树 树 树是一种非线性的数据结构,它是由n(n>0)个结点组成的一个具有层次关系的集合,之所以把它叫做树,是因为它长得像一棵倒挂的树,也就是根在上面&…

oracle的静态注册和动态注册

oracle的静态注册和动态注册 静态注册: 静态注册 : 指将实例的相关信息手动告知 listener 侦 听 器 , 可以使用netmgr,netca,oem 以及直接 vi listener.ora 文件来实现静态注册,在动态注册不稳定时使用,特点是:稳定&…

postgresql按照年月日统计历史数据

1.按照日 SELECT a.time,COALESCE(b.counts,0) as counts from ( SELECT to_char ( b, YYYY-MM-DD ) AS time FROM generate_series ( to_timestamp ( 2024-06-01, YYYY-MM-DD hh24:mi:ss ), to_timestamp ( 2024-06-30, YYYY-MM-DD hh24:mi:ss ), 1 days ) AS b GROUP BY tim…

调试器 gdb/cgdb 的使用

一. touch mycode.c vim mycode.c cgdb 下载 Ubuntu:sudo apt-get install -y cgdb Centos: sudo yum install -y cgdb Linux 下我们编译好的代码无法直接调试 g/gcc 默认的工作模式是release模式 程序要调试,必须是debug模式,编译时…

通过DataWorks实现MaxCompute跨项目迁移

本文为您介绍如何配置不同MaxCompute项目并实现数据迁移。 背景信息 本文使用的被迁移的原始项目为教程《简单用户画像分析(MaxCompute版)》中的WorkShop2023项目,您需要再创建一个迁移目标项目,用于存放原始项目的表、资源、配置…

【Linux】安装cuda

一、安装nvidia驱动 # 添加nvidia驱动ppa库 sudo add-apt-repository ppa:graphics-drivers/ppa sudo apt update# 查找推荐版本 sudo ubuntu-drivers devices# 安装推荐版本 sudo apt install nvidia-driver-560# 检验nvidia驱动是否安装 nvidia-smi 二、安装cudatoolkit&…

Vue.js 学习总结(14)—— Vue3 为什么推荐使用 ref 而不是 reactive

前言 ref 和 reactive 是 Vue3 中实现响应式数据的核心 API。ref 用于包装基本数据类型,而 reactive 用于处理对象和数组。尽管 reactive 似乎更适合处理对象,但 Vue3 官方文档更推荐使用 ref。 我的想法,ref就是比reactive好用,…

ctfshow-Misc入门(1-16)

misc1 查看图片得到flag misc2 1、打开文本,发现以“塒NG”开头 3、修改文件格式为png格式 4、查看图片,得到flag *遇到的问题:无法直接修改后缀名 *解决方法:需要点击文件夹,然后点击查看,将文件拓…

自动驾驶概念

1.线控底盘 由五大系统构成:线控转向、线控制动系统、线控换挡、线控油门踏板以及线控悬架。 2.自动驾驶分级 L1级别,也被称作驾驶支援阶段。在这一阶段,车辆系统能够根据驾驶环境来辅助驾驶者进行方向盘操作或减速操作中的一项&#xff0c…

【C】错误的变量定义导致sprintf()‌输出错误

问题描述 刚刚写一个用AT指令透传相关的函数,需要用到sprintf()‌拼接字符串。 结果发现sprintf()‌拼接出来的内容是错误的,简化后的代码如下: const char AT_CIPSEND_FIX_LENGTH_HEADER[11] "ATCIPSEND"; // 错误的&#xff0…

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想,将代码与数据分离,易维护,易上手。使用yaml编写编写测试用例,利用requests库发送请求,使用pytest管理用例,allure生成…

内网渗透横向移动1

1.信息收集 (1)判断域控 shell net time /domain shell ping OWA2010CN-God.god.org (2)主机探测 浏览探测->网络探测 主机列表显示: (3)域用户收集: shell net user /domain…

C++初阶——类和对象(下)

目录 1、再探构造函数——初始化列表 2、类型转换 3、static成员 4、友元 5、内部类 6、匿名对象 7、对象拷贝时编译器的优化(了解) 1、再探构造函数——初始化列表 1. 构造函数初始化除了使用函数体内赋值,还有一种方式——初始化列表, 初始化列…

数据指标与标签在数据分析中的关系与应用

导读:分享数据指标体系的文章很多,但讲数据标签的文章很少。实际上,标签和指标一样,是数据分析的左膀右臂,两者同样重要。实际上,很多人分析不深入,就是因为缺少对标签的应用。今天系统的讲解下…

Exploring Prompt Engineering: A Systematic Review with SWOT Analysis

文章目录 题目摘要简介方法论背景相关工作评估结论 题目 探索快速工程:基于 SWOT 分析的系统评价 论文地址: https://arxiv.org/abs/2410.12843 摘要 在本文中,我们对大型语言模型 (LLM) 领域的提示工程技术进行了全面的 SWOT 分析。我们强…

Android 常用命令和工具解析之内存相关

目录 1 基本概念 1.1 PSS & RSS & USS & VSS 1.1.1 PSS 1.1.2 RSS 1.2 Dirty & Clean & SwapPss 1.2.1 Private Dirty 1.2.2 Private Clean 1.2.3 SwapPss Dirty 1.3 Swap & buffers & cache 1.3.1 Swap 1.3.2 buffers 1.3.3 cache 2…