Web自动化测试(5)-POM

2023-11-15

POM设计模式

1、简介

POM(Page Object Model)设计模式又被称为页面对象模型,其核心思想是将web项目的每个页面当做一个对象,通过分层实现管理架构的优化,提高代码的复用性、可读性、可扩展性以及可维护性。POM设计模式主要分为Base层、PageObject层、TestCase层以及TestData层。

名称 功能
Base层 页面基础层,处理每个web页面对象的共性,或者说是相同的操作
PageObject层 不同的web页面定义不同的页面类,用于处理不同页面的差异性
TestCase层 用例层,主要包含页面测试的操作流程
TestData层 数据层,主要存储项目数据,包含配置数据、测试数据等

2、简单示例

关键字驱动中的示例POM设计模式的更改,首先构建basepage代码:

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import time
class BasePage:
    def __init__(self, driver):
        self.driver = driver
        time.sleep(1)
        self.driver.implicitly_wait(2)
        #超时时长为10s,由于自动化需要等待网页控件的加载,所以这里设置一个默认的等待超时,时长为10秒
        self.wait = WebDriverWait(self.driver, 10) 
    # 打开浏览器
    def open_browser(self,browser):
        browser = browser.capitalize()
        if browser in ["Chrome","Edge","Firefox"]:
            browser_driver = {"Chrome":"chromedriver","Edge":"MicrosoftWebDriver","Firefox":"geckodriver"}
            ##利用反射的方式获取浏览器驱动
            self.driver = getattr(webdriver,browser)("../%s.exe"%(browser_driver[browser]))
            self.driver.maximize_window() #窗口最大化
            self.driver.implicitly_wait(5)
        else:
            raise ValueError("未检测到支持的浏览器类型")
    # 加载网页
    def load_url(self,url):
        self.driver.get(url)
        self.driver.implicitly_wait(2)
    # 定位元素
    def locate_element(self,loc):
        # 使用*提取元组中的元素
        return self.driver.find_element(*loc)
    # 定位元素列表
    def locate_elements(self,loc):
        # 使用*提取元组中的元素
        self.wait.until(EC.presence_of_element_located(loc))
        return self.driver.find_elements(*loc)
    #输入信息
    def input(self,loc,value):
        self.locate_element(loc).send_keys(value)
        self.driver.implicitly_wait(1)
    #点击操作
    def click(self,loc):
        self.locate_element(loc).click()
        self.driver.implicitly_wait(1)
    #批量点击操作
    def click_elements(self,elements,attribute):
        for element in elements:
            if element.get_attribute(attribute):
                element.click()

接着分别构建主页搜索mainpage.py以及搜索结果点击的代码:

import sys
import time
sys.path.append("..")
from base.basepage import BasePage
from selenium.webdriver.common.by import By
class MainPage(BasePage):
    url = "https://www.baidu.com/"

    def open_page(self, url = url):
        self.load_url(url)
    
    def search_content(self, value):
        self.input((By.ID,"kw"),value)
        time.sleep(1)
        self.click((By.ID,"su"))
        time.sleep(2)
import sys
sys.path.append("..")
from base.basepage import BasePage
from selenium.webdriver.common.by import By
import time
class SearchResults(BasePage):
    def get_results(self,content):
        return self.locate_elements((By.XPATH,"//a[contains(string(), \'%s\')]"%(content)))
    
    def click_results(self, content,attribute):
        self.click_elements(self.get_results(content),attribute)
        time.sleep(5)

最后构建testCase测试代码:

from time import time
import unittest
import sys
sys.path.append("..")
from pageobjects.mainpage import MainPage
from pageobjects.searchresults import SearchResults
from selenium import webdriver
import time
class TestBaidu(unittest.TestCase):
    search_content = "selenium"
    attribute = "href"
    @classmethod
    def setUpClass(self):
        self.driver = webdriver.Edge("../../MicrosoftWebDriver.exe")
        self.driver.maximize_window()
        time.sleep(2)
        self.main_page = MainPage(self.driver)
        self.search_page = SearchResults(self.driver)
    @classmethod
    def tearDownClass(self):
        self.driver.quit()
    def test_01_openpage(self):
        self.main_page.open_page()
    def test_02_search(self):
        self.main_page.search_content(self.search_content)
    def test_03_click_results(self):
        self.search_page.click_results(self.search_content,self.attribute)
        time.sleep(5)


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

3、UnitTest框架测试用例执行顺序

