个人博客系统测试报告

文章目录

  • 一、功能测试
    • 1.编写测试用例
    • 2.总结测试后发现的BUG
  • 二、UI自动化测试
    • 0.搭建测试环境
    • 1. 创建公共类
    • 2.注册页面UI自动化测试用例编写
    • 3.登录页面UI自动化测试用例编写
    • 4.用户博客列表页面自动化测试
    • 5. 修改个信息页面
    • 6. 文章编辑页面
    • 7. 设置密保问题
      • 发现bug
    • 8. 所有用户文章列表页
    • 9. 总结
  • 三、性能测试
    • 1.编写性能测试脚本
      • 设置参数化
    • 2.创建测试场景
    • 3.开始执行
      • 简单分析性能测试报告
        • 运行的虚拟用户图表
        • 点击率表
        • 吞吐量表
        • 平均事务响应时间图
        • 系统资源图表


一、功能测试

1.编写测试用例

在这里插入图片描述

2.总结测试后发现的BUG

通过一系列的测试发现项目的以下bug:

  • 上传图片功能
    上传图片格式不正确直接跳转而没有提示,且图片格式校验不严谨
  • 发布博客测试
    文章正文为空,没有提示文章内容为空
  • 修改文章
    在修改文章时点击保存草稿没有做校验提示错误
  • 修改密码
    原密码错误,提示有问题
  • 找回密码
    未提示验证码错误,新密码格式为空
  • 博客列表页
    未简略显示文章正文字数过多问题

二、UI自动化测试

0.搭建测试环境

使用Junit5+selenium对项目进行简单的自动化测试。

引入Junit5和selenium依赖

<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>test</scope>
</dependency>
<dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.8.2</version><scope>test</scope>
</dependency>
<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>

为了方便自动化测试,这里关闭了项目的验证码功能。

1. 创建公共类

为了避免在使用时频繁创建Chrome驱动类,我们可以定义一个功能类使用单例创建驱动对象。公共类里包含了保存截图的方法,方便测试截图观察。

public class AutoTestUtil {private static volatile ChromeDriver driver;private static final String IMG_SAVE_DIR = "./src/img/";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;}/*** 获取格式化时间* @return*/private static List<String> getTime() {// 图片文件按照 包名.类名.方法名_时间搓区分SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd-HHmmssSS");// 图片目录按照天区分格式20230812SimpleDateFormat dirFormat = new SimpleDateFormat("yyyyMMdd");String fileName = fileFormat.format(System.currentTimeMillis());String dirName = dirFormat.format(System.currentTimeMillis());List<String> result = new ArrayList<>();result.add(dirName);result.add(fileName);return result;}/*** 截图* @param testFuncName 对应函数名* @throws IOException*/public static void saveFileImg(String testFuncName) throws IOException {List<String> times = getTime();String fileName = IMG_SAVE_DIR+times.get(0)+"/"+ testFuncName+"_"+times.get(1)+".png";File file = driver.getScreenshotAs(OutputType.FILE);FileUtils.copyFile(file,new File(fileName));}
}

2.注册页面UI自动化测试用例编写

在这里插入图片描述

在该测试中发现问题,找不到警告弹窗。异常信息:
在这里插入图片描述

因为我这里是采用的隐式等待,隐式等待是对弹窗不起作用的,代码执行过快就会出现代码执行到点击弹窗确定按钮,而弹窗还没有出现。所以在点击之前将一个1秒的强制等待即可解决问题。
在这里插入图片描述
编写测试代码:

  • 通过@TestMethodOrder(MethodOrderer.OrderAnnotation.class)保证测试用例的执行顺序
  • 对应的多个异常注册测试用例
  • 一个成功注册测试用例,通过检测是否跳转登录页面来判断是否注册成功
