Selenium WebUI 自动化测试框架

框架结构

框架结构

框架基于 PO 模型进行设计,将页面元素与操作进行拆分,减少页面改动时的维护成本;同时使用 xsd 自定义 xml 标签,通过解析 xml 来驱动 selenium 进行执行,减少了一定的语言学习成本。
主要功能

  1. 基于 selenium-grid 做并发执行
  2. 可基于 xml 编写脚本
  3. 执行步骤可插入自定义函数
  4. 基础操作 (点击、hover、输入、值比较、切换 iframe、切换页面、关闭页面、模板匹配等)
  5. 测试报告收集

设计思路

  1. webUI 自动化大部分都基于 selenium 来进行
  2. PO 模型是 webUI 自动化中应用最广的设计模式
  3. selenium 执行时,可以通过 DataProvider 提供测试数据
  4. 常见的测试数据管理方式无外乎存在 db / 存在本地文件,并且都是结构化数据
  5. Java 有 DOM4J 库,能够很方便的解析 DOM 文档,同时 DOM 中的 XML 可以灵活定义,描述性也比较强,因此选用 XML 作为测试数据管理这样就有了一个框架大致的运行流程
    1. 初始化流程数据以及基础配置
    2. 初始化 webDriver
    3. 遍历解析后的流程数据进行执行
    4. 输出测试报告
    5. 关闭 webDriver

设计初期的明显问题
Q1:如果只能调用内置方法的话,灵活性不够
A:因此引入了 Spring 作为实例管理,这样就只需要在流程数据中使用指定标签 +beanName 就可以实现自定义方法的执行了
Q2:webUI 自动化通常执行时间过长,如何缩短?
A:引入 selenium-grid 做分布式执行,并且可以隔离数据
Q3:元素定位有没有更为准确和快捷的方式?
A:引入特征识别、模板匹配、OCR 等图像算法

基本功能

XML 描述

使用具备自描述性的 XML 进行脚本编写,降低门槛
如果想要新增标签/属性,在 XSD 中定义和对应的 entity 增加字段后,在 AutoTestSuiteParser 类中增加赋值即可

元素复用

