个人博客系统测试报告
个人博客系统测试报告
- 一.项目背景
- 二.项目功能
- 三.测试用例
- 3.1 功能测试
- 3.2 自动化测试(部分测试)
- 3.2.1登陆页面
- 3.2.2博客详情页
- 3.2.3博客编辑页
- 3.2.4个人列表页
- 3.2.5测试结果
- 3.3 性能测试
一.项目背景
当学习完一项技能后,我们总会习惯通过博客来总结所学的知识点,方便后期遗忘时随时查看和快速复习。本次开发的类似于CSDN的个人博客系统便是为了更加轻量和方便地记录自己的学习笔记,方便自己后期学习记录。
二.项目功能
该个人博客系统主要实现了以下功能:注册和登录、注销、编写博客、修改博客、删除博客、查看博客详情,修改个人信息等功能。
- 注册登录功能:用户输入想创建的账号和密码,点击注册按钮无误后跳转到登陆页面,在登录页面输入正确的账号密码,登录成功后就会跳转到博客列表页。在右上角存在网站主页,注册两个按钮。
- 博客列表页面:可以在列表页查看用户所有的博客文章简介(支持分页功能),其包括博客标题、发布时间以及内容概要。在左侧可以看到登录的用户以及文章数、分类数等的模块。在右上角有主页、写博客和注销三个功能。
- 博客详情页面:在博客列表页面下方点击“查看全文”按钮就会跳转到当前博客详情页,此时就可以看到该篇博客的完整内容。在右上角有主页和写博客两个功能
- 个人信息页面:该页面显示用户全部的个人信息,包括头像,性别,账号,昵称,个人简介等,用户也可以修改除账号以外的全部信息。
- 博客编辑页面:在登录之后的任意界面点击“写博客”之后就会进入博客编辑页面,此时就可以进行博客的编写(支持markdown格式),点击“发布文章”后就可以成功发布文章,此时就会跳转到我的博客页面。
三.测试用例
3.1 功能测试
3.2 自动化测试(部分测试)
实现工具类,增加代码复用
为了避免在使用时频繁创建驱动类,我们可以定义一个功能类使用单例创建驱动对象。
// An highlighted block
package com.example.blogautotest.common;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
public class AutotestUtils {
public static EdgeDriver driver;
//创建驱动对象
public static EdgeDriver createDriver(){
//单例模式
if(driver==null){
driver=new EdgeDriver();
//创建隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
return driver;
}
//获取当前时间将截图按照时间保存
public List<String> getTime(){
//文件夹以天保存
//截图以毫秒时间戳保存
SimpleDateFormat sim1=new SimpleDateFormat("yyyyMMdd-HHmmssSS");
SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd");
String filename=sim1.format(System.currentTimeMillis());
String dirname=sim2.format(System.currentTimeMillis());
List<String> list = new ArrayList<>();
list.add(dirname);
list.add(filename);
return list;
}
//获取屏幕截图,把所有的用例执行的结果保存下来
public void getScreenShot(String str) throws IOException {
List<String> list=getTime();
// ./指的是当前的项目路径下,也就是BlogAutoTest下
String filename="./src/test/java/com/blogautotest/"+list.get(0)+"/"+str+"_"+list.get(1)+".png";
File srcfile=driver.getScreenshotAs(OutputType.FILE);
//把屏幕截图生成的文件放到指定的路径
FileUtils.copyFile(srcfile,new File(filename));
}
}
3.2.1登陆页面
创建一个类(自定义名为BlogLoginTest )继承 AutoTestUtils 类,获取驱动,之后选取典型 case 使用参数化注解对异常、正常登录分别进行测试,进行相应弹窗处理,最后进行屏幕截图.
package com.example.blogautotest.Tests;
import com.example.blogautotest.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.edge.EdgeDriver;
import java.io.IOException;
//设置优先级
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogLoginTest extends AutotestUtils {
public static final String UNIVERSAL_KAPTCHA_CODE="c8fd27d19b2aa9fa24affd2a4726778c";
public static EdgeDriver driver=createDriver();
@BeforeAll
public static void baseControl(){
driver.get("http://127.0.0.1:8080/login.html");
}
/*
检查登录页面打开是否正确
检查点:登录标题 用户名是否存在
*/
@Test
@Order(1)
public void loginPageLoadRight() throws IOException {
//检验页面是否加载正确(两个检查点)
driver.findElement(By.cssSelector("body > div.login-container > div > h3"));
driver.findElement(By.cssSelector("body > div.login-container > div > div:nth-child(2) > span"));
getScreenShot(getClass().getName());
}
@ParameterizedTest
@CsvSource({
"zhangsan,123","admin,admin"})
@Order(2)
public void loginSuc(String name , String password) throws InterruptedException, IOException{
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#rightCode")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys(name);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#rightCode")).sendKeys(UNIVERSAL_KAPTCHA_CODE);
driver.findElement(By.cssSelector("#submit")).click();
//处理弹窗
Thread.sleep(300);
driver.switchTo().alert().accept();
//对登录结果进行检测,存在草稿页元素代表登录成功
driver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)"));
//getScreenShot(getClass().getName());
driver.navigate().back();
}
@ParameterizedTest
@CsvSource({
"admin,123","zhangsan,666"})
@Order(3)
public void loginFail(String name,String password) throws IOException, InterruptedException {
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#rightCode")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys(name);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#rightCode")).sendKeys(UNIVERSAL_KAPTCHA_CODE);
driver.findElement(By.cssSelector("#submit")).click();
//处理弹窗
Thread.sleep(300);
//获取弹窗内容
String text=driver.switchTo().alert().getText();
String except="登陆成功!";
driver.switchTo().alert().accept();
Assertions.assertNotEquals(except,text);
//获取当前页面截屏
//getScreenShot(getClass().getName());
}
}
3.2.2博客详情页
package com.example.blogautotest.Tests;
import com.example.blogautotest.common.AutotestUtils;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import java.io.IOException;
public class BlogDetailTest extends AutotestUtils {
public static EdgeDriver driver=createDriver();
@BeforeAll
public static void baseControl(){
driver.get("http://127.0.0.1:8080/blog_content.html?id=12869974016131072");
}
@Test
public void blogDeailLoadRight() throws IOException{
driver.findElement(By.cssSelector("#data"));
driver.findElement(By.cssSelector("#title"));
}
}
3.2.3博客编辑页
package com.example.blogautotest.Tests;
import com.example.blogautotest.common.AutotestUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.edge.EdgeDriver;
import java.io.IOException;
public class BlogEditTest extends AutotestUtils {
public static EdgeDriver driver=createDriver();
@BeforeAll
public static void baseControl(){
driver.get("http://127.0.0.1:8080/blog_edit.html");
}
@Test
public void editAndSubimitBlog() throws IOException, InterruptedException {
driver.findElement(By.cssSelector("#title")).sendKeys("自动化测试");
//博客系统使用到的编辑是第三方软件,所以不能直接使用sendKeys向编辑模块发送文本
driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(30)")).click();
driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button:nth-child(2)")).click();
Thread.sleep(300);
String actual=driver.switchTo().alert().getText();
driver.switchTo().alert().accept();
String expect = "恭喜:添加成功!";
Assertions.assertEquals(expect,actual);
}
}
3.2.4个人列表页
package com.example.blogautotest.Tests;
import com.example.blogautotest.common.AutotestUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.edge.EdgeDriver;
public class MyBlogListTest extends AutotestUtils {
public static EdgeDriver driver=createDriver();
@BeforeAll
public static void baseControl(){
driver.get("http://127.0.0.1:8080/myblog_list.html");
}
@Test
public void myListPageLoadRight(){
//检查博客列表加载是否正常
driver.findElement(By.cssSelector("body > div.nav > a:nth-child(7)"));
driver.findElement(By.cssSelector("body > div.container > div.container-left > div > a"));
driver.findElement(By.cssSelector("body > div.container > div.container-right > div.blog-pagnation-wrapper > button:nth-child(1)"));
driver.findElement(By.cssSelector("body > div.container > div.container-right > div.blog-pagnation-wrapper > button:nth-child(3)"));
}
@Test
public void jumpTest(){
//测试导航栏能否正常跳转
driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();
Assertions.assertEquals("http://127.0.0.1:8080/blog_list.html",driver.getCurrentUrl());
driver.navigate().back();
driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
Assertions.assertEquals("http://127.0.0.1:8080/blog_edit.html",driver.getCurrentUrl());
driver.navigate().back();
}
}
3.2.5测试结果
3.3 性能测试
通过LoadRunner模拟多个用户进行并发进行登录后访问所有文章列表页面。
3.3.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的参数化即可实现。
针对编写好的脚本通过Controller创建测试场景
- 设置15个虚拟用户
- 设置每5秒进入3个虚拟用户到测试场景
- 设置虚拟用户执行循环执行5分钟
- 设置虚拟用户执行完毕后每10秒退出5个虚拟用户
- 添加监视系统资源
CPU运行时间和剩余内存
性能测试报告
通过虚拟用户运行图标可以发现,在脚本运行40秒到5分30秒之间虚拟用户给了服务器负载
通过点击率表可以看到和虚拟用户运行表运行对应起来,虚拟用户的增多点击率也随之增多,点击率越多说明和服务器的交互次数也越多。
通过事务响应时间发现,访问登录页面的时间比较长,登录事务时间响应时间是比较短的
还没有评论,来说两句吧...