// 使用方法排序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();driver.get("http://120.25.124.200:7070/register.html");driver.manage().window().maximize();}/*** 检查注册页面是否正确打开* 检测点:注册账号按钮是否显示*/@Test@Order(1)void regCheckLoad() {driver.findElement(By.xpath("//*[@id=\"reg_submit\"]"));}/*** 异常注册* @param username* @param password* @param confirmPass*/@ParameterizedTest@Order(2)@CsvSource({"null,admin,admin","admin,null,admin","admin,admin,null","admin,admin,add","hhy,hhy,hhy"})void regFail(String username,String password,String confirmPass) throws InterruptedException {WebElement usernameElement = driver.findElement(By.cssSelector("#reg_username"));WebElement passwordElement = driver.findElement(By.xpath("//*[@id=\"reg_password\"]"));WebElement confirmPassElement = driver.findElement(By.cssSelector("#confirm_pass"));if (!username.equals("null")) {usernameElement.sendKeys(username);}if (!password.equals("null")) {passwordElement.sendKeys(password);}if (!confirmPass.equals("null")) {confirmPassElement.sendKeys(confirmPass);}driver.findElement(By.xpath("//*[@id=\"reg_submit\"]")).click();Thread.sleep(2000);// 点击警告弹窗的确认按钮Alert alert = driver.switchTo().alert();alert.accept();usernameElement.clear();passwordElement.clear();confirmPassElement.clear();}/*** 正常注册* @param username* @param password* @param confirmPass*/@Order(3)@ParameterizedTest@CsvSource({"admin,admin,admin"})void regSuccess(String username,String password,String confirmPass) throws InterruptedException {driver.findElement(By.cssSelector("#reg_username")).sendKeys(username);driver.findElement(By.cssSelector("#reg_password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"confirm_pass\"]")).sendKeys(confirmPass);driver.findElement(By.cssSelector("#reg_submit")).click();// 检测登录页面的元素来判断是否注册成功跳转// 检测登录按钮+注册连接driver.findElement(By.xpath("//*[@id=\"submit\"]"));driver.findElement(By.xpath("/html/body/div[2]/div[5]/a[1]"));Thread.sleep(1500);}@AfterAllstatic void quit() {driver.quit();}}

自动化测试演示
在这里插入图片描述

执行完毕后7个用列全部完成
在这里插入图片描述

3.登录页面UI自动化测试用例编写

在这里插入图片描述

根据测试用例编写对应代码:

  • 通过截图查看是否进入博客列表页面
  • 使用套件执行自动化测试代码
@Suite
@SelectClasses(LogInAutoTest.class)
public class RunSuite {
}
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LogInAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();driver.get("http://120.25.124.200:7070/login.html");driver.manage().window().maximize();}/*** 检测登录页面是否正确打开* 检测点:注册链接、登录按钮*/@Test@Order(1)void loginCheckLoad() {driver.findElement(By.xpath("/html/body/div[2]/div[5]/a[1]"));driver.findElement(By.xpath("//*[@id=\"submit\"]"));}/*** 正常登录* @param username* @param password*/@ParameterizedTest@CsvSource({"admin,admin","hhy,hhy"})@Order(3)void loginSuccess(String username,String password) throws IOException, InterruptedException {driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();// 强制等待避免误截图Thread.sleep(1000);//将登录成功后的用户博客列表页面进行截图AutoTestUtil.saveFileImg(getClass().getName());driver.findElement(By.xpath("/html/body/div[1]/span[4]/a[3]")).click();Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();Thread.sleep(1000);alert.accept();}/*** 异常登录* @param username* @param password*/@ParameterizedTest@CsvSource({"null,null","null,admin","admin,null","admin,123","hello,000"})@Order(2)void loginFail(String username,String password) throws InterruptedException {WebElement usernameElement = driver.findElement(By.xpath("//*[@id=\"username\"]"));WebElement passwordElement = driver.findElement(By.cssSelector("#password"));if (!"null".equals(username)) {usernameElement.sendKeys(username);}if (!"null".equals(password)) {passwordElement.sendKeys(password);}driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();// 强制等待防止弹窗未出现Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();usernameElement.clear();passwordElement.clear();}@AfterAllstatic void quit() {driver.quit();}
}

自动化执行演示:
在这里插入图片描述
登录自动化执行完毕后,8个用例全部执行成功,保存了用户博客列表页面的截图。
在这里插入图片描述

4.用户博客列表页面自动化测试

