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

商品信息管理自动化测试

目录

前言

一、思维导图

二、代码编写

1.在pom.xml文件中添加相关依赖

         2.自动化代码编写

三、代码测试

小结


前言

1. 针对商品信息管理项目进行测试,商品信息管理项目主要有商品列表页、部门列表页、员工列表页,主要功能:对商品信息的增删改查的功能。对于商品信息管理的测试主要就是对主要功能进行测试,按照页面以及测试用例的思维导图进行自动化脚本的编写及测试。

2.自动化测试一般步骤:

1)使用Xmind编写web自动化测试用例

2)创建自动化项目,根据测试用例实现脚本的编写及测试

一、思维导图

web自动化测试用例思维导图

二、代码编写

  1. 根据思维导图进行测试用例的代码编写,每个页面一个测试类,然后在各个测试类中进行测试用例的编写。
  2. 注意公共属性需要单独放一个类,方便进行代码复用。
  3. 创建启动以及截图会频繁进行复用,所以创建方法进行封装。
  4. 注意添加隐式等待,为了确保页面正确加载显示

1.在pom.xml文件中添加相关依赖

<!--引入驱动管理依赖-->
<dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version><scope>test</scope></dependency>
<!--引入selenium依赖-->
<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version>
</dependency>
<!--引入屏幕截图依赖-->
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>

2.自动化代码编写

代码只展示主要部分

1.创建驱动对象和截屏会频繁使用,将其封装成方法


// 创建驱动对象
void createDriver() {if (driver == null) {// 1. 使用驱动管理程序打开谷歌浏览器驱动;WebDriverManager.chromedriver().setup();//  添加浏览器配置-创建的驱动对象允许浏览器访问所有链接ChromeOptions options = new ChromeOptions();options.addArguments("--remote-allow-origins=*");driver = new ChromeDriver(options);}
}/*** 截屏并保存到指定目录下* 文件名格式:./src/test/images/2025-01-29/FirstTest_130725.png*/
private void getScreenshot(String str) throws IOException {SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");// 日期 2025-01-29SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");// 时间戳 13时07分25秒25毫秒String dirTime = sim1.format(System.currentTimeMillis());// 日期目录 2025-01-29String fileTime = sim2.format(System.currentTimeMillis());// 时间戳 13时07分25秒25毫秒
//     ./src/test/images/2025-01-29/FirstTest_130725.pngString fileName = "./src/test/images/"+dirTime + "/"+str + "_" +fileTime + ".png";// 文件名System.out.println("截图文件名(fileName):" + fileName);//    拍截屏文件并保存到指定目录下File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);FileUtils.copyFile(srcFile, new File(fileName));
}

2. 测试商品搜索功能

  • 测试页面能否正常打开
  • 测试能否依据名字查询商品信息
  • 测试能否依据品牌查询商品信息
/*** 测试 商品根据名字进行搜索的功能* @throws IOException*/
void retrieveProduct() throws IOException, InterruptedException {createDriver();driver.get("http://localhost:90/#/product");// 获取商品页面中的输入框元素WebElement element = driver.findElement(By.cssSelector("body > div > section > section > main > form > div:nth-child(1) > div > div > input"));// 输入框输入内容 床上桌element.sendKeys("床上桌");// 点击搜索按钮driver.findElement(By.cssSelector("body > div > section > section > main > form > div:nth-child(2) > div > button")).click();Thread.sleep(1000);// 截屏并保存到指定目录下getScreenshot("ProductPageTest");//显示商品的详细信息,点击确定按钮driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(2) > div > div.el-dialog__footer > div > button.el-button.el-button--primary")).click();// 删除输入框中的内容 床上桌element.clear();driver.quit();
}

3.测试新增商品功能

  • 测试新增商品按钮功能能否正常使用
  • 测试填写新增商品的所有信息能否新增成功
  • 测试填写部分新增商品的信息能否新增成功
  • 测试不填写新增商品信息能否新增成功