通过 ref 标签引用 element 文件[

即可使用,重复引用可实现复用

提取与比较

通过指定 html 标签的属性获取对应值,和 variableName 以 kv 的形式存储在 threadLocal 的 Map 中,从而在同一 testFlow 的后续流程中以 $variableName 进行提取,与期望值比较

模板匹配点击

使用 JavaCV 进行模板匹配并点击的操作
eg:

使用属性 templateImgName 即可
模板图片存放于 src/test/template_img 下,源图片则是当前浏览器窗口截图
tips:使用模板匹配时,不建议在本地执行,会大概率失败,因为本地操作可能会干扰鼠标原始定位

并发与分布式执行

通过反射读取 engine.properties 文件中的配置,可动态配置并发执行用例数

并发执行时将会 send task 到 selenium-hub,并进行分发,加快执行速度

执行自定义方法

使用 custom 标签时,指定 customFunction 指定类的的 bean 名称,并且该类应该实现 ICustomAction 的 execute 方法

方法 bean 名称为_@_Service() 中的 beanName

常用操作封装

封装了常用的操作,同时可以进行扩展

环境部署

selenium-grid

m1 (arm64)

version: "3"
services:selenium-hub:image: seleniarm/hub:4.0.0-beta-1-20210215container_name: selenium-hub-armports:- "4444:4444"environment:- GRID_MAX_SESSION=50- GRID_TIMEOUT=200- START_XVFB=false- GRID_CLEAN_UP_CYCLE=200chrome:image: seleniarm/node-chromium:4.0.0-beta-1-20210215volumes:- /dev/shm:/dev/shmdepends_on:- selenium-hubenvironment:- SE_EVENT_BUS_PUBLISH_PORT=4444- SE_EVENT_BUS_HOST=selenium-hub- SE_EVENT_BUS_SUBSCRIBE_PORT=4443- NODE_MAX_INSTANCES=5- NODE_MAX_SESSION=5- GRID_CLEAN_UP_CYCLE=200

intel(x86)

version: "3"
services:selenium-hub:image: selenium/hubcontainer_name: selenium-hubports:- "4444:4444"environment:- GRID_MAX_SESSION=50- GRID_TIMEOUT=900- START_XVFB=falsechrome:image: selenium/node-chromevolumes:- /dev/shm:/dev/shmdepends_on:- selenium-hubenvironment:- SE_EVENT_BUS_PUBLISH_PORT=4444- SE_EVENT_BUS_HOST=selenium-hub- SE_EVENT_BUS_SUBSCRIBE_PORT=4443- NODE_MAX_INSTANCES=5- NODE_MAX_SESSION=5- GRID_CLEAN_UP_CYCLE=200

start.sh

#! /bin/shdocker-compose up -d --scale chrome=2

chrome=2 表示 selenium-grid 集群的节点数量,chrome 为 docker-compose 中的 service name
启动 shell 脚本,docker ps 查看是否启动成功

访问 localhost:4444 / 虚拟机 ip:4444

Extentx

创建 Dockerfile 文件

FROM node:alpine
LABEL maintainer="lain"RUN mkdir -p ./app
WORKDIR ./appRUN apk add --no-cache git
RUN git clone https://gist.github.com/3c4f35a41c58a55a0ffd00c3e64142c8.git tmpChange
RUN git clone https://github.com/anshooarora/extentx.gitRUN mv tmpChange/connections.js extentx/config/connections.js
RUN rm -rf tmpChangeWORKDIR ./extentxEXPOSE 1337RUN npm set registry https://registry.npm.taobao.org
RUN npm config set registry https://registry.npm.taobao.org
RUN npm config set disturl https://npm.taobao.org/dist
RUN npm installCMD ["./node_modules/.bin/sails", "lift"]

构建镜像
docker build -t extentx .
创建 docker-compose.yml 文件

version: '3.6'
services:extentx:build: .environment:- MONGODB_PORT_27017_TCP_ADDR=mongolinks:- mongo:mongoports:- 1337:1337mongo:image: mongo:3.4ports:- 27010:27017

docker-compose up -d启动
访问 localhost:1337 即可

打包到本地仓库

下载附在项目中的 extentsReport-1.0-SNAPSHOT.jar ,提取出 jar 包中的 pom 文件,和 jar 放在同一级目录下,执行命令
mvn install:install-file -Dfile=extentsReport-1.0-SNAPSHOT.jar -DartifactId=extentsReport -DgroupId=com.antigenmhc -Dversion=1.0-SNAPSHOT -Dpackaging=jar -DpomFile=pom.xml
即可

JavaCV (以 arm64 为例)

mac m1 (arm64)

前置环境为已下载 arm64 版本的 JDK

  1. 安装并设置环境变量
# 升级 brew
brew update
# 安装 cmake
brew install cmake
# 安装 ant
brew install antexport JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_331.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
export JAVA_AWT_INCLUDE_PATH=$JAVA_HOME
export JAVA_AWT_LIBRARY=$JAVA_HOME
export JAVA_INCLUDE_PATH=$JAVA_HOME/indclude
export JAVA_INCLUDE_PATH2=$JAVA_HOME/include/darwin
export JAVA_JVM_LIBRARY=$JAVA_HOME
  1. 打开 Java build

brew edit opencv
找到
-DBUILD_opencv_java=OFF 修改为-DBUILD_opencv_java=ON
在上面的参数之后添加参数:-DOPENCV_JAVA_TARGET_VERSION=1.8,防止使用高版本 JDK 进行编译

  1. 编译

brew install --build-from-source opencv

  1. 生成 jar 和 dylib:成功后在 /opt/homebrew/Cellar/opencv/4.7.0/share/java/opencv4 这里会生成 libopencv_java470.dylib 和 opencv-470.jar

  1. 将 jar 和 dylib 加入项目

设置项目 JDK 为刚才用来编辑 (即 JAVA\_HOME ) 的 JDK
  1. 引入依赖
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.7</version>
</dependency>
<dependency><groupId>org.bytedeco</groupId><artifactId>javacpp</artifactId><version>1.5.7</version>
</dependency>
  1. 运行 demo
//待匹配图片
Mat src = imread("filePath",Imgcodecs.IMREAD_GRAYSCALE);
Mat mInput=src.clone();
// 获取匹配模板
Mat mTemplate = imread("filePath",Imgcodecs.IMREAD_GRAYSCALE);
/**
* TM_SQDIFF = 0, 平方差匹配法,最好的匹配为0,值越大匹配越差
* TM_SQDIFF_NORMED = 1,归一化平方差匹配法
* TM_CCORR = 2,相关匹配法,采用乘法操作,数值越大表明匹配越好
* TM_CCORR_NORMED = 3,归一化相关匹配法
* TM_CCOEFF = 4,相关系数匹配法,最好的匹配为1,-1表示最差的匹配
* TM_CCOEFF_NORMED = 5;归一化相关系数匹配法
*/
int resultRows = mInput.rows() - mTemplate.rows() + 1;
int resultCols = mInput.cols() - mTemplate.cols() + 1;
Mat gResult = new Mat(resultRows, resultCols, CvType.CV_32FC1);Imgproc.matchTemplate(mInput, mTemplate, gResult, Imgproc.TM_CCORR_NORMED);Core.normalize(gResult, gResult, 0, 1, Core.NORM_MINMAX, -1, new Mat());
Core.MinMaxLocResult mmlr = Core.minMaxLoc(gResult);
Point matchLocation = mmlr.maxLoc;double x = matchLocation.x + (mTemplate.cols() / 2);
double y = matchLocation.y + (mTemplate.rows() / 2);
System.out.println(new Point(x, y));

控制台输出坐标即成功

运行项目

项目结构及说明

项目的大致结构如下

qa-ui-test-demo                                                   
├─ screen:截图                                                            
├─ src                                          
│  ├─ main                                           
│  │  └─ resources                              
│  │     ├─ css                                                      
│  │     ├─ driver:浏览器驱动                              
│  │     │  ├─ chromedriver                     
│  │     │  └─ geckodriver                                             
│  │     ├─ cc.properties:邮件发送方邮箱
│  │     ├─ extentx.properties:连接 extentx 平台配置                       
│  │     ├─ engine.properties:测试报告以及核心配置                   
│  │     ├─ mail.properties:邮件配置                     
│  │     └─ sendto.properties:邮件接收方邮箱                   
│  └─ test                                      
│     ├─ java                                   
│     │  └─ com                                 
│     │     └─ qalain                           
│     │        └─ ui                            
│     │           └─ action:java 脚本                     
│     └─ resources                              
│        ├─ page:page xml,用来转为 page pojo 的                                
│        │  └─ demo-baidu.xml                   
│        ├─ suiteflow:自动化测试流程文件                          
│        │  └─ demo-flow.xml                    
│        └─ suite-testng.xml                                    
├─ pom.xml                                                               
└─ README.md                                                     

因为经过 xml 二次封装了,所以需要了解常见标签

  1. action 为 openPage 时,需要设置的属性为 url;
  2. action 为 click 时,需要设置的属性为 refId;
  3. action 为 fillvalue 时,需要设置的属性为 elementId 和 value;
  4. action 为 compareValue 时,需要设置的属性为 refId 和 expectValue;
  5. action 为 keyBoardEnter 时,无需设置其他属性;
  6. action 为 swithWindow 时,无需设置其他属性;
  7. action 为 closeCurrentWindow 时,无需设置其他属性;
  8. action 为 closeDrive 时,无需设置其他属性;
  9. action 为 jsInvoker 时,需要设置的属性为 jsCode;
  10. action 为 custom 时,需要设置的属性为 customFunction;
  11. action 为 hover 时,无需设置其他属性

推荐Python自动化测试学习视频

【打卡WebUI自动化测试】从Selenium原理→元素定位→设计模式→关键字驱动→Excel数据驱动的实现效果,……

记录UI自动化测试框架从搭建到测试报告生成的全过程:设计模式→关键字驱动设计→Excel数据驱动设计→生成……

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

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

相关文章

关于地址存放的例题

unsigned int a 0x1234; unsigned char b *(unsigned char*)&a; 上面代码大端存储和小端存储的值分别是多少&#xff1f; 大端存储的是把高位地址存放在低位地址处&#xff0c;低位存放到高位。小端是高位存放在高位&#xff0c;低位在低位。因为a是整型&#xff0c;所…

C++ list容器的实现及讲解

所需要的基础知识 对C类的基本了解 默认构造函数 操作符重载 this指针 引用 模板等知识具有一定的了解&#xff0c;阅读该文章会很轻松。 链表节点 template<class T>struct list_node{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T&…

K8S:Pod容器中的存储方式及PV、PVC

文章目录 Pod容器中的存储方式一&#xff0e;emptyDir存储卷1.emptyDir存储卷概念2.emptyDir存储卷示例 二.hostPath存储卷1.hostPath存储卷概念2.hostPath存储卷示例 三.nfs共享存储卷1.nfs共享存储卷示例 四.PV和PVC1.PV、PVC概念2.PVC 的使用逻辑及数据流向3.storageclass插…

MySQL面试题-索引的基本原理及相关面试题

先了解一下MySQL的结构 下面我们重点讲一下存储引擎 MySQL的数据库和存储数据的目录是一一对应的&#xff0c;这些数据库的文件就保存在磁盘中对应的目录里 下面我们来看一下对应的具体数据文件 .frm是表的结构&#xff0c;不管什么样的索引都会有 .ibd代表我们现在使用的存…

基于微信小程序的房屋租赁系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境说明用户微信小程序端的主要功能有&#xff1a;户主微信小程序端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文…

力扣刷题-链表-两两交换链表中的节点

24.两两交换链表中的节点 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 解题思路 采用正常模拟的方法。 建议使用虚拟头结点&#xff0c;这样会方便很多&am…

仿制 Google Chrome 的恐龙小游戏

通过仿制 Google Chrome 的恐龙小游戏&#xff0c;我们可以掌握如下知识点&#xff1a; 灵活使用视口单位掌握绝对定位JavaScript 来操作 CSS 变量requestAnimationFrame 函数的使用无缝动画实现 页面结构 实现页面结构 通过上述的页面结构我们可以知道&#xff0c;此游戏中…

算法通关村第14关【白银】| 堆的经典问题

1.数组中的第k个最大元素 思路&#xff1a; 最直观的就是选择法&#xff0c;遍历一k次找到第k大的数之前使用快速排序的思想每次找出一个位置&#xff0c;会超时这里使用堆&#xff08;优先队列&#xff09;&#xff0c;找最大用小堆&#xff0c;找最小用大堆。 例如找第k大的…

【ArcGIS】土地利用变化分析详解(矢量篇)

土地利用变化分析详解-矢量篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤Step1&#xff1a;Step2&#xff1a;计算面积Step3&#xff1a;计算占比 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分…

计算机毕业设计 智慧养老中心管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

3、SpringBoot_配置文件

四、配置文件 1.前言 曾经使用SpringMVC的时候是手动修改tomcat配置的端口信息&#xff0c;那现在Springboot如何修改&#xff1f;springboot有一个默认的配置文件 application.properties 2.配置文件分类 常用配置信息官方文档地址 https://docs.spring.io/spring-boot/doc…

【Vue.js】使用Element搭建登入注册界面axios中GET请求与POST请求跨域问题

一&#xff0c;ElementUI是什么&#xff1f; Element UI 是一个基于 Vue.js 的桌面端组件库&#xff0c;它提供了一套丰富的 UI 组件&#xff0c;用于构建用户界面。Element UI 的目标是提供简洁、易用、美观的组件&#xff0c;同时保持灵活性和可定制性 二&#xff0c;Element…

变量、因子、缺失值、类型转换、剔除多余变量、随机抽样、用R使用SQL、trim、na.rm=TRUE、数据标准化应用

变量&#xff1a;名义型、有序型、连续型变量 名义型&#xff1a;普通事件类型&#xff0c;如糖尿病I型和糖尿病II型。 有序型&#xff1a;有顺序的事件类型&#xff0c;如一年级、二年级和三年级。 连续型&#xff1a;表示有顺序的数量&#xff0c;如年龄。 因子&#xff1a;…

【一、虚拟机vmware安装】

安装虚拟机 下载 官方下载地址&#xff1a;https://www.vmware.com/cn.html 大概流程就是&#xff0c;最重要的事最后一步

转转闲鱼交易猫链接源码 支持二维码收款

最新仿二手闲置链接源码 后台一键生成链接&#xff0c;后台管理教程&#xff1a;解压源码&#xff0c;修改数据库config/Congig 不会可以看源码里有教程 下载程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3

关于DatagridviewComboBox控件的若干技术问题

一&#xff1a;DatagridviewComboBox 选定索引更改时更改 DatagridviewTextBox 文本内容 private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e){if (dataGridView1.CurrentCell.ColumnIndex 1 && e.Contr…

vue3-ts-vite:Google 多语言调试 / 翻译

一、实现目标 二、代码实现 2.1、项目vue3 - ts - vite 2.2、index.html 引入文件 <script>window.onload function () {const script document.createElement(SCRIPT)script.src https://translate.google.com/translate_a/element.js?cbgoogleTranslateElementI…

uniapp解决h5跨域问题

我是用的最简单的方法进行去代理 在配置文件配置manifest.json 文件进行配置 "h5": {"devServer": {"port": 8080, //端口号"disableHostCheck": true,"proxy": {"/dev-api": {"target": "http://…

yum和vim工具的使用

目录 yum工具的使用 yum下载原理 软件的查找&下载&删除操作 查找lrzsz软件&#xff08;文件上传或者下载软件&#xff09; 下载lrzsz软件 删除lrzsz软件 vim工具的使用 vim命令模式 命令模式与光标相关的快捷键&#xff1a; 插入模式 底行模式 在本次的博客当中我们主要…

The 2023 ICPC Asia Regionals Online Contest (1) E. Magical Pair(数论 欧拉函数)

题目 T(T<10)组样例&#xff0c;每次给出一个n(2<n<1e18)&#xff0c; 询问多少对&#xff0c;满足 答案对998244353取模&#xff0c;保证n-1不是998244353倍数 思路来源 OEIS、SSerxhs、官方题解 2023 ICPC 网络赛 第一场简要题解 - 知乎 题解 官方题解还没有…