在这里插入图片描述

  • 未登录的情况下通过检测url是否是登录页面来判断是否跳转
  • 正常登录场景下通过直接访问博客列表后,判断是否存在写博客链接和文章标题判断是否正确打开
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserBlogListAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();driver.manage().window().maximize();}/*** 未登录访问*/@Test@Order(1)void userBlogListFail()  {driver.get("http://120.25.124.200:7070/user_blog_list.html");// 获取当前页面url,判断未登录情况下是否跳转String url = driver.getCurrentUrl();Assertions.assertEquals("http://120.25.124.200:7070/login.html",url);}/*** 进行正确登录* @param username* @param password*/@ParameterizedTest@CsvSource({"admin,admin"})@Order(2)void loginSuccess(String username,String password) {driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();}/*** 登录后访问* 检测点:写博客链接,用户文章标题*/@Test@Order(3)void userBlogListSuccess() {driver.get("http://120.25.124.200:7070/user_blog_list.html");driver.findElement(By.xpath("/html/body/div[1]/span[4]/a[2]"));driver.findElement(By.cssSelector("body > div.content > div.mid > div.show > div > h4"));}@AfterAllstatic void quit() throws InterruptedException {// 注销driver.findElement(By.xpath("/html/body/div[1]/span[4]/a[3]")).click();Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();Thread.sleep(1000);alert.accept();driver.quit();}
}

自动化演示:
在这里插入图片描述

5. 修改个信息页面

在这里插入图片描述

在进行修改信息页面测试时,发现无法找到昵称输入框,已经做了隐式等待。排查发现修改信息是在新窗口打开的,所以要通过代码切换窗口来处理。
在这里插入图片描述
通过句柄跳转到用户个人信息页面

// 获取博客列表页面句柄String windows = driver.getWindowHandle();// 点击修改资料链接driver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[3]/a")).click();// 获取所有页面句柄Set<String> windowHandles = driver.getWindowHandles();for (String s : windowHandles) {if (!s.equals(windows)) {// 切换到用户信息页面driver.switchTo().window(s);}}

