UI自动化测试痛点解决方案
前言
UI自动化测试可以快速、准确地执行大量的测试用例,减少人工测试所需的时间和劳动力。能够在短时间内完成多个测试用例的执行,提高测试的效率和速度。但是UI自动化有个最大的痛点。当前端界面发生变化时,往往页面元素定位也会改变,这时就需要投入大量的人力和时间进行修改,导致我们最初引入UI自动化的初衷(节省人力、时间成本,提高测试效率和速度)不能很好的实现。针对这个问题,本篇文章介绍了怎么使用图片定位的方法进行UI自动化测试,抛弃传统的元素定位方式,这样前端页面元素样子没有发生变化,我们就不需要修改维护脚本。如果元素样子发生了变化,我们只需要将以前的元素图片换一张就可以。
介绍
本篇内容主要使用Python、Selenium、PyAutoGUI、OpenCV实现了UI自动化测试,使用图片定位方式。我们将页面元素截取成一个个单独的图片,实际上可能在UI设计后,这些图片都已经由UI设计师切图完成,我们只需要拿到这些切图就可以了。我们将这些元素切图和整体页面进行对比,找出图片在整体界面上的坐标点,然后使用Selenium的ActionChains接口执行页面交互操作就可以了。
实现方式
由于Selenium大家都比较熟悉就不过多介绍了,不熟悉的同学可以参考我之前写的文章《Selenium4.0详细介绍》。
PyAutoGUI是一个Python 第三方库,需要pip install 安装 。它允许我们通过编程方式模拟鼠标和键盘的操作,窗口操作,以及界面的截图匹配。由于它是照搬人的操作,底层没有套牢在Windows系统,所以它可以跨平台。
OOpenCV(开源计算机视觉库)是计算机视觉和机器学习领域广泛应用的一个强大工具,它提供了丰富的API,支持多种编程语言,包括C++、Python、Java等。
安装
pip install pyautogui
pip install opencv-python
# 本人在使用过程中,由于要用到截图,有个报错,需要更新Pillow版本和安装gnome-screenshot,如果没有遇到相关报错,可以忽略下面
pip install Pillow --upgrade
sudo apt install gnome-screenshot
定位图片位置
首先,我们将被测系统的元素图片截图准备好。需要进行的操作是向接口名称输入框中输入‘test’。
系统页面
元素截图
定位图片位置
import cv2
import pyautoguiinput_img = cv2.imread('input.jpg')
# confidence参数设置了匹配度阈值,范围0到1,值越高要求越精确。
input_img_location = pyautogui.locateOnScreen(input_img, confidence=0.8)
# 获取输入框图片在整体页面的坐标位置,获取的是输入框图片的中心点位置
input_img_x, input_img_y = pyautogui.center(input_img_location)
# input_img_x 370 input_img_y 250
通过上面的方法,我们获取到了输入框的坐标点,下面用Selenium元素定位看一下位置是否正确。
from selenium import webdriver
from selenium.webdriver.common.by import Byinput_el = driver.find_element(By.XPATH, '//*[@id="app"]/section/section/div/form/div[1]')
input_el_location = input_el.location
print(input_el_location['x'], input_el_location['y'])
# 220 80
我们发现,两个方法获取的坐标点不一样,由于Selenium获取的是元素的左上角的点,所以我们看一下元素的高和宽计算一下。
从上图可以看出,元素的宽是296,高是41,通过计算Selenium获取的元素中心点位置为:(368,100.5),x轴坐标没有什么问题,y轴坐标差别有点大。造成这种问题的原因可能是PyAutoGUI获取的是整个电脑屏幕的尺寸,而Selenium获取的可能是浏览器页面的尺寸,我们获取一下他们的整体尺寸对比一下。
import pyautogui
from selenium import webdriveroptions = webdriver.ChromeOptions()
options.add_argument("--start-maximized")
driver = webdriver.Chrome(options=options)
driver.get('http://172.17.0.1/apitest/#/api?id=79')
pyautogui_size = pyautogui.size()
#获取系统页面尺寸
selenium_size = driver.find_element(By.ID, 'app').size
print(pyautogui_size, selenium_size)
# Size(width=1920, height=1080) {'width': 1920, 'height': 860}
通过上面的对比发现y轴确实不一样,经过查看发现,Selenium获取的是浏览器整个窗口的尺寸,PyAutoGUI获取的是整个电脑屏幕的尺寸,所以我们需要做一个转换
# 我们将获取的元素坐标值,减去Selenium和PyAutoGUI的坐标相差的值,就是实际Selenium操作需要的坐标值,我的y值加70是因为我的操作系统是ubuntu,下面有Dock,高是70.
x = img_x - (pyautogui_x - selenium_x)
y = img_y - (pyautogui_y - selenium_y) + 70
示例
现在我们写一个脚本,使用图片定位的方式,向接口名称输入框输入“test”。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import pyautogui
import cv2options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")
driver = webdriver.Chrome(options=options)
driver.get('http://172.17.0.1/apitest/#/api?id=79')
pyautogui_size = pyautogui.size()
selenium_size = driver.find_element(By.ID, 'app').size
input_img = cv2.imread('img/input.jpg')
input_img_location = pyautogui.locateOnScreen(input_img, confidence=0.8)
input_img_x, input_img_y = pyautogui.center(input_img_location)
x = input_img_x - (pyautogui_size.width - selenium_size['width'])
y = input_img_y - (pyautogui_size.height - selenium_size['height']) + 70
ActionChains(driver).move_by_offset(x, y).click().perform()
ActionChains(driver).send_keys('test').perform()
driver.quit()
最终运行结果
总结
这样我们就完成了使用图片定位页面元素进行操作。避免了因前端改动,需要重新定位页面元素的痛点。当然这只是个简单的demo,后续项目中使用可能还会遇到其他的问题。包括图形比较复杂的元素图片,这个时候我们可以使用confidence来调整匹配度,当匹配度为1时(最高),图片的一个像素不一致都会导致无法识别出坐标点。所以可以根据自己的实际情况来调整匹配度。
相关文章:

