一、项目背景
幸运闪烁抽奖系统 是一款基于 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
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0</version>
</dependency>
<!-- WebDriverManager 用于管理浏览器驱动 -->
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
</dependency>
<!-- 屏幕截图依赖 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
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<String> 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、项目上线后观察线上数据