自动化测试代码:

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UpdateUserInfoAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();}/*** 未登录状态下访问用户信息修改页面*/@Test@Order(1)void updateUserInfoFail() {driver.get("http://120.25.124.200:7070/updateInfo.html");driver.manage().window().maximize();}/*** 进行正确登录* @param username* @param password*/@ParameterizedTest@CsvSource({"admin,admin"})@Order(2)void loginSuccess(String username,String password) {driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();}/*** 登录成功场景,修改个人昵称*/@Order(3)@Testvoid updateUserInfoSuccess() throws InterruptedException {// 获取博客列表页面句柄String windows = driver.getWindowHandle();// 点击修改资料链接driver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[3]/a")).click();// 获取所有页面句柄Set<String> windowHandles = driver.getWindowHandles();for (String s : windowHandles) {if (!s.equals(windows)) {// 切换到用户信息页面driver.switchTo().window(s);}}Thread.sleep(1000);// 修改基本信息driver.findElement(By.cssSelector("#netName")).clear();driver.findElement(By.cssSelector("#netName")).sendKeys("网友");// 提交修改driver.findElement(By.xpath("//*[@id=\"submitInfo\"]")).click();// 点击弹窗确认按钮Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();}/*** 登录状态上传头像错误格式,大小错误*/@Order(4)@ParameterizedTest@CsvSource({"C:\\Users\\HeHanYu\\Desktop\\code\\test.txt","C:\\Users\\HeHanYu\\Desktop\\壁纸\\wallhaven-d6eylg.jpg"})void updateUserPhotoFail(String filePath) throws InterruptedException {// 获取文件上传按钮WebElement element = driver.findElement(By.cssSelector("#uploadImg"));// 指定路径选择文件element.sendKeys(filePath);// 点击上传头像driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();Thread.sleep(800);// 回退driver.navigate().back();}/*** 头像上传成功* @throws InterruptedException*/@Order(5)@Testvoid updateUserPhotoSuccess() throws InterruptedException {// 获取文件上传按钮WebElement element = driver.findElement(By.xpath("//*[@id=\"uploadImg\"]"));// 指定路径选择文件element.sendKeys("C:\\Users\\HeHanYu\\Desktop\\code\\Python.jpg");Thread.sleep(1500);// 点击上传头像driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();// 回退driver.navigate().back();}@AfterAllstatic void quit() throws InterruptedException {// 注销driver.findElement(By.xpath("/html/body/div[1]/span[4]/a[3]")).click();Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();Thread.sleep(1000);alert.accept();driver.quit();}}

自动测试执行完成后,测试用例全部通过

在这里插入图片描述

自动化测试演示:
在这里插入图片描述

6. 文章编辑页面

在这里插入图片描述

根据用例编写代码

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ArticleEditorAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();}/*** 未登录访问*/@Order(1)@Testvoid notLogin() {driver.get("http://120.25.124.200:7070/blog_editor.html");}/*** 进行正确登录* @param username* @param password*/@ParameterizedTest@CsvSource({"admin,admin"})@Order(2)void loginSuccess(String username,String password) {driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();}/*** 正确登录场景下打开* 检测点文章标题输入框是否存在*/@Order(3)@Testvoid openArticleEditor() {// 点击写博客链接driver.findElement(By.cssSelector("body > div.nav > span.links > a:nth-child(2)"));// 直接输入urldriver.get("http://120.25.124.200:7070/blog_editor.html");driver.manage().window().maximize();// 检测页面是否正确打开driver.findElement(By.cssSelector("#title"));}/*** 错误发布示例* @param title* @throws InterruptedException*/@ParameterizedTest@CsvSource({"null"})@Order(4)void postFail(String title) throws InterruptedException {if (!"null".equals(title)) {driver.findElement(By.cssSelector("#title")).sendKeys(title);}driver.findElement(By.xpath("/html/body/div[2]/div[1]/button[1]")).click();Thread.sleep(800);Alert alert = driver.switchTo().alert();alert.accept();}@ParameterizedTest@CsvSource({"博客标题"})@Order(5)void postSuccess(String title) throws InterruptedException {driver.findElement(By.cssSelector("#title")).sendKeys(title);driver.findElement(By.xpath("/html/body/div[2]/div[1]/button[1]")).click();Thread.sleep(800);Alert alert = driver.switchTo().alert();alert.accept();}@AfterAllstatic void quit() {driver.quit();}}

自动化演示:
在这里插入图片描述

博客发布页面自动化测试用例全部通过
在这里插入图片描述

7. 设置密保问题

在这里插入图片描述

  • 通过执行对应的错误测试用例
  • 执行正确的测试用例设置密保问题后,去找回密码页面获取密保问题

代码编写:

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class SetQuestionPasswordAutoTest {private static ChromeDriver driver;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();}/*** 未登录状态下访问*/@Order(1)@Testvoid notLogin() {driver.get("http://120.25.124.200:7070/set_questionPass.html");driver.manage().window().maximize();}/*** 进行正确登录进入到修改密码页面* @param username* @param password*/@ParameterizedTest@CsvSource({"admin,admin"})@Order(2)void loginSuccess(String username,String password) throws InterruptedException {driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.xpath("//*[@id=\"submit\"]")).click();Thread.sleep(500);driver.get("http://120.25.124.200:7070/set_questionPass.html");}/**** 错误设置* @param password* @param answerOne* @param answerTwo* @param answerThree* @throws InterruptedException*/@ParameterizedTest@CsvSource({"null,one,two,three","test,one,two,null","test,one,null,three","test,null,two,three","test,one,two,three"})@Order(3)void setQuestionPassFail(String password,String answerOne,String answerTwo,String answerThree) throws InterruptedException {WebElement passElement = driver.findElement(By.xpath("//*[@id=\"password\"]"));WebElement oneElement = driver.findElement(By.cssSelector("#oneValue"));WebElement twoElement = driver.findElement(By.xpath("//*[@id=\"twoValue\"]"));WebElement threeElement = driver.findElement(By.xpath("//*[@id=\"threeValue\"]"));if (!"null".equals(password)) {passElement.sendKeys(password);}if (!"null".equals(answerOne)) {oneElement.sendKeys(answerOne);}if (!"null".equals(answerTwo)) {twoElement.sendKeys(answerTwo);}if (!"null".equals(answerThree)) {threeElement.sendKeys(answerThree);}// 获取Select问题标签Select selectOne = new Select(driver.findElement(By.xpath("//*[@id=\"one\"]")));Select selectTwo = new Select(driver.findElement(By.xpath("//*[@id=\"two\"]")));Select selectThree = new Select(driver.findElement(By.xpath("//*[@id=\"three\"]")));// 选取问题selectOne.selectByIndex(1);selectTwo.selectByIndex(1);selectThree.selectByIndex(1);//提交driver.findElement(By.xpath("//*[@id=\"reg_submit\"]")).click();// 点击弹窗确认按钮Thread.sleep(500);driver.switchTo().alert().accept();// 清空输入框passElement.clear();oneElement.clear();twoElement.clear();threeElement.clear();}/**** 正确设置* @param password* @param answerOne* @param answerTwo* @param answerThree* @throws InterruptedException*/@ParameterizedTest@CsvSource({"admin,one,two,three"})@Order(3)void setQuestionPassSuccess(String password,String answerOne,String answerTwo,String answerThree) throws InterruptedException {WebElement passElement = driver.findElement(By.xpath("//*[@id=\"password\"]"));WebElement oneElement = driver.findElement(By.cssSelector("#oneValue"));WebElement twoElement = driver.findElement(By.xpath("//*[@id=\"twoValue\"]"));WebElement threeElement = driver.findElement(By.xpath("//*[@id=\"threeValue\"]"));// 填写密码和问题passElement.sendKeys(password);oneElement.sendKeys(answerOne);twoElement.sendKeys(answerTwo);threeElement.sendKeys(answerThree);// 获取Select问题标签Select selectOne = new Select(driver.findElement(By.xpath("//*[@id=\"one\"]")));Select selectTwo = new Select(driver.findElement(By.xpath("//*[@id=\"two\"]")));Select selectThree = new Select(driver.findElement(By.xpath("//*[@id=\"three\"]")));// 选取问题selectOne.selectByIndex(1);selectTwo.selectByIndex(1);selectThree.selectByIndex(1);//提交driver.findElement(By.xpath("//*[@id=\"reg_submit\"]")).click();}/*** 检测问题是否设置成功*/@Test@Order(4)void checkSetQuestion() throws InterruptedException {driver.get("http://120.25.124.200:7070/find_pass.html");Thread.sleep(1000);driver.switchTo().alert().accept();System.out.println(driver.getCurrentUrl());driver.findElement(By.xpath("//*[@id=\"username\"]")).sendKeys("admin");driver.findElement(By.cssSelector("#reg > div:nth-child(1) > button")).click();String answer = driver.findElement(By.xpath("//*[@id=\"one\"]")).getText();System.out.println(answer);// 如果获取到了问题说明设置密保问题就成功了Assertions.assertNotEquals("问题1",answer);}@AfterAllstatic void quit() {driver.quit();}
}

