【测试报告】云枢馈赠系统(Java+Selenium+Jmeter自动化测试)
一、项目背景
云枢馈赠系统是一款基于 Spring Boot 实现的前后端分离式的网络抽奖系统,操作便捷,安全可靠。有管理员和普通用户两个角色,支持管理员创建普通用户、新建活动奖品、创建抽奖活动、进行抽奖、通过短信/邮箱通知中奖用户等功能。引入多种设计模式,保证系统的可迭代性和易维护性。
二、测试环境
硬件: ASUS TUF Gaming A15 FA506QM_FA506QM
操作系统: Windows 11 家庭中文版
浏览器: Google Chrome 135.0.7049.96(正式版本) (64 位)测试工具: 自动化测试 Selenium,性能测试 Jmeter
自动化脚本运行环境: IntelliJ IDEA 2024.1.4
三、测试分类
1、功能测试
1.1 测试用例
1.2 实际执行测试的部分操作截图
(1)正常登录
输入正确的手机号和密码执行登录操作
预期结果:成功登录
实际结果:成功登录
(2)注册用户测试(成功)
输入正确格式的数据,且这些手机号和邮箱没有被使用过,然后进行注册
预期结果:成功注册
实际结果:成功注册
(3)获取人员列表测试(上一步创建的用户在列表可以查询到)
预期结果:成功显示所有人员
实际结果:成功显示所有人员
(4)创建奖品测试(成功)
输入符合要求的奖品属性,进行奖品的创建
预期结果:奖品成功创建
实际结果:奖品成功创建
(5)获取奖品列表测试(上一步创建的奖品在列表可以查询到)
预期结果:显示完整的奖品属性,包括奖品id、奖品图片、奖品名、奖品价格、奖品描述
实际结果:显示完成的奖品属性
(6)创建活动测试(成功)
输入活动名称,活动描述,并且圈选奖品与人员,其中人员数量不小于奖品数量
预期结果:活动成功创建
实际结果:活动成功创建
(7)获取活动列表测试(上一步创建的活动在列表可以查询到)
预期结果:显示所有活动,不同状态活动的标识不一样
实际结果:显示所有活动,不同状态活动的标识不一样
(8)测试执行抽奖活动(成功)
点击页面未执行的活动进行抽奖,抽取完所有奖品
预期结果:成功抽完所有奖品,并给中奖人员发送短信/邮件
实际结果:成功抽完所有奖品,中奖人员接收到短信和邮件,与预期结果一致
功能测试结果:
测试用例100%通过,符合项目需求
2、非功能测试
包括:
界面测试、性能测试、兼容性测试、易用性测试、安全测试
3、自动化测试
3.1 测试用例
以页面为单元书写测试类,对主要功能进行测试
3.2 具体实现
1、添加相关依赖 pom.xml
org.seleniumhq.selenium selenium-java 4.0.0 io.github.bonigarcia webdrivermanager 5.8.0 commons-io commons-io 2.6
2、封装常用的方法
将测试过程中常用的初始化和关闭浏览器驱动,用户登录等功能进行封装,减少代码的冗余,便于后续调用。
package common; import io.github.bonigarcia.wdm.WebDriverManager;import org.apache.commons.io.FileUtils;import org.openqa.selenium.By;import org.openqa.selenium.OutputType;import org.openqa.selenium.TakesScreenshot;import org.openqa.selenium.WebDriver;import org.openqa.selenium.chrome.ChromeDriver;import org.openqa.selenium.chrome.ChromeOptions; import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.time.Duration; public class Utils { public static WebDriver driver; public static WebDriver createDriver() { if (driver == null) { // 1、打开浏览器 // 使用驱动管理程序,打开对应的浏览器驱动 // 这边使用谷歌浏览器进行自动化测试 WebDriverManager.chromedriver().setup(); // 增加浏览器配置,创建驱动对象时要强制允许访问所有的链接 ChromeOptions options = new ChromeOptions(); options.addArguments(\"--remote-allow-origins=*\"); // 创建一个浏览器驱动对象 (在这里会打开一个网页) driver = new ChromeDriver(options); // 隐式等待 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3)); } return driver; } public Utils(String url) { // 调用 driver 对象 driver = createDriver(); // 访问指定的url driver.get(url); } // 屏幕截图 public void getScreenShot(String str) throws IOException { // 屏幕截图 SimpleDateFormat sim1 = new SimpleDateFormat(\"yyyy_MM_dd\"); SimpleDateFormat sim2 = new SimpleDateFormat(\"HH_mm_ss_SSS\"); String dirTime = sim1.format(System.currentTimeMillis()); String fileTime = sim2.format(System.currentTimeMillis()); // 设置文件名称 String fileName = \"./src/test/image/\" + dirTime + \"/\" + str + \"_\" + fileTime + \".png\"; File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); // 存放至对应路径 FileUtils.copyFile(file,new File(fileName)); } // 登录 public void base_login() { // 登录页面跳转至添加奖品页面 driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13111111111\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"123456\"); driver.findElement(By.cssSelector(\"#loginForm > button\")).click(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); }}
提供了以下功能:
1、在测试开始之前,通过 Selenium WebDriver 初始化浏览器驱动(ChromeDriver)
2、获取屏幕截图并保存,根据当前时间生成文件名并将截图保存至指定路径
3、用户的登录操作
3、登录页面测试
验证登录成功的情况与登录失败的情况,具体流程如下:
1、使用 WebDriver 打开登录页面
2、输入正确手机号和正确密码
3、点击登录按钮,登录成功跳转到主页面
4、回退到登录页面
5、输入正确手机号和错误密码 / 输入错误手机号和正确密码
6、点击登录按钮,处理弹窗
7、看程序是否正常结束,若正常,则符合预期
/** * 测试登录 * 1、创建驱动,并打开页面 * 2、测试页面是否正常打开 * 3、测试正常登录:多参数测试 * 4、测试异常登录:用户名/密码错误(不测试null) */ public void login() throws InterruptedException { /** * 测试正常登录 * 流程: * 1、输入正确手机号 * 2、输入正确密码 * 3、点击登录按钮 */ driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13111111111\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"123456\"); driver.findElement(By.cssSelector(\"#loginForm > button\")).click(); /** * 测试登录失败 * 流程: * 1、回退到登录页面 * 2、输入正确/错误手机号 * 3、输入正确/错误密码 * 4、点击登录按钮 */ // 回退到登录页面 driver.findElement(By.cssSelector(\"body > div.header-box > div.user-box > div > span\")).click(); // 手机号未注册、密码正确 driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13131313131\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"111111\"); driver.findElement(By.cssSelector(\"#loginForm > button\")).click(); // 此时会有弹窗显示登录失败 点击确定 Alert alert = driver.switchTo().alert(); alert.accept(); // 手机号已注册、密码错误 driver.findElement(By.cssSelector(\"#phoneNumber\")).clear(); driver.findElement(By.cssSelector(\"#password\")).clear(); driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13111111111\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"666666\"); driver.findElement(By.cssSelector(\"#loginForm > button\")).click(); // 此时会有弹窗显示登录失败 点击确定 alert = driver.switchTo().alert(); alert.accept(); }
自动化执行结果:成功
4、注册页面测试
验证注册成功,具体流程如下:
1、使用 WebDriver 打开登录页面
2、点击页面中的注册按钮,跳转至注册页面
3、填写正确格式的属性值
4、点击注册按钮进行注册
5、在登录页面使用注册的信息进行登录,验证是否注册成功
6、如果成功登录,就说明注册成功,程序正常执行完毕
/** * 测试注册 * 1、刷新页面 * 2、跳转至注册页面 * 3、填写注册信息 * 4、点击注册按钮 * 5、回到登录页面测试是否可以登录 */ public void register() throws InterruptedException { // 刷新页面 driver.navigate().refresh(); // 在登录界面点击跳转注册 driver.findElement(By.cssSelector(\"body > div > div.login-container.col-sm-6.col-md-6.col-lg-5.col-xl-5 > div.register-link > a\")).click(); // 填写信息 driver.findElement(By.cssSelector(\"#name\")).sendKeys(\"自动化测试\"); driver.findElement(By.cssSelector(\"#mail\")).sendKeys(\"test@qq.com\"); driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13100000000\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"123456\"); driver.findElement(By.cssSelector(\"#registerForm > button\")).click(); // 注册完有弹窗显示注册成功,点击确认。点击完跳转回登录界面 Thread.sleep(100); Alert alert = driver.switchTo().alert(); alert.accept(); // 测试注册成功 driver.findElement(By.cssSelector(\"#phoneNumber\")).clear(); driver.findElement(By.cssSelector(\"#password\")).clear(); driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13100000000\"); driver.findElement(By.cssSelector(\"#password\")).sendKeys(\"123456\"); driver.findElement(By.cssSelector(\"#loginForm > button\")).click(); driver.close(); }
自动化执行结果:成功
5、用户页面测试
验证创建普通用户,与用户列表页功能,具体流程如下:
1、在主页面点击进入注册普通用户界面
2、输入用户名、手机号、邮箱
3、点击注册按钮
4、注册成功自动跳转至人员列表页(逆序排列)
5、校验首个人员用户名是否与新注册的一致
6、若一致,则说明注册成功,程序正常执行完毕
public void createUser() throws InterruptedException { // 进入注册普通用户界面 driver.findElement(By.cssSelector(\"#register\")).click(); // 显示等待,直到输入框出来 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3)); // 找到输入框,输入信息,点击注册按键 driver.findElement(By.cssSelector(\"#name\")).sendKeys(\"普通用户\"); driver.findElement(By.cssSelector(\"#mail\")).sendKeys(\"123456@qq.com\"); driver.findElement(By.cssSelector(\"#phoneNumber\")).sendKeys(\"13200000000\"); // 注册成功弹出弹窗 点击确定 自动跳转到人员列表页 Thread.sleep(100); Alert alert = driver.switchTo().alert(); alert.accept(); // 注册成功的用户会显示在首行 测试名称是否与要求的一致 String name = driver.findElement(By.cssSelector(\"#userList > tr:nth-child(1) > td:nth-child(2)\")).getText(); System.out.println(\"自动化测试创建普通用户是否成功 -> \" + name.equals(\"普通用户\")); }
自动化测试结果:打印 \"自动化测试创建普通用户是否成功 -> true\",符合预期
6、奖品页面测试
验证创建奖品和奖品列表页功能,具体流程如下:
1、在主页面点击进入创建奖品界面
2、输入奖品属性值,上传奖品图片
3、点击创建按钮
4、创建成功自动跳转至奖品列表页(逆序排列)
5、校验首个奖品属性值是否与新创建的一致
6、若一致,则说明创建成功,程序正常执行完毕
// 测试添加奖品 public void addPrize() throws InterruptedException { base_login(); // 登录页面跳转至添加奖品页面 driver.findElement(By.cssSelector(\"body>div.cont-box>div.sidebar>ul>li:nth-child(2)>ul>li:nth-child(2)>a\")).click(); System.out.println(driver.getCurrentUrl()); // 目标元素可能位于一个 iframe 中,若未先切换到该 iframe,Selenium 就无法定位到元素 WebElement iframe = driver.findElement(By.id(\"contentFrame\")); driver.switchTo().frame(iframe); // 设置奖品名称 driver.findElement(By.cssSelector(\"#prizeName.form-control\")).sendKeys(\"自动化测试奖品\"); // 定位文件输入框元素 WebElement uploadElement = driver.findElement(By.cssSelector(\"#prizeImageUrl\")); // 上传奖品图片uploadElement.sendKeys(\"E:\\\\LotterySystem\\\\LotteryAutoTest\\\\src\\\\test\\\\robot.png\"); // 设置奖品价格 driver.findElement(By.cssSelector(\"#price.form-control\")).sendKeys(\"100\"); // 设置奖品描述 driver.findElement(By.cssSelector(\"#description.form-control\")).sendKeys(\"自动化测试设置奖品111\"); // 点击创建按钮,显示弹窗提示创建成功 Thread.sleep(1000); driver.findElement(By.xpath(\"/html/body/div/button\")).click(); Thread.sleep(200); // 等待弹窗出现 Alert alert = driver.switchTo().alert(); alert.accept(); // 跳转至奖品列表页面 测试第一个是不是设置的奖品 String prizeName = driver.findElement(By.cssSelector(\"#prizeList > tr:nth-child(1) > td:nth-child(3)\")).getText(); System.out.println(prizeName); System.out.println(\"自动化添加的奖品是否成功 -> \" + prizeName.equals(\"自动化测试奖品\")); driver.close(); }
自动化测试结果:打印 \"自动化添加的奖品是否成功 -> true\",符合预期
7、活动页面测试
验证创建活动和执行活动功能,具体流程如下:
1、在主页面点击进入创建活动界面
2、输入活动属性值,圈选奖品、人员
3、点击创建按钮
4、创建成功自动跳转至活动列表页(逆序排列)
5、校验首个活动属性值是否与新创建的一致,是否为未执行状态
6、若一致,则说明创建成功,开始执行活动
7、点击执行活动,页面跳转,需切换句柄
8、执行活动,若程序正常运行完毕,则说明符合需求
public void createActivity() throws InterruptedException { base_login(); // 进入创建抽奖活动界面 driver.findElement(By.cssSelector(\"#createActivity\")).click(); // 进入iframe WebElement iframe = driver.findElement(By.id(\"contentFrame\")); driver.switchTo().frame(iframe); // 输入活动名称、活动描述 driver.findElement(By.cssSelector(\"#activityName\")).sendKeys(\"自动化活动名称\"); driver.findElement(By.cssSelector(\"#description\")).sendKeys(\"自动化活动描述\"); Thread.sleep(1000); // 圈选奖品 // 点击圈选按钮、圈选人员、点击确定、看圈选按钮是否显示已圈选 driver.findElement(By.cssSelector(\"#buttonPrizes\")).click(); driver.findElement(By.cssSelector(\"#prize-30\")).click(); driver.findElement(By.cssSelector(\"#prizesModal > div > div.form-btn-box > button.btn.btn-primary\")).click(); String putPrize = driver.findElement(By.cssSelector(\"#buttonPrizes\")).getText(); if (putPrize.equals(\"圈选奖品(已选)\")) { System.out.println(\"圈选奖品成功\");} // 圈选人员 // 点击圈选按钮、圈选人员、点击确定、看圈选按钮是否显示已圈选 driver.findElement(By.cssSelector(\"#buttonUsers\")).click(); driver.findElement(By.cssSelector(\"#user-42\")).click(); driver.findElement(By.cssSelector(\"#usersModal > div > div.form-btn-box > button.btn.btn-primary\")).click(); String putUser = driver.findElement(By.cssSelector(\"#buttonUsers\")).getText(); if (putUser.equals(\"圈选人员(已选)\")) { System.out.println(\"圈选人员成功\"); } // 创建活动 driver.findElement(By.cssSelector(\"#createActivity\")).click(); // 处理弹窗 Thread.sleep(200); Alert alert = driver.switchTo().alert(); alert.accept(); // 校验活动是否创建成功 String activityName = driver.findElement(By.cssSelector(\"#activities > div:nth-child(1) > div.activity-info > h4\")).getText(); if (activityName.equals(\"自动化活动名称\")) { System.out.println(\"活动创建成功\"); } // 此时页面在奖品列表页 // 测试执行抽奖活动 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3)); driver.findElement(By.cssSelector(\"#activities > div:nth-child(1) > div.active > p > a\")).click(); // 跳转至新标签页 需要切换句柄 // 获取当前页面句柄 String currentHandle = driver.getWindowHandle(); Set allHandles = driver.getWindowHandles(); for (String handle : allHandles) { // 如果句柄和当前的不一样,就切换 if (!handle.equals(currentHandle)) { driver.switchTo().window(handle); } } // 点击抽奖 driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3)); driver.findElement(By.cssSelector(\"#container > div.opt-box > span.btn.next-btn\")).click(); driver.findElement(By.cssSelector(\"#container > div.opt-box > span.btn.next-btn\")).click(); driver.findElement(By.cssSelector(\"#container > div.opt-box > span.btn.next-btn\")).click(); driver.close(); }
自动化测试结果:程序正常执行完毕,符合预期
四、遗留风险
由于测试时间紧张,先保证了抽奖主体功能没问题,可能存在细节测试不到位
五、测试结果评估
1、主线功能测试通过,项目可以上线
2、项目上线后观察线上数据