文章目录
- 项目介绍
- 编写测试用例
- 根据测试用例编写自动化测试
- 1. 创建功能类
- 2. 编写注册功能自动化
- 3.编写登录功能自动化
- 性能测试
- 1.使用VUG编写性能测试脚本
- 2. 创建测试场景
- 3.开始执行
- 4. 简单分析性能测试报告
- 事务报告
- 运行的虚拟用户图表
- 点击率表
- 吞吐量图表
- 系统资源消耗图
项目介绍
AcCode是一个类似于牛客力扣的在线OJ平台,可以进行算法题的编写,提交后可以看到题目是否通过。项目使用的技术栈有:Java、MySQL、SpringBoot、MyBatis、Redis、Nginx、Docker。
项目的主要功能有:
- 登录注册
- 添加/修改题目信息
- 提交并运行代码,查看代码运行是否通过
- 反向代理和负载均衡
- 沙箱机制保护物理主机
编写测试用例
部分测试截图
根据测试用例编写自动化测试
使用Junit5+selenium对项目进行简单的自动化测试。把项目验证码关闭,方便自动化测试。
1. 创建功能类
public class AutoTestUtil {private static volatile ChromeDriver driver;private AutoTestUtil(){}public static ChromeDriver getDriver() {if (driver == null){synchronized (AutoTestUtil.class) {if (driver == null) {ChromeOptions options = new ChromeOptions();options.addArguments("--remote-allow-origins=*");driver = new ChromeDriver(options);// 设置隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));}}}return driver;}
}
2. 编写注册功能自动化
// 标注排序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegAutoTest {private static ChromeDriver driver;@BeforeAllpublic static void init() {driver = AutoTestUtil.getDriver();driver.get("http://127.0.0.1:7777/reg.html");driver.manage().window().maximize();}/*** 检测页面是否正确打开*/@Order(1)@Testpublic void check() {String key = driver.findElement(By.xpath("/html/body/div/h1")).getText();// 断言Assertions.assertEquals("注册账号",key);}/*** 错误注册* @param username* @param password* @param confirmPassword*/@Order(2)@ParameterizedTest@CsvSource(value = {"null,null,null","null,test,test","test,null,test","test,test,null","test,test,1234"})public void errorReg(String username,String password,String confirmPassword) throws InterruptedException {WebElement usernameInput = driver.findElement(By.xpath("//*[@id=\"username\"]"));WebElement passwordInput = driver.findElement(By.cssSelector("#password"));WebElement confirmPass = driver.findElement(By.xpath("//*[@id=\"confirmPassword\"]"));if (!"null".equals(username)) {usernameInput.sendKeys(username);}if (!"null".equals(password)) {passwordInput.sendKeys(password);}if (!"null".equals(confirmPassword)) {confirmPass.sendKeys(confirmPassword);}driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();Thread.sleep(800);// 点击警告弹窗上的确认按钮driver.switchTo().alert().accept();usernameInput.clear();passwordInput.clear();confirmPass.clear();}@Order(3)@ParameterizedTest@CsvSource(value = {"test,test,test"})public void successReg(String username,String password,String confirmPassword) throws InterruptedException {driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"confirmPassword\"]")).sendKeys(confirmPassword);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();Thread.sleep(500);driver.switchTo().alert().accept();}@AfterAllpublic static void quit() {driver.quit();}}
执行示例:
3.编写登录功能自动化
编写自动化代码
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LoginAutoTest {private static ChromeDriver driver;@BeforeAllpublic static void init() {driver = AutoTestUtil.getDriver();driver.get("http://127.0.0.1:7777/login.html");driver.manage().window().maximize();}/*** 检测页面是否正确打开*/@Order(1)@Testpublic void check() {String str = driver.findElement(By.cssSelector("body > div > h1")).getText();Assertions.assertEquals("AcCode登录",str);}@Order(2)@ParameterizedTest@CsvSource(value = {"null,null","null,test","test,null","test,123","demo,demo"})public void errorLogin(String username,String password) throws InterruptedException {WebElement usernameInput = driver.findElement(By.cssSelector("#username"));WebElement passwordInput = driver.findElement(By.xpath("//*[@id=\"password\"]"));if (!"null".equals(username)) {usernameInput.sendKeys(username);}if (!"null".equals(password)) {passwordInput.sendKeys(password);}driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();Thread.sleep(800);driver.switchTo().alert().accept();usernameInput.clear();passwordInput.clear();}@Order(3)@ParameterizedTest@CsvSource(value = {"admin,admin","test,test"})public void success(String username,String password) throws InterruptedException {driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.xpath("//*[@id=\"password\"]")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();// 检测是否跳转到题目列表页面String str = driver.findElement(By.xpath("//*[@id=\"tables\"]/div/div/h3")).getText();Assertions.assertEquals("题目列表",str);// 注销driver.findElement(By.cssSelector("body > nav > a.btn.btn-light")).click();Thread.sleep(400);driver.switchTo().alert().accept();}@AfterAllpublic static void quit() {driver.quit();}
}
测试中发现bug,如果用户不存在查询不到就会出现空指针异常,被统一异常处理捕获。
所有测试用例全部通过
自动化测试展示:
性能测试
使用LoadRunner对项目进行简单的性能测试。模拟多个用户同时进行登录后进入题目点击提交题目。
1.使用VUG编写性能测试脚本
模拟用户进入登录页面并进行登录
Action()
{// 开启进入登录页面事务lr_start_transaction("login_html");/* 注册获取返回参数,该方法可以配合打印返回数据,检测数据内容 */web_reg_save_param("ParaResult","LB=","RB=",LAST);// 定义虚拟用户集合点lr_rendezvous("user_start");// 定义检测点,检测登录页面是否正确打开web_reg_find("Text=AcCode",LAST);// 访问登录页面web_url("login_html","URL=http://127.0.0.1:7777/login.html","TargetFrame=","Resource=0","Referer=",LAST);// 结束进入登录页面事务lr_end_transaction("login_html",LR_AUTO);// 开启登录事务lr_start_transaction("login");// 进行登录web_submit_data("user_login","Action=http://127.0.0.1:7777/user/login","Method=POST","TargetFrame=","Referer=","Mode=HTTP",ITEMDATA,"Name=username", "Value={username}", ENDITEM,"Name=password", "Value={password}", ENDITEM,LAST);// 定义检测点,检测登录后题目列表页面是否正确打开web_reg_find("Text=ID",LAST);// 结束进入登录事务lr_end_transaction("login",LR_AUTO);// 开启访问题目列表事务lr_start_transaction("problemList_html");// 访问题目列表页面web_url("index_html","URL=http://127.0.0.1:7777/index.html","TargetFrame=","Resource=0","Referer=",LAST);// 结束访问题目列表事务lr_end_transaction("problemList_html",LR_AUTO);return 0;
}
添加4个用户名密码
2. 创建测试场景
1.设置10个虚拟用户
2.设置没5秒初始化两个用户
3.设置每5秒进入2个虚拟用户到测试场景
4.设置虚拟用户循环执行5分钟
5.设置执行结束后,每5秒退出一个虚拟用户
6.添加监控系统资源
监控CPU的运行时间和剩余内存
3.开始执行
4. 简单分析性能测试报告
事务报告
在事务报告中,一般只关心平均值和标准偏差,标准偏差值越大,说明越不稳定,可以到在脚本里写的login事务,
运行的虚拟用户图表
这个图标对应了前面设置的每5秒进入两个虚拟用户到测试场景,以及每5秒有一个虚拟用户从测试场景退出,中间从40秒到5分4时秒是服务器的负载时间,对应前设置的循环执行5分钟。
点击率表
通过点击率表可以看到和虚拟用户运行表运行对应起来,虚拟用户的增多点击率也随之增多,点击率越多说明和服务器的交互次数也越多。
吞吐量图表
吞吐量图形和点击数图形有点相似,但是吞吐量的曲线会稍微延后一点递增,因为吞吐量表示的是响应返回的资源数量,是要现有请求才会有响应的。
系统资源消耗图
precessorTime:CPU使用时间,被消耗的处理器时间数量
Available MBytes:可用的物理内存,一般根据这个指标推算消耗的物理内存有多大。(已经消耗的物理内存=实际内存 - 可用物理内存)