自动化演示:
在这里插入图片描述

发现bug

在这里插入图片描述
设置获取的密保问题的断言执行了。
在执行多次设置密保问后都设置成功了,但是在验证通过密保问题找回密码时,发生了错误。

在这里插入图片描述
通过查看数据库的问题表发现了问题:
同一个用户有多个问题存在数据表中,原因是设置密保问题时没有对已经设置过密保的用户进行校验。导致多次插入数据,引发查询到多条数据。
在这里插入图片描述

8. 所有用户文章列表页

在这里插入图片描述
在测试过程中发现为找到过期元素异常
在这里插入图片描述
发现是每次点击上一页或者下一页,页面都会刷新,所以导致元素失效,原理的代码如下

@Testvoid test() throws InterruptedException {WebElement first = driver.findElement(By.cssSelector("body > div:nth-child(3) > div > button.first"));WebElement last = driver.findElement(By.xpath("/html/body/div[3]/div/button[4]"));WebElement front = driver.findElement(By.xpath("/html/body/div[3]/div/button[2]"));WebElement next = driver.findElement(By.xpath("/html/body/div[3]/div/button[3]"));first.click();Thread.sleep(1000);driver.switchTo().alert().accept();front.click();Thread.sleep(1000);driver.switchTo().alert().accept();next.click();Thread.sleep(1000);front.click();Thread.sleep(1000);last.click();Thread.sleep(1000);next.click();Thread.sleep(1000);driver.switchTo().alert().accept();last.click();Thread.sleep(1000);driver.switchTo().alert().accept();}

改进代码,每次切换页面后重新获取元素

public class BlogListAutoTest {private static ChromeDriver driver;static WebElement first;static WebElement last;static WebElement front;static WebElement next;@BeforeAllstatic void init() {driver = AutoTestUtil.getDriver();driver.get("http://120.25.124.200:7070/blog_list.html");driver.manage().window().maximize();}void get() {first = driver.findElement(By.xpath("/html/body/div[3]/div/button[1]"));last = driver.findElement(By.xpath("/html/body/div[3]/div/button[4]"));front = driver.findElement(By.xpath("/html/body/div[3]/div/button[2]"));next = driver.findElement(By.xpath("/html/body/div[3]/div/button[3]"));}@Testvoid test() throws InterruptedException {get();first.click();Thread.sleep(1000);driver.switchTo().alert().accept();front.click();Thread.sleep(1000);driver.switchTo().alert().accept();next.click();get();Thread.sleep(1000);front.click();get();Thread.sleep(1000);last.click();get();Thread.sleep(1000);next.click();Thread.sleep(1000);driver.switchTo().alert().accept();get();last.click();Thread.sleep(1000);driver.switchTo().alert().accept();}@AfterAllstatic void quit() {driver.quit();}
}