从上述示例中可以看出,测试用例的函数都是以“test_dd_xxxx”的命名格式进行命名,其中“dd”表示手动指定测试用例的执行顺序,通常来说unittest框架进行自动化测试时会对测试用例进行排序,通常情况下排序的结果与字符串排序结果类似,因此如果存在多个测试用例,在不补0的情况下“test_11”会比“test_2”先执行,导致测试用例的执行顺序与预期不符的情况,因此,为了避免此种情况的发生,可以采用补0的方式即将“test_2”改为“test_02”,在这种情况下,“test_02”会先于“test_11”执行,对于测试用例特别多,比如成百上千个,可以考虑修改unittest加载测试用例的排序函数,也可以采取补0的方式。

4、数据驱动

数据驱动主要指通过一组数据或者数据文件对同一组脚本进行循环测试,从而实现数据与脚本的分离,从而提供代码的复用性、扩展性。本文利用ddt扩展库实现数据驱动的自动化测试。ddt的安装比较简单,使用如下代码即可完成安装:

pip install ddt

ddt模块主要包含类的装饰器ddt和两个方法装饰器data,具体如下表所示:

名称 功能
ddt.ddt 装饰类,继承了TestCase类
ddt.data 装饰测试方法,参数是一系列的值
ddt.file_dat 装饰测试方法,参数是文件名,文件类型可以是json或者yaml

5、简单示例

对上文中的示例进行改进,主要更改testcases.py,主要修改三处,首先引入依赖项,接着对测试类进行装饰,最后对测试方法进行装饰,此外,为了简化测试,删减了test_03测试用例:

from time import time
import unittest
import sys
sys.path.append("..")
from pageobjects.mainpage import MainPage
from pageobjects.searchresults import SearchResults
from selenium import webdriver
import time
from ddt import ddt,data # 第一处修改,引入ddt依赖库
@ddt # 第二处修改,使用类装饰器
class TestBaidu(unittest.TestCase):
    search_content = "selenium"
    attribute = "href"
    @classmethod
    def setUpClass(self):
        self.driver = webdriver.Edge("../../MicrosoftWebDriver.exe")
        self.driver.maximize_window()
        time.sleep(2)
        self.main_page = MainPage(self.driver)
        self.search_page = SearchResults(self.driver)
    @classmethod
    def tearDownClass(self):
        self.driver.quit()
    def test_01_openpage(self):
        self.main_page.open_page()
    # 第三处修改,装饰测试方法
    @data("selenium","web自动化","python")
    def test_02_search(self,search_content):
        self.main_page.search_content(search_content)