/*** 测试 新增商品* @throws IOException* @throws InterruptedException*/
void createProduct() throws IOException, InterruptedException {createDriver();driver.get("http://localhost:90/#/product");// 点击新增按钮driver.findElement(By.cssSelector("body > div > section > section > main > div.el-row > button")).click();//     获取 名字输入框元素WebElement nameInput = driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__body > form > div:nth-child(1) > div > div > input"));// 输入内容 插头nameInput.clear();nameInput.sendKeys("插头");//  获取 价格输入框元素WebElement priceInput = driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__body > form > div:nth-child(2) > div > div > input"));// 输入内容 100priceInput.clear();priceInput.sendKeys("100");// 获取 品牌输入框元素WebElement descInput = driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__body > form > div:nth-child(3) > div > div > input"));// 输入内容descInput.clear();descInput.sendKeys("公牛");// 获取库存输入框元素WebElement stockInput = driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__body > form > div:nth-child(4) > div > div > input"));// 输入内容 100stockInput.clear();stockInput.sendKeys("100");// 点击确定按钮driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__footer > div > button.el-button.el-button--primary")).click();// 显示等待1秒,直到确定按钮被点击,然后刷新页面WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1));wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(4) > div > div.el-dialog__footer > div > button.el-button.el-button--primary")));// 刷新页面driver.navigate().refresh();
//     Thread.sleep(1000);// 截屏并保存到指定目录下getScreenshot("ProductPageTest");// 断言新增的商品是否存在
//        WebElement product = driver.findElement(By.xpath("//td[contains(text(),'插头')]"));
//     assert product != null;driver.quit();
}

4.测试修改商品信息功能

  • 测试编辑按钮功能能否正常使用
  • 测试修改商品的所有信息能否修改成功
  • 测试修改商品的部分信息能否修改成功
/*** 测试 修改商品的价格* @throws IOException* @throws InterruptedException*/
void updateProduct() throws IOException, InterruptedException {createDriver();driver.get("http://localhost:90/#/product");
//     Thread.sleep(1000);
//     隐式等待1秒driver.manage().timeouts().implicitlyWait(Duration.ofMillis(1000));// 点击编辑按钮driver.findElement(By.xpath("/html/body/div/section/section/main/div[4]/div[3]/table/tbody/tr[1]/td[5]/div/button[1]")).click();// 获取 价格输入框元素WebElement priceInput = driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(7) > div > div.el-dialog__body > form > div:nth-child(2) > div > div > input"));// 修改价格为 20priceInput.clear();priceInput.sendKeys("20");// 点击确定按钮driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(7) > div > div.el-dialog__footer > div > button.el-button.el-button--primary")).click();// 显示等待1秒,直到确定按钮被点击,然后刷新页面WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1));wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(7) > div > div.el-dialog__footer > div > button.el-button.el-button--primary")));// 刷新页面driver.navigate().refresh();// 截屏并保存到指定目录下getScreenshot("ProductPageTest");// 断言修改后的价格是否正确
//     WebElement product = driver.findElement(By.xpath("//td[contains(text(),'20')]"));
//     assert product != null;driver.quit();
}

5.测试删除商品功能

  • 测试删除按钮是否能够正常使用
  • 测试点击删除按钮再确认删除能否删除成功
  • 测试点击删除按钮再取消删除能否取消删除成功
  • 测试删除成功后刷新页面是否能够显示非删除数据
/*** 测试 删除商品* @throws IOException* @throws InterruptedException*/
void deleteProduct() throws IOException, InterruptedException {createDriver();driver.get("http://localhost:90/#/product");// 点击删除按钮driver.findElement(By.xpath("/html/body/div/section/section/main/div[4]/div[3]/table/tbody/tr[1]/td[5]/div/button[2]")).click();// 点击确定按钮
//     driver.findElement(By.cssSelector("body > div:nth-child(2) > section > section > main > div:nth-child(6) > div > div.el-dialog__footer > div > button.el-button--primary")).click();// 显示等待1秒,直到确定按钮被点击,然后刷新页面WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1));wait.until(ExpectedConditions.elementToBeClickable(By.xpath("/html/body/div/section/section/main/div[4]/div[3]/table/tbody/tr[1]/td[5]/div/button[2]")));// 刷新页面driver.navigate().refresh();// 截屏并保存到指定目录下getScreenshot("ProductPageTest");// 断言删除后的商品是否不存在
//     WebElement product = driver.findElement(By.xpath("//td[contains(text(),'头')]"));
//     assert product == null;driver.quit();
}

三、代码测试

所有测试用例通过,但发现测试耗时有些长,说明性能还有优化的空间。

小结

  1. 一定要关注测试用例的执行顺序问题
  2. 对于页面的检查一定要到位,如检查元素是否存在确保页面的正确性
  3. 驱动关闭的位置要注意,只有最后一个用例结束之后才进行关闭
  4. 为了把所有的用例的执行结果保存下来,方便后续查错或查看,此时就需要进行该方法的定义即封装一个屏幕截图的方法
  5. 注意屏幕截图保存的方式:动态时间戳并进行时间格式化,然后期望按照某种维度(天、周)以文件夹的方式进行保存
  6. 在定位元素时,当复制的cssSelector的值比较长时建议复制xpath,因为cssSelector的值比较长就可能会导致定位元素失败
  7. 可以适当关注用例执行时间,如果时间过长就需要考虑是我们自己写的测试用例的问题还是程序真的有性能问题