自动化演示:

在这里插入图片描述

9. 总结

通过Junit5单元测试工具配合selenium4自动化工具有如下亮点(好处)

  1. 使用注解:避免生成过多对象,造成资源和时间的浪费
  2. 通过static修饰静态变量,全局只创建一次驱动对象,避免重复创建驱动对象造成时间的浪费
  3. 使用参数化:保持用例简洁,提高了代码的可读性
  4. 使用测试套件:一次性执行所有我们想要运行的自动化用例
  5. 使用等待(隐式等待+强制等待):提高自动化指定的稳定性(降低自动化出现误报的概率)
  6. 使用屏幕截图:方便问题的追溯和问题的解决

三、性能测试

使用LoadRunner对项目做一个简单的性能测试,性能测试在本机上进行测试,测试云服务器太麻烦。

登录和所有文章列表页面是高频使用场景,通过LoadRunner模拟多个用户进行并发进行登录后访问所有文章列表页面。

1.编写性能测试脚本

Action()
{//开启进入登录页事务lr_start_transaction("login_index");/* 注册获取返回参数,该方法可以配合打印返回数据,检测数据内容 */web_reg_save_param("ParaResult","LB=","RB=",LAST);// 定时检查点,检测登录页面是否正确打开web_reg_find("Text=登录",LAST);// 定义虚拟用户结合点lr_rendezvous("start");// 进入登录页面web_url("login_html","URL=http://127.0.0.1:7070/login.html","TargetFrame=","Resource=0","Referer=",LAST);// 结束进入登录页事务lr_end_transaction("login_index", LR_AUTO);//开启登录事务lr_start_transaction("login");// 进行登录web_submit_data("login","Action=http://127.0.0.1:7070/user/login","Method=POST","EncType=application/x-www-form-urlencoded; charset=UTF-8","TargetFrame=","Referer=","Mode=HTTP",ITEMDATA,"Name=username", "Value=<username>", ENDITEM,"Name=password", "Value=<password>", ENDITEM,LAST);//定时检测所有文章列表页检查点web_reg_find("Text=查看全文",LAST);// 结束登录事务lr_end_transaction("login", LR_AUTO);//文章列表事务lr_start_transaction("blog_list");// 登录后访问所有文章列表页面web_url("blog_list","URL=http://127.0.0.1:7070/blog_list.html","TargetFrame=","Resource=0","Referer=",LAST);// 结束文章列表页事务lr_end_transaction("blog_list", LR_AUTO);return 0;
}

点击测试
在这里插入图片描述

测试脚本没有问题后修改Action脚本的执行次数,执行5次脚本
在这里插入图片描述

设置参数化

为了保证测试的合理性,多个虚拟用户使用多个不同的账号进行登录,使用LoadRunner的参数化即可实现。
在这里插入图片描述

2.创建测试场景

针对编写好的脚本通过Controller创建测试场景

1.设置15个虚拟用户
在这里插入图片描述

2.设置创建好测试场景后每5秒初始化3个虚拟用户
在这里插入图片描述

3.设置每5秒进入3个虚拟用户到测试场景
在这里插入图片描述
4.设置虚拟用户执行循环执行5分钟
在这里插入图片描述
5.设置虚拟用户执行完毕后每10秒退出5个虚拟用户
在这里插入图片描述
6.添加监视系统资源
CPU运行时间和剩余内存
在这里插入图片描述

3.开始执行

在这里插入图片描述

简单分析性能测试报告

在这里插入图片描述

在事务报告中,一般只关注平均值和标准方差,标准偏差值越大,说明越不稳定。而且脚本里值是写3个事务,而这里却有6个,因为每个文件就是一个事务脚本文件中的(init、action、end)
在这里插入图片描述

运行的虚拟用户图表

通过虚拟用户运行图标发现,在脚本运行40秒到5分30秒之间虚拟用户给了服务器负载

在这里插入图片描述

点击率表

通过点击率表可以看到和虚拟用户运行表运行对应起来,虚拟用户的增多点击率也随之增多,点击率越多说明和服务器的交互次数也越多。
在这里插入图片描述