UI自动化测试痛点解决方案
前言 UI自动化测试可以快速、准确地执行大量的测试用例,减少人工测试所需的时间和劳动力。能够在短时间内完成多个测试用例的执行,提高测试的效率和速度。但是UI自动化有个最大的痛点。当前端界面发生变化时,往往页面元素定位也会改变&#…...

如何将QAD系统EDI模块无缝迁移到知行之桥?
什么是QAD系统? QAD(Quality, Applications, Development)系统,是专为制造业设计的一款ERP软件,主要包含供应链管理、生产管理、财务和客户管理等业务功能,这家公司1979年成立于美国,目前在汽车…...

Linux学习-ELK(一)
配置三台elasticsearch服务器 安装包 elasticsearch.j2 报错 #---执行rsync命令报以下错误 [rootes1 ~]# rsync -av /etc/hosts 192.168.29.172:/etc/hosts root192.168.29.172s password: bash: rsync: 未找到命令 rsync: connection unexpectedly closed (0 bytes receive…...
Selenium事件监听
引言 你一定总是渴望从WebDriver中获得更多的日志信息,以便调试你的脚本或记录更多有关测试的信息。这里为你提供了解决方案:EventFiringWebDriver 和 WebDriverEventListener。EventFiringWebDriver 是一个类,用于包装你的WebDriver以抛出事件,而WebDriverEventListener是…...
视频写作入门:9个步骤开始您的视频日志并与观众建立真实的联系
视频博客(vlogging)通过视频内容帮助你独特的声音和故事被听到,这能与你的观众建立强烈而有意义的联系,从而促进你的业务发展。使用光年AI平台,你可以将业务场景无缝接入AI能力,轻松实现私域流量的增长。 …...

使用豆包MarsCode 编写 Node.js 全栈应用开发实践
以下是「豆包MarsCode 体验官」优秀文章,作者狼叔。 欢迎更多用户使用豆包MarsCode 并分享您的产品使用心得及反馈、创意项目开发等,【有奖征集|人人都是豆包MarsCode 测评官!】活动正在火热进行中,欢迎大家投稿参加&a…...
Spring Cloud全解析:熔断之Hystrix执行流程
Hystrix执行流程 每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中执行execute()/queue做同步或异步调用判断熔断器(circuit-breaker)是否打开,如果打开则执行fallback进行降级策略,如果关闭继续执行判断线程池/队列/信号量…...