相关文章:

商品信息管理自动化测试

目录 前言 一、思维导图 二、代码编写 1.在pom.xml文件中添加相关依赖 2.自动化代码编写 三、代码测试 小结 前言 1. 针对商品信息管理项目进行测试&#xff0c;商品信息管理项目主要有商品列表页、部门列表页、员工列表页&#xff0c;主要功能&#xff1a;对商品信息的…...

Redis实战(黑马点评)——redis存储地理信息、位图、HyperLogLog 用法

Redis存储geo数据类型基本介绍 geo 就是 geolocation 的简写形式&#xff0c;代表地理坐标。redis 在 3.2 版本中加入了对 geo 的支持&#xff0c;允许存储地理坐标信息&#xff0c;帮助我们根据经纬度来检索数据。常见的命令有&#xff1a; geoadd&#xff1a;添加一个地理空…...

判断1到100之间有多少个素数,并输出所有的素数。

def is_prime(num): #判断一个数是否素数if num<1:return False #因为1和负数都不是素数for i in range(2,int(num**0.5)1): #从2开始到根号num的整数结束&#xff0c;因为一个数num不是素数&#xff0c;那么把必定有一个小于或等于根号num的因素if num%i0:return False #如…...

JAVA:利用 Content Negotiation 实现多样式响应格式的技术指南

1、简述 Content Negotiation&#xff08;内容协商&#xff09; 是 RESTful 服务的重要特性&#xff0c;允许客户端和服务器根据请求的不同特性动态选择适合的响应格式。它是一种在 HTTP 协议中实现的机制&#xff0c;通过它&#xff0c;服务器能够根据客户端需求返回适合的内…...

layui Table单元格编辑支持Enter键换行,包括下拉框单元格