吞吐量表

吞吐量图形和点击数图形有点相似,但是吞吐量的曲线会稍后延后一点递增。因为吞吐量表示的是响应返回的资源数量,所有是要先有请求才会有响应。

在这里插入图片描述

平均事务响应时间图

通过事务响应时间发现,访问登录页面的时间比较长,登录事务时间响应时间是比较短的,(深蓝是访问登录页面、黄色是登录事务、粉红色是进入文章列表页面),在40秒的时候事务的响应时间达到最大,那个时候正是15个虚拟用户生成完成,进行访问服务,导致一大波请求到达服务,导致事务响应时间长。
虚拟用户在性能测试过程中,每秒在服务器上命中的次数,通过次图可以帮助根据命中次数评估虚拟用户生成的负载量
在这里插入图片描述

系统资源图表

  • precessorTime:CPU使用时间,被消耗的处理器时间数量
  • Available MBytes:可用的物理内存,一般根据这个指标推算消耗的物理内存有多大。(已经消耗的物理内存=实际内存 - 可用物理内存)
    CPU的占用时间从30多秒开始,基本在长时间使用CPU,对CPU的使用时间还是长的。因为本地使用的是自己的电脑,而且并发设置了15,对于电脑压力还是比较大的。
    对应的这次测试对于内存的占用还不是特别高的。
    在这里插入图片描述

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

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

相关文章

Stable Diffusion +EbSynth应用实践和经验分享

Ebsynth应用 1.安装ffmpeg 2.安装pip install transparent-background,下载模型https://www.mediafire.com/file/gjvux7ys4to9b4v/latest.pth/file 放到C:\Users\自己的用户名.transparent-background\加一个ckpt_base.pth文件 3.秋叶安装ebsynth插件,重启webui 填写项目基本…

Rest 优雅的url请求处理风格及注意事项

&#x1f600;前言 本篇博文是关于Rest 风格请求的应用和注意事项&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大家&#xff0c;您…

应急响应-Webshell

文章目录 一、Webshell概述什么是WebshellWebshell分类基于编程语言基于文件大小/提供的功能多少 Webshell 检测方法 二、常规处置方法三、技术指南1、初步预判2、 Webshell排查3、Web日志分析&#xff08;查找攻击路径及失陷原因&#xff09;4、系统排查4.1 Windows4.2 Linux …

CSS中的position属性有哪些值,并分别描述它们的作用。

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ static⭐ relative⭐ absolute⭐ fixed⭐ sticky⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那…

通达OA SQL注入漏洞【CVE-2023-4166】

通达OA SQL注入漏洞【CVE-2023-4166】 一、产品简介二、漏洞概述三、影响范围四、复现环境POC小龙POC检测工具: 五、修复建议 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损…

新的 Python URL 解析漏洞可能导致命令执行攻击

Python URL 解析函数中的一个高严重性安全漏洞已被披露&#xff0c;该漏洞可绕过 blocklist 实现的域或协议过滤方法&#xff0c;导致任意文件读取和命令执行。 CERT 协调中心&#xff08;CERT/CC&#xff09;在周五的一份公告中说&#xff1a;当整个 URL 都以空白字符开头时&…

gitlab修改远程仓库地址

目录 背景&#xff1a; 解决&#xff1a; 1.删除本地仓库关联的远程地址&#xff0c;添加新的远程仓库地址 2.直接修改本地仓库关联的远程仓库地址 3.打开.git隐藏文件修改远程仓库地址 4.拉取代码报错(git host key verification failed) 背景&#xff1a; 公司搬家&#…

image has dependent child images

问题&#xff1a;很多none的镜像无法被删除 解决过程&#xff1a; 1、通过 docker image prune -f 提示可删除为 0 2、直接进行删除报错&#xff1a; docker rmi 8f5116cbc201Error response from daemon: conflict: unable to delete 8f5116cbc201 (cannot be forced) - im…

银河麒麟安装php7.1.33

银河麒麟V10兼容CentOS 8 安装过程与CentOS类似。 TencentOS3.1安装PHPNginxredis测试系统_乐大师的博客-CSDN博客 可以参考之前我写的文章。 不过有2个细节不同&#xff0c;下面说下。 问题1&#xff1a;编译错误提示“error:off_t undefined” 解决方法&#xff1a; 编…

宋浩线性代数笔记(五)矩阵的对角化