大模型算法岗,面试百问百答,7天3个offer拿到手!
导读 大模型时代很多企业都在开发自己的大模型,这直接刺激了大模型岗位的需求。本文为大家整理了大模型面试相关的知识点,希望对大家面试求职有所帮助。 今天分享大模型面试相关知识点,持续更新。 1. RAG技术体系的总体思路 数据预处理->…...

代码随想录算法day32 | 动态规划算法part05 | 完全背包,518. 零钱兑换 II, 377. 组合总和 Ⅳ,70. 爬楼梯 (进阶)
完全背包理论基础 本题力扣上没有原题,大家可以去卡码网第52题 (opens new window)去练习,题意是一样的。 完全背包 有N件物品和一个最多能背重量为W的背包。第 i 件物品的重量是 weight[i],得到的价值是 value[i] 。每件物品都有无限个&…...
【Linux 从基础到进阶】自动化备份与恢复策略
自动化备份与恢复策略 在 Linux 运维中,数据的安全性至关重要,自动化备份与恢复策略是保障系统和数据安全的核心环节。无论是系统配置文件、用户数据、数据库还是应用程序日志,备份和恢复都能为系统灾难恢复、数据丢失等突发情况提供可靠的解决方案。 本文将介绍如何在 Ce…...

前端打包装包——设置镜像
1、打包失败,因为没装包,装包失败,因为装包的源错误 npm config get registry npm config set registry https://registry.npmmirror.com/npm install npm run build还是失败,因为缺少了包,在package.json文件中没有包…...
volatile 的作用?是否具有原子性,对编译器有什么影响?什么情况下一定要用 volatile, 能否和 const 一起使用?
目录 1. volatile 的作用 2. 是否具有原子性 3. 对编译器的影响 4.volatile 的使用场景 5.volatile 和 const 的组合 1. volatile 的作用 防止编译器优化:volatile 告诉编译器,变量的值可能会在程序的其他地方(如硬件中断、其他线程等&…...

iPhone 16分辨率,屏幕尺寸,PPI 详细数据对比 iPhone 16 Plus、iPhone 16 Pro、iPhone 16 Pro Max
史上最全iPhone 机型分辨率,屏幕尺寸,PPI详细数据!已更新到iPhone 16系列! 点击放大查看高清图 !...
FunASR搭建语音识别服务和VAD检测
搭建ASR语音识别服务(含VAD检测)教程 在本文中,我将为大家详细介绍如何搭建一套基于FunASR的ASR(语音识别)服务,并集成VAD(语音活动检测)。该服务使用阿里达摩院的模型,…...
设计一个支持多线程写入的并发日志记录系统:C++实战指南
设计一个支持多线程写入的并发日志记录系统:C实战指南 在现代软件开发中,日志记录是一个至关重要的功能,它帮助开发者调试、监控和维护系统。然而,在多线程环境中,日志记录系统需要处理多个线程同时写入日志的问题&am…...

使用LSTM(长短期记忆网络)模型预测股票价格的实例分析
一:LSTM与RNN的区别 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN)架构。LSTM是为了解决传统RNN在处理长序列数据时遇到的梯度消失或梯度爆炸问题而设计的。 在传统的RNN中,信息通过隐藏状…...

开源的 Windows 12 网页体验版!精美的 UI 设计、丰富流畅的动画
大家周二好呀!博主今天给小伙伴们分享一款炫酷的 Windows 12 体验版,网页效果拉满,非常值得我们去尝试! 如果你对未来的Windows操作系统充满期待,那么这款开源的Windows 12 网页体验版绝对不容错过!这不仅…...

chapter14-集合——(List)——day18
目录 518-Set接口方法 518-Set接口方法...

Frida 脚本抓取 HttpURLConnection 请求和响应
引入 Java 类: 引入 okhttp3.OkHttpClient、okhttp3.OkHttpClient$Builder、okhttp3.Interceptor、okhttp3.ResponseBody 等类。 创建自定义拦截器: 通过 Java.registerClass 创建自定义拦截器 MyInterceptor。拦截器中重写 intercept 方法࿰…...
Java实现建造者模式和源码中的应用
Java实现建造者模式(Builder Pattern) 文章目录 Java实现建造者模式(Builder Pattern)案例:汉堡制作建造者模式的核心角色代码实现:汉堡制作 🍔内部类实现:Step 1:产品类…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...