亲手教你WebUI自动化框架从零开始搭建

news2025/1/16 5:33:52

一、设计思路
PO模式

对象库层:二次封装Selenium的方法。 core:主要封装driver方法,并加入日志、失败截图
页面操作层(逻辑层):元素对象和元素操作的封装。page:封装页面的元素对象和元素操作
业务层:测试用例的操作部分。 test: 业务测试,使用testng框架执行测试用例
二、代码层级结构

代码层级如下:
.
├── README.md
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── selenium
│   │   │           └── webui
│   │   │               ├── Browser.java       浏览器类型枚举
│   │   │               ├── LocatorType.java   定位方式类型枚举
│   │   │               ├── core
│   │   │               │   ├── Config.java    加载环境配置文件,设置浏览器driver驱动参数
│   │   │               │   ├── DriverManager.java   driver能力封装(点击、滚动、跳转、输入、元素定位查找检查、实现失败处理接口、异常截图等)
│   │   │               │   ├── FailureAction.java   失败处理接口--截图功能 
│   │   │               │   └── WebDriverFactory.java  按浏览器类型创建driver
│   │   │               ├── page
│   │   │               │   ├── HomeSearchPage.java  页面类:继承page,定义页面元素、方法
│   │   │               │   ├── Page.java   基础页面:加载PO,页面元素初始化
│   │   │               │   └── ReturnValue.java  
│   │   │               └── utils
│   │   │                   ├── Constants.java
│   │   │                   ├── FileManager.java   文件处理:查找文件是否存在,删除文件
│   │   │                   ├── JsonFileParser.java  json文件处理
│   │   │                   ├── ResourcePathParser.java 读取path
│   │   │                   ├── SshCmd.java   执行ssh,并执行命令
│   │   │                   └── Util.java   工具类:加载配置文件、日期获取、等待、js脚本
│   │   └── resources
│   │       ├── application.properties  配置文件
│   │       ├── log4j.properties  log4j配置文件
│   │       ├── testng.xml  测试用例集
│   │       └── webdriver   
│   │           ├── IEDriverServer.exe
│   │           ├── chromedriver
│   │           ├── chromedriver.exe
│   │           ├── geckodriver
│   │           ├── geckodriver_0.11.0.exe
│   │           └── geckodriver_0.17.0.exe
│   └── test
│       └── java
│           └── com
│               └── selenium
│                   └── webui
│                       ├── TestPage.java  基础页面测试类:BeforeClass/AfterClass操作
│                       └── page
│                           └── TestHomeSearchPage.java  测试页面类继承TestPage:具体测试用例

三、核心功能实现

1.工具类:

// Load properties: application.properties.
    public static Properties loadProperties(String path){
        try{
            InputStream is = Util.class.getClassLoader().getResourceAsStream(path);
            if (is != null){
                properties.load(is);
            }
        } catch (IOException e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return properties;
    }
 
    public static String getProperty(String path, String pName){
        Properties properties = loadProperties(path);
        return (String)properties.get(pName);
    }

2.对象库层

// selenium的二次封装
		//选择浏览器,创建driver
    public static WebDriver createWebDriver(Browser browser){
        WebDriver driver;
        Properties properties;
        final String propertyPath;
        propertyPath  = "application.properties";
        properties = Util.loadProperties(propertyPath);
        switch (browser){
            case CHROME:
                driver = new ChromeDriver(Config.getChromeOptions());
                break;
            case IE:
            	DesiredCapabilities cap=DesiredCapabilities.internetExplorer();
            	cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
            	System.setProperty("webdriver.ie.driver", properties.getProperty("ie.webdriver.driver"));
                driver = new InternetExplorerDriver(cap);
                break;
            case EDGE:
                driver = new EdgeDriver();
                break;
            case FIREFOX:
            default:
                //driver = new FirefoxDriver(Config.getFirefoxProfile());
            	System.setProperty("webdriver.gecko.driver", properties.getProperty("ff.webdriver.gecko.driver"));
            	//System.setProperty("webdriver.firefox.marionette", properties.getProperty("ff.webdriver.gecko.driver"));
            	driver = new FirefoxDriver();
        }
        driver.manage().timeouts().implicitlyWait(Config.WAIT_FOR_TIMEOUT, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        return driver;
    }
	//DriverManager.java
	// driver Capabilities
	public void navigateTo(String url) {
		logger.info("Navigate to: " + url + " to build Page: ");
		try {
			driver.get(url);
			Thread.sleep(SLEEP_DURATION);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e.getMessage());
			screenshot("Exception_navigateTo");
		}
	}
	
		public void click(WebElement we, int retries) {
		logger.info("click by: " + we);
		if (retries < MAX_RETRIES) {
			try {
				we.click();
				implicitlyWait(60);
			} catch (Exception e) {
				e.printStackTrace();
				screenshot("Exception_click");
				logger.info(e.getMessage());
				long waitTime = (1 << retries++) * 1000;
				logger.info("Retries: " + retries + " after " + waitTime
						+ " milliseconds");
				Util.sleep(waitTime);
				click(we, retries);
				throw e;
			}
		}
	}

3.逻辑层

  • 定义页面元素,并在类加载时调用initElements方法实现元素初始化
// PageFactory模式
    public static <T> T initPage(Class<T> clz) {
        logger.info("init page: " + clz.getSimpleName() + " begin...");
        T page = PageFactory.initElements(manager.getDriver(), clz);
        logger.info("init page: " + clz.getSimpleName() + " done!");
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(e.getMessage());
        }
        return page;
    }
 
