当前位置: 首页 > news >正文

Python —— UI自动化之Page Object模式

1、Page Object模式简介

1、二层模型

        Page Object Model(页面对象模型), 或者也可称之为POM。在UI自动化测试广泛使用的一种分层设计 模式。核心是通过页面层封装所有的页面元素及操作,测试用例层通过调用页面层操作组装业务逻辑。

1、实战 

目录如下:

home_page.py文件的内容:

from selenium.webdriver.common.by import Byclass HomePage:login_link_locator = (By.LINK_TEXT, '登录')def click_login_link(self,driver):# 前面加*号是解包的操作,因为login_link_locator是元组driver.find_element(*self.login_link_locator).click()

login_page.py文件的内容:

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import Byclass LoginPage:#属性->元素定位信息(元素定位方法+元素定位值)-元组类型phone_input_locator = (By.XPATH,'//input[@placeholder="请输入手机号/用户名"]')pwd_input_locator = (By.XPATH,'//input[@placeholder="请输入密码"]')login_button_locator = (By.CLASS_NAME,'login-button')#操作->元素行为,登录操作def page_login(self,driver,phone,pwd):# *self.phone_input_locator 前面的*号是解包使用的driver.find_element(*self.phone_input_locator).send_keys(phone)driver.find_element(*self.pwd_input_locator).send_keys(pwd)sleep(2)driver.find_element(*self.login_button_locator).click()

登录案例 - PO.py的文件内容:

from selenium import webdriver
from d6_JavaScript处理.testcases.home_page import HomePage
from d6_JavaScript处理.testcases.login_page import LoginPagedriver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://mall.banan.com:3344/")
HomePage().click_login_link(driver)LoginPage().page_login(driver,"1723693766728","ydgcdlcb")

2、三层模型

        基本的PO分层包括页面层与用例层,但是在编写页面层代码时会发现一个问题:页面中存在非常多相同 的操作方法,比如都需要等待元素、获取元素属性/文本信息、页面滚动等等,每个页面层类都需要有相 同的代码,代码存在非常多冗余。我们可以把这些【公共】的页面操作方法给提取出来放到一个类中进 行维护,其他的页面类共用该类中的操作方法即可(通过继承实现)。

UI自动化断言:
        断言是自动化测试不可缺少的部分,当我们使用测试脚本对业务逻辑进行操作时,需要检查交互操作之 后结果的正确性,此时需要通过断言机制来进行验证。

        Pytest测试框架内置丰富的断言,通过assert语句即可,常见的断言方法比较包括:

  • 比较相等
assert a == b
  • 比较大小(大于/小于/大于等于/小于等于)
assert a > b
  • 内容包含/内容不包含
assert a in b
  • 验证表达式是否为真
assert condition
UI自动化常见的断言条件包括:
  • 通过当前页面的URL地址

  • 通过当前页面的标题
  • 通过当前页面的提示文本信息
  • 通过当前页面的某些元素变化/显示

一句话总结:通过肉眼观察页面的变化检查

3、三层模型实战

思路:抽取一个公共类,这个类中可以写公共页面的属性和函数,也可以写每次都要使用的属性,从UI自动化的角度来看,浏览器驱动是每次执行用例都会用到的,所以也可以抽取出来。

三层模型的文件目录如下:

base_page.py文件中的内容:

import osfrom selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait# BasePage 用来存放所有页面类的公共部分,一些公共的操作(显式封装)
class BasePage:def __init__(self,driver):self.driver = driver# 封装的意思:把相同类似的代码放到一个函数里面,重复使用# locator是元组的类型def wait_element_clickable(self, locator):web_element = WebDriverWait(self.driver,5,0.5).until(EC.element_to_be_clickable(locator))return web_elementdef wait_element_visible(self, locator):# web_element代表通过显示等待找到的元素web_element = WebDriverWait(self.driver,5,0.5).until(EC.visibility_of_element_located(locator))return web_elementdef wait_element_presence(self, locator):web_element = WebDriverWait(self.driver,5,0.5).until(EC.presence_of_all_elements_located(locator))return web_element# JavaScript进行元素的滚动def page_scroll(self,distance):self.driver.execute_script(f"document.documentElement.scrollTop={distance}")# JavaScript进行元素的点击def page_js_click(self,locator):element = self.wait_element_visible(self.driver,locator)self.driver.execute_script("arguments[0].click()",element)# JavaScript进行元素的移除def remove_element_attribute(self,locator,attribute):element = self.wait_element_visible(self.driver,locator)self.driver.execute_script(f"arguments[0].removeAttribute({attribute})", element)# 鼠标点击def mouse_click(self,locator):element = self.wait_element_visible(self.driver,locator)ActionChains(self.driver).click(element).perform()# 窗口切换def switch_to_window(self,title):handles = self.driver.window_handlesfor handle in handles:if self.driver.title == title:breakelse:self.driver.switch_to.window(handle)# 文件上传def update_file(self,filepath):os.system(f"test.exe {filepath}")

home_page.py文件中的内容:

import timefrom selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from PO模式优化与自动化用例断言.common.base_page import BasePageclass HomePage(BasePage):# 属性-登录链接login_link_locator = (By.LINK_TEXT,'登录')# 欢迎提示信息welcome_tips_locator = (By.XPATH,'//span[text()="欢迎来到天使的世界"]')welcome_tips_text_locator = (By.XPATH,'//span[@class="text"]')# 用户名username_text_locator = (By.XPATH,'//a[@class="link-name"]')def click_login_link(self):self.wait_element_clickable(self.login_link_locator).click()def is_display_welcome_tips(self):time.sleep(2)# return  self.wait_element_clickable(self.welcome_tips_locator).is_displayed()return self.wait_element_clickable(self.welcome_tips_text_locator).textdef get_username_text(self):return self.wait_element_visible(self.username_text_locator).text

login_page.py文件中的内容: 

import timefrom selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from PO模式优化与自动化用例断言.common.base_page import BasePageclass LoginPage(BasePage):# 属性->元素定位信息(元素定位方法+元素定位值)-元组类型phone_input_locator = (By.XPATH, '//input[@placeholder="请输入手机号/用户名"]')pwd_input_locator = (By.XPATH, '//input[@placeholder="请输入密码"]')login_button_locator = (By.CLASS_NAME, 'login-button')login_tips_locator = (By.XPATH, '//p[@class="el-message__content"]')def login(self,phone,pwd):# 因为继承了 basepage类,所以克不用再写driver参数# self.wait_element_visible(self.driver,self.phone_input_locator).send_keys("17728373518")self.wait_element_visible(self.phone_input_locator).send_keys(phone)self.wait_element_visible(self.pwd_input_locator).send_keys(pwd)self.wait_element_clickable(self.login_button_locator).click()time.sleep(3)def get_login_tips(self):# 这里比较文本内容return self.wait_element_visible(self.login_tips_locator).textprint(self.wait_element_visible(self.login_tips_locator).text)

test_login.py文件中的内容

from selenium import webdriver
from d7_PO模式优化与自动化用例断言.pageobjects.home_page import HomePage
from d7_PO模式优化与自动化用例断言.pageobjects.login_page import LoginPagedef test_login_success():driver = webdriver.Chrome()driver.get("http://mall.banan.com:3344/")driver.maximize_window()# 点击首页的登录操作homepage = HomePage(driver)homepage.click_login_link()# 在登陆页面进行登录操作loginpage = LoginPage(driver)loginpage.login("le_auto","le123456")# 断言检测测试是否成功(通过预期结果和实际结果的比较)#  检查点:1、欢迎页,如果函数的返回值为True,那么断言之后返回是通过的assert homepage.is_display_welcome_tips()# assert loginpage.get_login_tips() == '账号或者密码不正确'assert homepage.get_username_text() == 'lemon_auto'# 对登录结果的断言
def test_login_uncorrect_username():driver = webdriver.Chrome()driver.get("http://mall.banan.com:3344/")homepage = HomePage(driver)homepage.click_login_link()# 在登陆页面进行登录操作loginpage = LoginPage(driver)loginpage.login("le_auto1", "le123456")# 页面登录过程中的提示信息断言assert loginpage.get_login_tips() == '账号或密码不正确'

2、PO模式的优点

1、提高测试用例的可读性

2、提高测试用例可维护性

3、减少代码重复

相关文章:

Python —— UI自动化之Page Object模式

1、Page Object模式简介 1、二层模型 Page Object Model(页面对象模型), 或者也可称之为POM。在UI自动化测试广泛使用的一种分层设计 模式。核心是通过页面层封装所有的页面元素及操作,测试用例层通过调用页面层操作组装业务逻辑。 1、实战 …...

职能篇—自动驾驶产品经理

自动驾驶产品开发流程 在讲自动驾驶产品经理之前,先简单了解一下自动驾驶的开发体系。如上图所示,从产品需求开始,经由系统需求、系统架构、软件需求、软件架构,最终分解到软件代码实现模块,再经由MIL、SIL、HIL、VIL完…...

ubuntu安装golang

看版本:https://go.dev/dl/ 下载: wget https://go.dev/dl/go1.21.3.linux-amd64.tar.gz卸载已有的go,可以apt remove go,也可以which go之后删除那个go文件,然后: rm -rf /usr/local/go && tar…...

ES 8 新特性