if __name__ == '__main__':
    unittest.main()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Web自动化测试(5)-POM 的相关文章

  • 将 saxon 与 python 结合使用

    我需要使用 python 处理 XSLT 目前我正在使用仅支持 XSLT 1 的 lxml 现在我需要处理 XSLT 2 有没有办法将 saxon XSLT 处理器与 python 一起使用 有两种可能的方法 设置一个 HTTP 服务 接受
  • 如何在flask中使用g.user全局

    据我了解 Flask 中的 g 变量 它应该为我提供一个全局位置来存储数据 例如登录后保存当前用户 它是否正确 我希望我的导航在登录后在整个网站上显示我的用户名 我的观点包含 from Flask import g among other
  • 为 Anaconda Python 安装 psycopg2

    我有 Anaconda Python 3 4 但是每当我运行旧代码时 我都会通过输入 source activate python2 切换到 Anaconda Python 2 7 我的问题是我为 Anaconda Python 3 4 安
  • Python(Selenium):如何通过登录重定向/组织登录登录网站

    我不是专业程序员 所以请原谅任何愚蠢的错误 我正在做一些研究 我正在尝试使用 Selenium 登录数据库来搜索大约 1000 个术语 我有两个问题 1 重定向到组织登录页面后如何使用 Selenium 登录 2 如何检索数据库 在我解决
  • 使用 matplotlib 绘制时间序列数据并仅在年初显示年份

    rcParams date autoformatter month b n Y 我正在使用 matpltolib 来绘制时间序列 如果我按上述方式设置 rcParams 则生成的图会在每个刻度处标记月份名称和年份 我怎样才能将其设置为仅在每
  • Flask如何获取请求的HTTP_ORIGIN

    我想用我自己设置的 Access Control Allow Origin 标头做出响应 而弄清楚请求中的 HTTP ORIGIN 参数在哪里似乎很混乱 我在用着烧瓶 0 10 1 以及HTTP ORIGIN似乎是这个的特点之一object
  • 在Python中获取文件描述符的位置

    比如说 我有一个原始数字文件描述符 我需要根据它获取文件中的当前位置 import os psutil some code that works with file lp lib open path to file p psutil Pro
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • 在f字符串中转义字符[重复]

    这个问题在这里已经有答案了 我遇到了以下问题f string gt gt gt a hello how to print hello gt gt gt f a a gt gt gt f a File
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 使用 \r 并打印一些文本后如何清除控制台中的一行?

    对于我当前的项目 有一些代码很慢并且我无法使其更快 为了获得一些关于已完成 必须完成多少的反馈 我创建了一个进度片段 您可以在下面看到 当你看到最后一行时 sys stdout write r100 80 n I use 80覆盖最终剩余的
  • Pandas:merge_asof() 对多行求和/不重复

    我正在处理两个数据集 每个数据集具有不同的关联日期 我想合并它们 但因为日期不完全匹配 我相信merge asof 是最好的方法 然而 有两件事发生merge asof 不理想的 数字重复 数字丢失 以下代码是一个示例 df a pd Da
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 每个 X 具有多个 Y 值的 Python 散点图

    我正在尝试使用 Python 创建一个散点图 其中包含两个 X 类别 cat1 cat2 每个类别都有多个 Y 值 如果每个 X 值的 Y 值的数量相同 我可以使用以下代码使其工作 import numpy as np import mat
  • 为字典中的一个键附加多个值[重复]

    这个问题在这里已经有答案了 我是 python 新手 我有每年的年份和值列表 我想要做的是检查字典中是否已存在该年份 如果存在 则将该值附加到特定键的值列表中 例如 我有一个年份列表 并且每年都有一个值 2010 2 2009 4 1989
  • 解释 Python 中的数字范围

    在 Pylons Web 应用程序中 我需要获取一个字符串 例如 关于如何做到这一点有什么建议吗 我是 Python 新手 我还没有找到任何可以帮助解决此类问题的东西 该列表将是 1 2 3 45 46 48 49 50 51 77 使用
  • 有人用过 Dabo 做过中型项目吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们正处于一个新的 ERP 风格的客户端 服务器应用程序的开始阶段 该应用程序是作为 Python 富客户端开发的 我们目前正在评估 Dabo
  • 使用 Python 绘制 2D 核密度估计

    I would like to plot a 2D kernel density estimation I find the seaborn package very useful here However after searching
  • 如何使用 Pycharm 安装 tkinter? [复制]

    这个问题在这里已经有答案了 I used sudo apt get install python3 6 tk而且效果很好 如果我在终端中打开 python Tkinter 就可以工作 但我无法将其安装在我的 Pycharm 项目上 pip
  • Statsmodels.formula.api OLS不显示截距的统计值

    我正在运行以下源代码 import statsmodels formula api as sm Add one column of ones for the intercept term X np append arr np ones 50