本章的知识点难度和重要程度都是线代中当之无愧的T0级&#xff0c;对于各种杂碎的知识点&#xff0c;多做题复盘才能良好的掌握&#xff0c;良好掌握的关键点在于&#xff1a;所谓的性质A与性质B&#xff0c;是谁推导得谁~

Ubuntu22.04复现SHADEWACHER(手动安你就慢了)

因为我是打算跑TC数据集&#xff0c;所以跳过audit安装。 我的Ubuntu使用的是清华源。 1. Parser Setup 1.1 g apt install g1.2 neo4j Ubuntu22.04换什么源都会导致无法定位软件包&#xff0c;添加neo4j的官方源又会导致不信任的源。 22.04以下的版本&#xff0c;直接用命…

MySQL 根据多字段查询重复数据

MySQL 根据多字段查询重复数据 在实际的数据库应用中&#xff0c;我们经常需要根据多个字段来查询重复的数据。MySQL 提供了一些方法来实现这个功能&#xff0c;让我们能够快速准确地找到和处理重复数据。本文将介绍如何使用 MySQL 来根据多字段查询重复数据&#xff0c;并提供…

SIFT 算法 | 如何在 Python 中使用 SIFT 进行图像匹配

介绍 人类通过记忆和理解来识别物体、人和图像。你看到某件事的次数越多,你就越容易记住它。此外,每当一个图像在你的脑海中弹出时,它就会将该项目或图像与一堆相关的图像或事物联系起来。如果我告诉你我们可以使用一种称为 SIFT 算法的技术来教机器做同样的事情呢? 尽管…

C语言——动态内存函数(malloc、calloc、realloc、free)

了解动态内存函数 前言&#xff1a;一、malloc函数二、calloc函数三、realloc函数四、free函数 前言&#xff1a; 在C语言中&#xff0c;动态内存函数是块重要的知识点。以往&#xff0c;我们开辟空间都是固定得&#xff0c;数组编译结束后就不能继续给它开辟空间了&#xff0…

贴吧照片和酷狗音乐简单爬取

爬取的基本步骤 很简单&#xff0c;主要是两大步 向url发起请求 这里注意找准对应资源的url&#xff0c;如果对应资源不让程序代码访问&#xff0c;这里可以伪装成浏览器发起请求。 解析上一步返回的源代码&#xff0c;从中提取想要的资源 这里解析看具体情况&#xff0c;一…

浅谈现代医院手术室IT供配电系统的设计与研究

安科瑞 华楠 &#xff3b;摘要&#xff3d; 随着人们的生活水平的不断提高&#xff0c;医疗条件的不断改善&#xff0c;人们对健康越来越重视同时对医疗条件的要求也越来越高&#xff0c;对医院手术室医疗设施提出了新的要求。以往医院普通手术室状况已不能满足人们的要求&…

腾讯云CVM服务器端口在安全组中打开!

腾讯云服务器CVM端口怎么开通&#xff1f;腾讯云服务器端口是通过配置安全组规则来开通的&#xff0c;腾讯云服务器网以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0…

基于Yolov5与LabelMe训练自己数据的图像分割完整流程

基于Yolov5与LabelMe训练自己数据的实例分割完整流程 1. Yolov5配置2. 创建labelme虚拟环境4. 接下来开始使用labelme绘制分割数据集4.1 json to txt4.2 划分数据集(可分可不分) 5. 训练 1. Yolov5配置 参照这边文章&#xff1a; https://blog.csdn.net/ruotianxia/article/de…

okcc对接ASR平台,okcc客户投诉的安全问题

客户投诉: 客户为什么要投诉&#xff1f;实际上分为两种情况&#xff0c;一是客户被冒犯到不能容忍导致的投诉&#xff0c;二是恶意投诉。降低客户被冒犯投诉的概率&#xff0c;无非就是选择客户、规范用语、降低频度&#xff1b;减少恶意投诉&#xff0c;回避是实践证明最有效…

《C语言深度解剖》.pdf

&#x1f407; &#x1f525;博客主页&#xff1a; 云曦 &#x1f4cb;系列专栏&#xff1a;深入理解C语言 &#x1f4a8;吾生也有涯&#xff0c;而知也无涯 &#x1f49b; 感谢大家&#x1f44d;点赞 &#x1f60b;关注&#x1f4dd;评论 C语言深度解剖.pdf 提取码:yunx