1. async 和 await async 和 await 两种语法结合可以让异步代码像同步代码一样。(即:看起来是同步的,实质上是异步的。) 先从字面意思理解,async 意为异步,可以用于声明一个函数前,该函数是异步的。await 意为等待,即等待一个异步方法完成。 1.1 async async 声明(…...

linux-防火墙

目录 一、防火墙概念 1.软件防火墙 2.iptables默认规则 3.iptables的五链 4.iptables动作 5.四表五链 6.iptables实例 一、防火墙概念 linux下防火墙一般分为软件防火墙、硬件防火墙 硬件防火墙:在硬件的级别实现防火墙过滤功能,性能高&#xf…...

Pytorch--3.使用CNN和LSTM对数据进行预测

这个系列前面的文章我们学会了使用全连接层来做简单的回归任务,但是在现实情况里,我们不仅需要做回归,可能还需要做预测工作。同时,我们的数据可能在时空上有着联系,但是简单的全连接层并不能满足我们的需求&#xff0…...

爬虫进阶-反爬破解9(下游业务如何使用爬取到的数据+数据和文件的存储方式)

一、下游业务如何使用爬取到的数据 (一)常用数据存储方案 1.百万级别数据:单机数据库,搭建和使用方便快捷,成本低 2.千万级别数据:负载均衡的多台数据库,安全和稳定 3.海量数据:…...

Docker常用应用部署

Docker常用应用部署 一、Ubuntu系统Docker快速安装 Docker官网安装文档:https://docs.docker.com/engine/install/ubuntu/ # 文本处理的流编辑器 -i直接修改读取的文件内容,而不是输出到终端 # sed -i s/原字符串/新字符串/ /home/1.txt # 下面这个是修…...

【数据分享】2014-2022年我国淘宝村点位数据(Excel格式/Shp格式)

电子商务是过去一二十年我国发展最快的行业,其中又以淘宝为代表,淘宝的发展壮大带动了一大批服务淘宝电子商务的村庄,这些村庄被称为淘宝村! 截至到目前,阿里研究院梳理并公布了2014-2022年共9个年份的淘宝村名单&…...

Ubuntu 安装 docker-compose

在Ubuntu上安装Docker Compose,可以按照以下步骤进行操作: 下载 Docker Compose 二进制文件 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker…...

vue2、vue3中路由守卫变化

什么是路由守卫? 路由守卫就是路由跳转的一些验证,比如登录鉴权(没有登录不能进入个人中心页)等等等 路由守卫分为三大类: 全局守卫:前置守卫:beforeEach 后置钩子:afterEach 单个…...

Leetcode—547.省份数量【中等】

2023每日刷题(八) Leetcode—547.省份数量 实现代码 static int father[210] {0};int Find(int x) {if(x ! father[x]) {father[x] Find(father[x]);}return father[x]; }void Union(int x, int y) {int a Find(x);int b Find(y);if(a ! b) {fathe…...

Nginx 防盗链

nginx防盗链问题 盗链: 就是a网站有一张照片,b网站引用了a网站的照片 。 防盗链: a网站通过设置禁止b网站引用a网站的照片。 nginx防止网站资源被盗用模块 ngx_http_referer_module 如何区分哪些是不正常的用户? HTTP Referer…...

26. 通过 cilium pwru了解网络包的来龙去脉

pwru是一种基于eBPF的工具,可跟踪Linux内核中的网络数据包,并具有先进的过滤功能。它允许对内核状态进行细粒度检查,以便通过调试网络连接问题来解决传统工具(如iptables TRACE或tcpdump)难以解决甚至无法解决的问题。在本文中,我将介绍pwru如何在不必事先了解所有内容的…...

刷题笔记day01-数组

704 题 主要强调,左闭右闭的情况,就是每次查询都会和 [left, right] 进行比较。所以后面的都是mid-1,mid1 的情况。 package mainfunc search(nums []int, target int) int {// 二分查找方法// 每次查找都是左闭右闭的情况left : 0right : …...

C#调用C++ 的DLL传送和接收中文字符串

1 c#向c传送中文字符串 设置&#xff1a;将 字符集 改为 使用多字节字符集 cpp代码&#xff1a; extern "C"_declspec(dllexport) int input_chn_str(char in_str[]) {cout<<in_str<<endl;return 0; }c#代码&#xff1a; [DllImport("Demo.dll…...

【MySQL】数据库常见错误及解决

目录 2003错误&#xff1a;连接错误1251错误&#xff1a;身份验证错误1045错误&#xff1a;拒绝访问错误服务没有报告任何错误net start mysql 发生系统错误 5。 1064错误&#xff1a;语法错误1054错误&#xff1a;列名不存在1442错误&#xff1a;触发器中不能对本表增删改1303…...

spring常见问题汇总

1. 什么是spring? Spring是一个轻量级Java开发框架&#xff0c;最早有Rod Johnson创建&#xff0c;目的是为了解决企业级应用开发的业务 逻辑层和其他各层的耦合问题。它是一个分层的JavaSE/JavaEE full-stack&#xff08;一站式&#xff09;轻量级开源框架&#xff0c; 为开…...

java8 Lambda表达式以及Stream 流

Lambda表达式 Lambda表达式规则 Lambda表达式可以看作是一段可以传递的代码&#xff0c; Lambda表达式只能用于函数式接口&#xff0c;而函数式接口只有一个抽象方法&#xff0c;所以可以省略方法名&#xff0c;参数类型等 Lambda格式&#xff1a;&#xff08;形参列表&…...

基于Java的音乐网站管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

23-Oracle 23 ai 区块链表(Blockchain Table)

小伙伴有没有在金融强合规的领域中遇见&#xff0c;必须要保持数据不可变&#xff0c;管理员都无法修改和留痕的要求。比如医疗的电子病历中&#xff0c;影像检查检验结果不可篡改行的&#xff0c;药品追溯过程中数据只可插入无法删除的特性需求&#xff1b;登录日志、修改日志…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...