随机推荐

  • 【以太网硬件三】1000base-T和1000base-TX有什么区别?

    个人主页 highman110 作者简介 一名硬件工程师 持续学习 不断记录 保持思考 输出干货内容 从以太网的发展历程我们知道 以太网接口速率越来越高 传输距离越来越远 编码方式在不断变化发展 诞生了各种各样的以太网物理接口类型 我们先按
  • C++ 实现string字符串替换全部子串

    函数说明 对字符串中所有指定的子串进行替换 参数 string resource str 源字符串 string sub str 被替换子串 string new str 替换子串 返回值 string string subreplace
  • 记录自己激光打眼手术过程

    本人近视500度 其中300多度近视 100多度的散光 想毕业去应征入伍 所以想去做激光手术 在学校初检的医院做了激光打眼前的检查 发现角膜地形图不正常 被告知不能做 要观察半年后才能去做 我又去了JN附属医院做了检查发现还是地形图不正常
  • Ubuntu linux Androidstudio 卡死 杀死进程

    打开任务管理器 方法一 系统搜索 system monitor 如图 打开系统监视器 方法二 打开终端输入 gnome system monitor 打开系统监视器后 注意 androidstudio 对应的进程是java 在监视其中找到J
  • CTF—WEB基础篇

    01 HTML 文本标记语言 标题 h1 这是一个标题 h1 h2 这是一个标题 h2 h3 这是一个标题 h3 复制 段落 p 这是一个段落 p p 这是另外一个段落 p 复制 链接 a href URL 这是一个链接 a 复制 图像 i
  • 【Unity3D】XR: OpenVR Error! OpenVR failed initialization解决方案

    2019年12月2日 0次阅读 共213个字 0条评论 0人点赞 QueenDekimZ Console报错 XR OpenVR Error OpenVR failed initialization with error code VRIn
  • 游戏开发unity xlua框架知识系列:vscode 识别非.lua后缀的代码文件

    插眼 总结 setting json中进行配置 参考 https blog csdn net iway lch article details 91364825
  • 数据库查询语句遇到:Unknown column 'XXXX' in 'where clause'解决方法

    数据库查询语句遇到 Unknown column XXXX in where clause 解决方法 根本原因 可能是sql语句所用到的数据类型错误 int与String 弄错 我的情况 在网页其中的jsp页面接收html页面传来的cssn
  • vue3+vite3+vant搭建移动端简易模版

    前言 vue3 x相关的生态已经在不断的完善中 相应的UI 路由 pinia等都已成熟 新的项目也在考虑使用新版本开发了 开一个帖子记录一下搭建移动端简易模版的过程 方便以后回顾 vite前端构建工具 兼容性注意 Vite 需要 Node
  • 数据结构单向链表的C++实现

    本文的链表实现使用的是c 的类模板 构造节点类模板Node
  • 打卡格式

    2019 X xx Chen70
  • 还只看花书,西瓜书?一文告诉你如何正确学习深度学习,从理论到实战。

    如今春招已接近尾声 大家都知道今年就业形势整体不乐观 不仅应聘人数远远大于招聘岗位 而且面试难度加大 想拿到理想的offer更是难上加难 这段时间 很多人都在自我充电 我也经常在后台给读者解答很多深度学习相关问题 但大家问的更多的却是一些非
  • 如何查看文件的MD5值?

    MD5 什么是MD5 md5是一种信息摘要算法 是计算机广泛使用的杂凑算法之一 又译摘要算法 哈希算法 它可以从一个字符串或一个文件中按照一定的规则生成一个特殊的字符串 这个特殊的字符串就被称之为摘要 我理解就是从文件中摘一些信息片段加工而
  • R语言colorRampPalette函数-创建颜色梯度(渐变色)

    在绘热图时 需要将数值映射到不同的颜色上 这时就需要一系列的颜色梯度 colorRampPalette 函数支持自定义的创建一系列的颜色梯度 代码示例 gt colors lt colorRampPalette c blue red 5 g
  • windows加固-服务安全

    禁用TCP IP上的NetBIOS NETBIOS 在安装了TCP IP协议的同时 NetBIOS也会被作为默认设置安装到系统中 NetBIOS 协议所使用的端 是139端口 139 端 的开放意味硬盘可能会在网络中共享 网上黑客也可通Ne
  • 网络地址转换的类型及特点

    1 网络地址转换的类型及特点 NAT有三种类型 静态NAT StaticNAT 动态地址NAT PooledNAT 网络地址端口转换NAPT Port LevelNAT 静态NAT 指将内部网络的私有IP地址转换为公有IP地址 IP地址对是
  • On Distillation of Guided Diffusion Models

    本论文是解决什么问题的 无分类器引导扩散模型最近被证明在高分辨率图像生成方面非常有效 无分类器的引导扩散模型的缺点是 它们在推理时计算昂贵 原因是 因为它们需要评估两个扩散模型 一个类条件模型和一个无条件模型 数十到数百次 这篇论文提出的解
  • Linux Ubuntu安装教程

    1 创建新的虚拟机 2 选择 典型 点击 下一步 3 选择 稍后安装操作系统 点击 下一步 4 选择 Linux 版本选择 ubuntu 64位 点击 下一步 5 虚拟机名称输入 ubuntu 64位 点击 浏览 更改系统的安装位置 建议安
  • MySQL基础命令学习

    MySQL安装请看上一篇MySQL server安装记录 进入到数据库管理系统 DBMS C Windows System32 gt cd D mysql 8 0 22 winx64 bin D mysql 8 0 22 winx64 bi
  • Web自动化测试(5)-POM

    POM设计模式 目录 POM设计模式 1 简介 2 简单示例 3 UnitTest框架测试用例执行顺序 4 数据驱动 5 简单示例 1 简介 POM Page Object Model 设计模式又被称为页面对象模型 其核心思想是将web项目