public class HomeSearchPage extends Page {
	private static final Logger logger = Logger.getLogger(HomeSearchPage.class);
 
	@FindBy(id = "states-autocomplete")
	private WebElement searchBox;
 
	@FindBy(xpath = "//div[@class=\"item item-type-103\"][1]")
	private WebElement selectKeyword;
 
	@FindBy(xpath = "//div[text()=\"搜索民宿\"]")
	private WebElement searchButton;
  • 页面健康检查,页面类中被FindBy注解的字段都会检查是否存在
      public boolean healthCheck() {
        boolean flag = true;
        for (Field field : this.getClass().getDeclaredFields()) {
            if (field.isAnnotationPresent(FindBy.class)) {
                field.setAccessible(true);
                try {
                    if (!manager.weIsDisplayed((WebElement)(field.get(this)))) {
                        flag = false;
                    }
                } catch (Exception e) {
                    flag = false;
                    logger.warn(e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

4.业务层

    @Parameters({"words", "browser"})
    public void testSearch(String words, String browser) {
    	logger.debug(Constants.REG+"testSearch"+Constants.REG);
//        page = ((LoginPage)page).login(userId, password);
    	HomePage homepage = Page.initPage(HomePage.class);
        ReturnValue rv = homepage.search(words, browser);
        logger.info(page);
       // page = rv.getPage();
        Assert.assertEquals(rv.getError(), SUCCESS);
    }

参数化:testng的@Parameters读取testng.xml中参数

四、测试用例执行和测试报告

         // pom.xml
					<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20</version>
                <configuration>
                    <runOrder>alphabetical</runOrder>
                    <suiteXmlFiles>
                        <suiteXmlFile>src/main/resources/testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                    <properties>
                        <property>
                            <name>usedefaultlisteners</name>
                            <value>false</value>
                        </property>
                        <property>
                            <name>listener</name>
                            <value>org.uncommons.reportng.HTMLReporter,org.uncommons.reportng.JUnitXMLReporter</value>
                        </property>
                    </properties>
                    <forkMode>once</forkMode>
 
                </configuration>
            </plugin>
            
    // testng.xml        
    <listeners>
        <listener class-name="org.uncommons.reportng.HTMLReporter"/>
        <listener class-name="org.uncommons.reportng.JUnitXMLReporter"/>
    </listeners>
    <classes>
        <class name="com.selenium.webui.page.TestHomeSearchPage">
            <methods>
                <include name="testSelectKeyword"/>
                <include name="testSelectCity"/>
            </methods>
        </class>
    </classes>
    <test name ="Teardown Test" preserve-order="true" >
        <classes>
            <class name = "com.selenium.webui.TestPage">
                <methods>
                    <include name="shutDown"/>
                </methods>
            </class>
        </classes>
    </test>
 
    <parameter name="host" value="inn.ctrip.com/onlineinn/index" />
    <parameter name="browser" value="chrome"/>
    <parameter name="words" value="迪士尼"/>

pom.xml中加入插件,使用mvn install clean运行testng.xml中的测试用例

报告目录:test-output/html/index.html

五、持续集成

1.Jenkins安装插件:TestNG Results Plugin

2.创建job运行脚本

“构建后操作”->“Publish TestNG Results”

3.查看报告

 学习安排上
如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助,朋友们如果需要可以自行免费领取 【保证100%免费】

视频文档获取方式:

这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行领取

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

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

相关文章

零信任安全模型和多因素身份验证:提升网络安全的关键一步

近年来&#xff0c;随着疫情的蔓延和科技的飞速发展&#xff0c;数据和工作的数字化程度前所未有。这虽然为机会创造提供了更多空间&#xff0c;但也为潜在威胁行为者提供了新的入侵途径。因此&#xff0c;数据泄露的防范已经成为每个组织IT基础设施中不可或缺的一部分。 数据泄…

为什么SQL日志文件很大,该如何处理?

SQL Server 日志文件是记录所有数据库事务和修改的事务日志文件。用 SQL 术语来说&#xff0c;此日志文件记录对数据库执行的所有INSERT、UPDATE和DELETE查询操作。 如果数据库联机或恢复时日志已满&#xff0c;SQL Server 通常会发出 9002 错误。在这种情况下&#xff0c;数据…

苹果下载神器Folx2024

很多苹果电脑用户日常都会有下载东西的需求&#xff0c;不过Mac系统本身并不自带下载工具&#xff0c;我们只能使用浏览器本身的下载功能进行下载。但是很多时候浏览器的下载功能并不能满足我们的需求&#xff0c;速度也有限。 Folx2024最新版下载如下&#xff1a; https://w…

数据库开发软件Navicat Premium 15 mac中文软件介绍

Navicat Premium 15 mac是一款数据库开发工具&#xff0c;Navicat Premium 15 Mac版可以让你以单一程序同時连接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 数据库。 Navicat Premium for Mac软件介绍 Navicat premium是一款数据库管理工具。将此工具连接数…

手机怎么去水印?超级好用!

有些图片或视频中带有水印&#xff0c;这些水印可能会影响图片或视频的美观和视觉效果&#xff0c;或者可能会遮盖住部分内容。那么如何利用手机去除图片和视频水印呢&#xff1f;下面分别介绍了一些详细的操作步骤&#xff5e; 方法一&#xff1a;使用醒图APP去除图片水印 1、…

十二、W5100S/W5500+RP2040树莓派Pico<ARP 地址解析>

文章目录 1 前言2 简介2 .1 什么是ARP&#xff1f;2.2 ARP的优点2.3 ARP工作原理2.4 ARP应用场景 3 WIZnet以太网芯片4 ARP网络设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 随着网络安全越来越受到重…

API管理神器:Apipost

在数字化时代&#xff0c;API已成为企业和开发者实现数据互通、应用集成的重要桥梁。然而&#xff0c;随着API数量的不断增加&#xff0c;API设计、调试、文档和测试等工作也变得越来越复杂。为了解决这一痛点&#xff0c;一款名为Apipost的API协同研发工具应运而生&#xff0c…

如何远程访问具有多个显示器的计算机

留出扩展空间对身体和电脑屏幕都有好处。许多人受益于使用多台显示器或将笔记本电脑连接到外接显示器以扩展屏幕。对于使用屏幕的人来说&#xff0c;拥有这样的屏幕空间可能意味着更高效的工作流程和生产力。 但是&#xff0c;如果你需要远程访问那台计算机呢&#xff1f;是否…

containerd-rootless安装

实验环境&#xff1a;centos7.7.1908 参考文档&#xff1a; containerd &#xff08;nerdctl&#xff09; 依赖项 |无根容器 (rootlesscontaine.rs) [CentOS 7] 无法安装 containerd-rootless-setuptool.sh &#xff08;[ERROR] 需要 systemd &#xff08;systemctl --user&…

【Nvidia】nvidia驱动安装

1. 安装前需要安装依赖(必须执行) sudo apt-get update #更新软件列表 #安装编译依赖 sudo apt-get install g sudo apt-get install gcc sudo apt-get install make2. 查看自己的GPU型号 lspci | grep -Ei (vga|display) 或者 lspci | grep -i nvidia 或者 lspci | grep…

控制穆格射流管伺服阀控制器

驱动穆格MOOG伺服阀放大器是一种电子设备&#xff0c;用于驱动伺服阀。它能够将输入信号转换成控制电流来驱动伺服阀力矩马达&#xff0c;从而实现对流量、压力等参数的精确控制。 伺服阀已成为许多自动化系统中不可或缺的一部分。它们被广泛应用于液压和气动系统&#xff0c;…

【React】02.create-react-app基础操作

文章目录 当前以及未来的开发&#xff0c;一定是&#xff1a;组件化开发如何划分组件React的工程化/组件化开发create-react-app基础运用运用react常用版本一个React项目中&#xff0c;默认会安装 2023年最新珠峰React全家桶【react基础-进阶-项目-源码-淘系-面试题】 当前以及…

全球前十正规外盘贵金属理财软件最新排名(综合版)

随着科技的发展和金融市场的繁荣&#xff0c;贵金属理财软件成为了越来越多投资者的首选。为了帮助大家更好地选择合适的贵金属理财软件&#xff0c;本文将结合市场现状&#xff0c;通过功能评测、用户体验、优惠活动、技术安全和合规发展等方面&#xff0c;对全球前十正规外盘…

【网安AIGC专题11.1】将代码生成大模型用于命名实体识别(NER)和关系抽取(RE):提示工程设计+控制变量对比实验(格式一致性、模型忠实度、细粒度性能)

CODEIE: Large Code Generation Models are Better Few-Shot Information Extractors 写在最前面汇报研究背景命名实体识别&#xff08;NER&#xff09;和关系抽取&#xff08;RE&#xff09;相关工作作者动机研究方案实例 研究方案方案预览 实验数据集和基线模型评价指标实验方…

dfs序及相关例题

常用的三种dfs序 欧拉序 每经过一次该点记录一次的序列。 dfs序 记录入栈和出栈的序列。 dfn序 只记录入栈的序列。 dfs序 DFS 序列是指 DFS 调用过程中访问的节点编号的序列。 如何求dfs序&#xff1f;可以用以下代码来找dfs序。 vector<vector<int>> g(n…

Android开发,车载通讯应用——binder通讯原理解析

Binder简单理解 简单来说&#xff0c;Binder 就是用来Client 端和 Server 端通信的。并且 Client 端和 Server 端 可以在一个进程也可以不在同一个进程&#xff0c;Client 可以向 Server 端发起远程调用&#xff0c;也可以向Server传输数据&#xff08;当作函数参数来传&#…

JavaSE 优先级队列(堆)

目录 1 二叉树的顺序存储1.1 存储方式1.2 下标关系 2 堆(heap)2.1 概念2.2 操作-向下调整2.3 操作-建堆 3 堆的应用-优先级队列3.1 概念3.2 内部原理3.3 操作-入队列(向上调整)3.4 操作-出队列(优先级最高&#xff09;3.5 返回队首元素(优先级最高)3.6 java 中的优先级队列3.7 …

你工作中最推荐的 C/C++ 程序库有哪些,为什么?

你工作中最推荐的 C/C 程序库有哪些&#xff0c;为什么&#xff1f; 我主要做计算力学&#xff0c;说说平时用的一些c库1、前处理划网格用netgen&#xff0c;非结构网格功能强大&#xff0c;有可执行的软件和供调用的库&#xff0c;使用方便。 最近很多小伙伴找我&#xff0c;…

Trino 源码剖析

Functions function 反射和注册 io.trino.operator.scalar.annotations.ScalarFromAnnotationsParser 这里是提取注解元素的方法 String baseName scalarFunction.value().isEmpty() ? camelToSnake(annotatedName(annotated)) : scalarFunction.value(); 这里如果 scala…

早安心语微语早读,保持一颗平常心,坐看云起落花开谢得之淡然

1、保持一颗平常心&#xff0c;坐看云起落花开谢得之淡然&#xff0c;失之坦然&#xff0c;让生命中每一天都充满着阳光和希望&#xff01; 2、每个人都一样&#xff0c;都有一段独行的日子&#xff0c;或长或短&#xff0c;这都是无可回避的。不必总觉得生命空空荡荡&#xf…