layui Table表格编辑支持Enter键换行 可编辑单元格 $(".layui-table td").keydown(function (e) {// console.log("111",e);var index $(this).index(),tr $(this).parent(tr),isKeydown (event.type "keydown");if (e.code "Enter&q…...

Swoole的MySQL连接池实现

在Swoole中实现MySQL连接池可以提高数据库连接的复用率&#xff0c;减少频繁创建和销毁连接所带来的开销。以下是一个简单的Swoole MySQL连接池的实现示例&#xff1a; 首先&#xff0c;确保你已经安装了Swoole扩展和PDO_MySQL扩展&#xff08;或mysqli&#xff0c;但在这个示…...

无人机红外热成像:应急消防的“透视眼”

无人机红外热成像&#xff1a;应急消防的“透视眼” 亲爱的小伙伴们&#xff0c;每年一到夏天&#xff0c;应急消防的战士们就像上紧了发条的闹钟&#xff0c;时刻准备应对各种灾害。炎热天气让火灾隐患“蹭蹭”往上涨&#xff0c;南北各地还有防洪救灾、台风、泥石流等灾害轮…...

【redis】Redis操作String类型key的发生了什么?

关于Redis操作&#xff08;添加、删除、修改、查询&#xff09;String类型key的完整过程&#xff0c;包括引用源码数据、时序图、磁盘IO读写、数据长度限制和故障处理机制。 数据结构 Redis对象&#xff08;robj&#xff09; typedef struct redisObject {unsigned type:4; …...

hdfs之读写流程

写入流程&#xff1a; 客户端Client想将文件a.txt上传至hdfs&#xff0c;首先向Namenode发送请求进行权限校验&#xff0c;Namenode通过后会计算出来三个节点&#xff0c;并将这三个节点告知客户端&#xff0c;客户端将输入进行切割成块&#xff0c;一个一个的块进行传输&…...

研发的立足之本到底是啥?

0 你的问题&#xff0c;我知道&#xff01; 本文深入T型图“竖线”的立足之本&#xff1a;专业技术 技术赋能业务能力。研发在学习投入精力最多&#xff0c;也误区最多。 某粉丝感发展遇到瓶颈&#xff0c;项目都会做&#xff0c;但觉无提升&#xff0c;想跳槽。于是&#x…...

Baklib揭示内容中台与人工智能技术的创新协同效应

内容概要 在当今信息爆炸的时代&#xff0c;内容的高效生产与分发已成为各行业竞争的关键。内容中台与人工智能技术的结合&#xff0c;为企业提供了一种新颖的解决方案&#xff0c;使得内容创造的流程更加智能化和高效化。 内容中台作为信息流动的核心&#xff0c;能够集中管…...

智慧消防营区一体化安全管控 2024 年度深度剖析与展望

在 2024 年&#xff0c;智慧消防营区一体化安全管控领域取得了令人瞩目的进展&#xff0c;成为保障营区安全稳定运行的关键力量。这一年&#xff0c;行业在政策驱动、技术创新应用、实践成果及合作交流等方面呈现出多元且深刻的发展态势&#xff0c;同时也面临着一系列亟待解决…...

自定义数据集,使用 PyTorch 框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测

在本文中&#xff0c;我们将展示如何使用 NumPy 创建自定义数据集&#xff0c;利用 PyTorch 实现一个简单的逻辑回归模型&#xff0c;并在训练完成后保存该模型&#xff0c;最后加载模型并用它进行预测。 1. 创建自定义数据集 首先&#xff0c;我们使用 NumPy 创建一个简单的…...

UE5 特效

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 post processexposurebloomvignettesaturationunbound material材质蓝图alt z base colorconstant3Vector roughnessconstant metallicconstant pbrroughnessmetallicmake more realmake some areas rougher than o…...

CMAKE工程编译好后自动把可执行文件传输到远程开发板

# 设置 CMake 最低版本要求 cmake_minimum_required(VERSION 3.10)# 设置项目名称 project(MyProject)# 添加可执行文件&#xff0c;这里以项目名作为可执行文件的名称 add_executable(${PROJECT_NAME} main.cpp)# 设置开发板信息 set(DEVELOPMENT_BOARD_IP "192.168.1.10…...

Windows 程序设计7:文件的创建、打开与关闭

文章目录 前言一、文件的创建与打开CreateFile1. 创建新的空白文件2. 打开已存在文件3. 打开一个文件时&#xff0c;如果文件存在则打开&#xff0c;如果文件不存在则新创建文件4.打开一个文件&#xff0c;如果文件存在则打开文件并清空内容&#xff0c;文件不存在则 新创建文件…...

策略模式 - 策略模式的使用

引言 在软件开发中&#xff0c;设计模式是解决常见问题的经典解决方案。策略模式&#xff08;Strategy Pattern&#xff09;是行为型设计模式之一&#xff0c;它允许在运行时选择算法的行为。通过将算法封装在独立的类中&#xff0c;策略模式使得算法可以独立于使用它的客户端…...

具身智能研究报告

参考&#xff1a; &#xff08;1&#xff09;GTC大会&Figure&#xff1a;“具身智能”奇点已至 &#xff08;2&#xff09;2024中国具身智能创投报告 &#xff08;3&#xff09;2024年具身智能产业发展研究报告 &#xff08;4&#xff09;具身智能行业深度&#xff1a;发展…...

Windows安装Milvus

安装Milvus 安装Docker前置条件&#xff1a; 安装Mlivus方案一方案二 Attu管理端 安装Docker 系统&#xff1a;Windows 11 家庭中文版 Mlivus&#xff1a;V2.3.0 Attu: V2.3.10 前置条件&#xff1a; 启用“适用于 Linux 的 Windows 子系统”可选功能&#xff0c;才能在 Win…...

Excel分区间统计分析(等步长、不等步长、多维度)

在数据分析过程中&#xff0c;可能会需要统计不同数据区间的人数、某个数据区间的平均值或者进行分组区间统计&#xff0c;本文从excel函数到数据透视表的方法&#xff0c;从简单需求到复杂需求&#xff0c;采用不同的方法进行讲解&#xff0c;尤其是通过数据透视表的强大功能大…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...

Linux-进程间的通信

1、IPC&#xff1a; Inter Process Communication&#xff08;进程间通信&#xff09;&#xff1a; 由于每个进程在操作系统中有独立的地址空间&#xff0c;它们不能像线程那样直接访问彼此的内存&#xff0c;所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...

CppCon 2015 学习:REFLECTION TECHNIQUES IN C++

关于 Reflection&#xff08;反射&#xff09; 这个概念&#xff0c;总结一下&#xff1a; Reflection&#xff08;反射&#xff09;是什么&#xff1f; 反射是对类型的自我检查能力&#xff08;Introspection&#xff09; 可以查看类的成员变量、成员函数等信息。反射允许枚…...

嵌入式面试常问问题

以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...

若依项目部署--传统架构--未完待续

若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加&#xff0c;传统开发模式存在效率低&#xff0c;重复劳动多等问题。若依项目通过整合主流技术框架&…...

C/Python/Go示例 | Socket Programing与RPC

Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流&#xff0c;会涉及到许多有意思的话题&#xff0c;诸如怎么确保对方能收到信息&#xff0c;怎么应对数据丢失、被污染或者顺序混乱&#xff0c;怎么提高…...