【项目】论坛系统测试
文章目录
- 一、项目介绍
- 二、测试环境
- 三、测试用例
- 3.1 论坛系统功能测试用例
- 3.2 论坛系统非功能测试用例
- 四、测试计划
- 1. 手工测试
- 1.1 注册页面
- 1.2 登陆页面
- 1.3 主页面(列表页)
- 2. 自动化测试
- 2.1 添加对应的依赖
- 2.2 Utils类(公有类)
- 2.3 RegisterPage类 (注册页面)
- 2.4 LoginPage 类(登录页面)
- 2.5 PageByNoLogin 类 (未登录页面)
- 2.6 ListPage 类 (主页面/列表页)
- 2.7 RunTest 类(测试运行)
- 3. 性能测试
- 3.1 HTTP请求默认值
- 3.2 CSV数据文件设置
- 3.3 梯度压测
一、项目介绍
论坛系统是采用前后端分离的方式实现的,使用到的技术有:SpringBoot,SpringMVC,MyBatis,MySQL等,并将其部署到了云服务器上。系统旨在为用户提供一个基于 Web 的文章发布和讨论平台。用户可以进行注册登录、查看和修改个人信息,以及进行帖子的增删改查等基础操作。此外,系统还提供了评论、站内信等交流功能,用户可以对帖子进行点赞,并在帖子详情页上查看阅读量、点赞数、评论量等信息。
二、测试环境
- 硬件: LAPTOP-C2IIA694 (i7 10710U/16GB/512GB/MX250)
- 操作系统: Windows11(专业版)
- 浏览器: 129.0.6668.100(正式版本) (64 位)
- 测试工具: 自动化测试Selenium,性能测试Jmeter
- 自动化脚本运行环境: IntelliJ IDEA Community Edition 2022.3.3
三、测试用例
3.1 论坛系统功能测试用例
3.2 论坛系统非功能测试用例
四、测试计划
1. 手工测试
注:手工测试仅执行部分测试用例
1.1 注册页面
测试用例一:
用户名,昵称,密码以及确认密码均为必填,未填写完整,点击注册按钮
预期结果:页面提示该信息不能为空
实际结果:页面给出相应提示与预期结果一致
测试用例二:
输入用户名在数据库中已存在,点击注册按钮
预期结果:页面给出相应提示该用户已存在
实际结果:页面给出相应提示与预期结果一致
测试用例三:
输入用户名在数据库中不存在,密码和确认密码不一致,点击注册按钮
预期结果:页面给出相应提示该请检查确认密码
实际结果:页面给出相应提示与预期结果一致
测试用例四:
输入用户名在数据库中不存在,密码和确认密码一致,未勾选同意使用条款和隐私政策,点击注册按钮
预期结果:页面给出相应提示勾选框和同意字体为红色
实际结果:页面给出相应提示与预期结果一致
测试用例五:
输入的用户名数据库中不存在,昵称不为空,密码与确认密码一致并且勾选同意使用条款和隐私政策,点击注册按钮
预期结果:页面显示注册成功,并跳转回登录界面。
实际结果:页面显示注册成功并跳转至登陆界面与预期结果一致
1.2 登陆页面
测试用例一:
输入已存在的用户名,并且密码正确
预期结果:登录成功并跳转至列表页
实际结果:登录成功并跳转至列表页与预期结果一致
测试用例二:
账号为空/密码为空
预期结果:页面给出相应提示用户名不能为空/密码不能为空
实际结果:页面给出相应提示与预期结果一致
测试用例三:
账号为空密码不为空但账号密码错误
预期结果:页面给出相应提示用户名或密码错误
实际结果:页面给出相应提示与预期结果一致
1.3 主页面(列表页)
首页
测试用例一:
未登录状态下,打开列表页
预期结果:跳转回登录界面
实际结果:跳转回登录界面,与预期结果一致测试用例二:
登录状态下,打开列表页
预期结果:第一行论坛名和论坛logo,同行有搜索框,昼夜调节,消息,用户头像,下一行是导航栏显示所有版块名,各个板块均可点击,接下来左边是首页二字,左边是发布帖子按钮,下面是当前论坛的所有帖子。
实际结果:页面加载成功,与预期结果一致
测试用例三:
登录状态下,在搜索框输入关键字“Java”搜索
预期结果:下方显示帖子正文中所有存在“Java”这三个字的帖子;
实际结果:刷新回到首页界面,与预期不符。不支持搜索功能测试用例四:
登录状态下,点击页面小月亮图标
预期结果:可以实现昼夜调节
实际结果:页面与预期结果一致测试用例五:
登录状态下,点击消息模块
预期结果:导航栏点击小铃铛显示当前所有私信,未读用文字和红色小圆点标识,已读用文字和灰色小圆点表示,已回复用文字和绿色小圆点标识
实际结果:页面与预期结果一致
测试用例六:
登录状态下,点击发布帖子按钮并测试板块下拉框
预期结果:板块名默认选择Java并且下拉框正常
实际结果:页面与预期结果一致
测试用例七:
登录状态下,点击用户
预期结果:出现我的帖子,个人中心,退出等选项
实际结果:页面加载与预期结果一致
我的帖子
- 测试用例一:
登录状态下,点击用户->我的帖子
预期结果:出现个人头像,昵称,发帖数,邮箱,简介以及个人帖子等信息
实际结果:页面加载与预期结果一致
- 测试用例二:
登录状态下,点击用户->我的帖子->点击第一篇帖子
预期结果:会出现帖子标题,个人头像昵称,帖子内容,点赞编辑删除按钮及回复框
实际结果:页面加载与预期结果一致
- 测试用例三:
登录状态下,点赞
预期结果:页面右下角出现提示点赞成功
实际结果:页面与预期结果一致
- 测试用例四:
登录状态下,点击编辑帖子,清空内容直接点提交
预期结果:页面右下角出现提示请输入帖子内容
实际结果:页面与预期结果一致
…(手工测试仅测试部分测试用例)
个人中心
- 测试用例一:
登录状态下,点击用户->个人中心
预期结果:下方显示该登录用户的所有信息
实际结果:页面与预期结果一致
- 测试用例二:
登录状态下,修改头像
预期结果:打开 电脑,上传本地图片并更新头像。
实际结果:打开电脑,上传本地图片,但是没有反应。与预期不符(不支持修改头像)。- 测试用例三:
登录状态下,修改昵称
预期结果:修改成功,右下角出现提示操作成功
实际结果:页面与预期结果一致- 测试用例四:
原密码正确,新密码和确认密码不一致,修改失败,给出错误提示
预期结果:修改失败,页面右下角出现提示两次密码输入不相同
实际结果:页面与预期结果一致
…(手工测试仅测试部分测试用例)
2. 自动化测试
自动化测试码云链接:FourmAutoTest
2.1 添加对应的依赖
- 先添加对应的依赖
<dependencies><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version></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></dependencies>
2. 定义两个包common里放公共方法类,tests包里放各个页面的测试,运行类RunTest放在两个包外
2.2 Utils类(公有类)
公有类:创建driver对象,测试过程中屏幕截图的通用工具类
package common;import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
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;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统公共方法*/public class Utils {public static WebDriver driver;public static WebDriver createDriver(){if(driver == null){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();//访问urldriver.get(url);//窗口最大化driver.manage().window().maximize();}//屏幕截图public void getScreenShot(String str) throws IOException, IOException {// ./src/test/image/// /2024-07-17/// /test01-17453010.png// /test02-17453020.png// /2024-07-18/// /test01-17453030.png// /test02-17453034.png//屏幕截图SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//./src/test/image/2024-07-17/test01-17453020.pngString filename ="./src/test/image/"+ dirTime +"/" + str + "-" + fileTime+".png";File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);//srcFile放到指定位置FileUtils.copyFile(srcFile,new File(filename));}}
2.3 RegisterPage类 (注册页面)
测试注册页面的加载,注册成功和注册成功
package tests;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统注册页面* Author: WJW*/
public class RegisterPage extends Utils {public static String url = "http://127.0.0.1:9580/sign-up.html";public RegisterPage() {super(url);}public void RegisterPageRight() {//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div.text-center.mb-4 > img"));//用户注册driver.findElement(By.cssSelector("#signUpForm > div > h2"));}//注册成功public void RegisterSuc() throws InterruptedException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("橘子004");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("橘子树0");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);//校验注册是否成功并返回登录页面String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//注册失败01--该用户已存在public void RegisterFai01() throws IOException {//在登录页面点击注册按钮// driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail01.equals("警告");}//注册失败02--用户名为空public void RegisterFai02() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名 当前用户名为空driver.findElement(By.cssSelector("#username"));//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail02 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(2) > div")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail02.equals("用户名不能为空");}//注册失败03--昵称为空public void RegisterFai03() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称 当前昵称为空driver.findElement(By.cssSelector("#nickname"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail03 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(3) > div")).getText();//截图保存当前异常getScreenShot(getClass().getName());//断言assert fail03.equals("昵称不能为空");}//注册失败04--密码与确认密码不一致public void RegisterFai04() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("13");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail04 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();getScreenShot(getClass().getName());assert fail04.equals("请检查确认密码");}//注册失败05--未点击同意使用条款和隐私服务public void RegisterFai05() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//未点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy"));//点击注册driver.findElement(By.cssSelector("#submit")).click();//截图保存当前异常getScreenShot(getClass().getName());}}
2.4 LoginPage 类(登录页面)
测试登录页面的加载,登录成功和登录失败
package tests;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统登录页面*/
public class LoginPage extends Utils {public static String url = "http://127.0.0.1:9580/sign-in.html";public LoginPage() {super(url);}//通过查看页面元素是否存在来检查页面加载成功与否public void loginPageRight(){//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));//用户登录driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2"));}//检查登录功能public void LoginSuc(){//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("xiaoweng");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("0123");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//检查点击登录是否成功//通过查看比特论坛logo是否登录成功driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));//通过查看发布帖子是否登录成功driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//返回登录页面// driver.navigate().back();//刷新页面// driver.navigate().refresh();}//检查登录失败01--密码错误public void LoginFail01() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("aaa");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div>h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res01.equals("警告");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败02--用户名为空public void LoginFail02() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res02 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res02.equals("用户名不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败03--密码为空public void LoginFail03() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("swhdf");//输入密码driver.findElement(By.cssSelector("#password"));//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res03 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res03.equals("密码不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}}
2.5 PageByNoLogin 类 (未登录页面)
未登录状态下,访问类列表页,直接返回登录页面
public class PageByNoLogin extends Utils {public static String listurl = "http://127.0.0.1:9580/index.html";public PageByNoLogin() {super(listurl);}public void ListPageByNoLogin() throws InterruptedException {// driver.get(listurl);//直接返回登录界面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}
}
2.6 ListPage 类 (主页面/列表页)
列表页面是否加载成功,站内信息回复,发布帖子,显示个人帖子,帖子的点赞、编辑、删除以及回复测试,个人中心页面的加载,个人中心的修改,退出等测试。
package tests;import common.Utils;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import java.io.IOException;
import java.time.Duration;import static org.openqa.selenium.support.ui.ExpectedConditions.textToBe;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统列表页面*/
public class ListPage extends Utils{public static String url = "http://127.0.0.1:9580/index.html";public ListPage() {super(url);}//检查页面各个元素是否加载成功public void ListByLoging() throws InterruptedException {//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//通过查看比特论坛logo是否登录成功driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));//通过查看发布帖子是否登录成功driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));//昼夜模式测试driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg")).click();driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light")).click();//输入框测试driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input"));//信息栏driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg"));//个人信息模块driver.findElement(By.cssSelector("#index_nav_avatar")).click();//不同模块点击,点击java模块driver.findElement(By.cssSelector("#topBoardList > li:nth-child(2) > a > span.nav-link-title")).click();//查看java模块第一个帖子是否存在来校验是否切换模块成功driver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div"));}//处理私信成功public void MessageSuc() throws InterruptedException {driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg")).click();//等待页面加载//Thread.sleep(4000);//点击消息driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a")).click();//点击回复driver.findElement(By.cssSelector("#btn_index_message_reply")).click();//输入回复信息WebDriverWait foo = new WebDriverWait(driver, Duration.ofSeconds(3));Thread.sleep(2000);foo.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_receive_content"))).sendKeys("越努力越幸运!");//Thread.sleep(3000);// driver.findElement(By.cssSelector("#index_message_reply_receive_content")).sendKeys("越努力越幸运!");//发送driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();//检验发送成功String sendSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert sendSuc.equals("成功");//关闭信息页面driver.findElement(By.cssSelector("#index_message_offcanvasEnd > div.offcanvas-header > button")).click();}//处理私信失败public void MessageFail() throws InterruptedException, IOException {driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a > svg")).click();//等待页面加载//Thread.sleep(4000);//点击消息driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a")).click();//点击回复driver.findElement(By.cssSelector("#btn_index_message_reply")).click();//输入回复信息driver.findElement(By.cssSelector("#index_message_reply_receive_content"));//发送Thread.sleep(3000);driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();//检验发送结果//显示等待WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));boolean send = wait.until(ExpectedConditions.textToBe(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2"),"警告"));if(send){getScreenShot(getClass().getName());}else {System.out.println("发送成功");}/* String sendFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert sendFail.equals("警告");
*///显示等待关闭回复框/*WebDriverWait foo = new WebDriverWait(driver, Duration.ofSeconds(10));Thread.sleep(2000);foo.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_modal > div > div > div.modal-header > button"))).click();
*///关闭信息页面WebDriverWait closeWait = new WebDriverWait(driver, Duration.ofSeconds(10));closeWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_offcanvasEnd > div.offcanvas-header > button"))).click();}//发布帖子成功public void PublishPostSuc() throws IOException {//点击页面发布帖子按钮driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post")).click();//板块driver.findElement(By.cssSelector("#article_post_borad")).click();driver.findElement(By.cssSelector("#article_post_borad>option:nth-child(1)")).click();//标题driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试01");//内容driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(20) > a > i")).click();//发布/* WebDriverWait publishWait = new WebDriverWait(driver, Duration.ofSeconds(50));try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}publishWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#article_post_submit"))).click();*/try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}driver.findElement(By.cssSelector("#article_post_submit")).click();//校验发布成功String pubSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert pubSuc.equals("成功");}//发布帖子失败public void PublishPostFail() throws IOException {//点击页面发布帖子按钮driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post")).click();//板块driver.findElement(By.cssSelector("#article_post_borad")).click();driver.findElement(By.cssSelector("#article_post_borad>option:nth-child(1)")).click();//标题driver.findElement(By.cssSelector("#article_post_title"));//内容driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(20) > a > i")).click();//发布try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}driver.findElement(By.cssSelector("#article_post_submit")).click();/* WebDriverWait publishWait = new WebDriverWait(driver, Duration.ofSeconds(10));try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}publishWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#article_post_submit"))).click();*///校验提示发布失败String pubFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert pubFail.equals("提示");}//显示个人帖子public void ShowPost(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击我的帖子driver.findElement(By.cssSelector("#index_user_profile")).click();//查看当前用户昵称是否存在来校验页面是否加载成功driver.findElement(By.cssSelector("#profile_nickname"));//点击当前用户的第一篇帖子driver.findElement(By.cssSelector("#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a")).click();}//点赞public void LickCount(){ShowPost();driver.findElement(By.cssSelector("#details_btn_like_count")).click();String likeCountSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert likeCountSuc.equals("成功");}//编辑成功public void EditSuc(){ShowPost();//点击当前帖子页面的编辑按钮driver.findElement(By.cssSelector("#details_artile_edit")).click();//清空原标题driver.findElement(By.cssSelector("#edit_article_title")).clear();//修改标题driver.findElement(By.cssSelector("#edit_article_title")).sendKeys("修改标题01");//点击提交driver.findElement(By.cssSelector("#edit_article_submit")).click();String editSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert editSuc.equals("成功");}//编辑失败public void EditFail() throws IOException {ShowPost();//点击当前帖子页面的编辑按钮driver.findElement(By.cssSelector("#details_artile_edit")).click();//清空原标题driver.findElement(By.cssSelector("#edit_article_title")).clear();//点击提交driver.findElement(By.cssSelector("#edit_article_submit")).click();String editSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert editSuc.equals("提示");}//删除成功public void DeleteSuc(){ShowPost();//点击当前帖子页面的删除按钮driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div:nth-child(1) > div.col-9.card.card-lg > div.card-footer.bg-transparent.mt-auto.justify-content-end > div > div:nth-child(3) > div > a")).click();//点击删除driver.findElement(By.cssSelector("#details_delete_modal > div > div > div.modal-footer > div > div > div:nth-child(2)>a")).click();String deleteSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert deleteSuc.equals("成功");}//删除失败public void DeleteFail(){ShowPost();//点击当前帖子页面的删除按钮driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div:nth-child(1) > div.col-9.card.card-lg > div.card-footer.bg-transparent.mt-auto.justify-content-end > div > div:nth-child(3) > div > a")).click();//点击取消driver.findElement(By.cssSelector("#details_delete_modal > div > div > div.modal-footer > div > div > div:nth-child(1) > a")).click();}//回复public void RepleSuc(){ShowPost();//在回复框中输入内容driver.findElement(By.cssSelector("#article_details_reply > div.editormd-toolbar > div > ul > li:nth-child(20) > a")).click();//点击回复按钮driver.findElement(By.cssSelector("#details_btn_article_reply")).click();String replySuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert replySuc.equals("提示");}//回复失败public void RepleFail() throws IOException {ShowPost();//当回复框为空没有内容时直接点击回复按钮driver.findElement(By.cssSelector("#details_btn_article_reply")).click();String replyFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert replyFail.equals("提示");}//个人中心public void PersonalCenter(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击个人中心driver.findElement(By.cssSelector("#index_user_settings")).click();//通过查看头像是否存在来校验页面是否加载成功driver.findElement(By.cssSelector("#settings_avatar"));}//个人中心修改失败01---修改密码,原密码错误,新密码和确认密码一致public void PersonalCenterModifyFail01() throws IOException {PersonalCenter();//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();String modifyFail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail01.equals("警告");//刷新页面driver.navigate().refresh();}//个人中心修改失败02---修改密码,原密码正确,新密码和确认密码不一致public void PersonalCenterModifyFail02() throws IOException {PersonalCenter();//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();String modifyFail02 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail02.equals("提示");//刷新页面driver.navigate().refresh();}//个人中心修改失败03---未修改简介内容,确点击修改按钮public void PersonalCenterModifyFail03() throws IOException {driver.findElement(By.cssSelector("#settings_submit_remark")).click();String modifyFail03 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail03.equals("警告");//刷新页面driver.navigate().refresh();}//个人中心修改成功public void PersonalCenterModifySuc() throws InterruptedException, IOException {PersonalCenter();//清空当前昵称driver.findElement(By.cssSelector("#setting_input_nickname")).clear();//输入要修改的昵称driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys("阿巴阿巴4");//点击修改driver.findElement(By.cssSelector("#setting_submit_nickname")).click();//提示修改成功String modifyNicknameSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifyNicknameSuc.equals("成功");//清空当前邮箱driver.findElement(By.cssSelector("#setting_input_email")).clear();//输入要修改的邮箱driver.findElement(By.cssSelector("#setting_input_email")).sendKeys("275****82@qq.com");//点击修改driver.findElement(By.cssSelector("#setting_submit_email")).click();//提示修改成功String modifymailSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifymailSuc.equals("成功");//清空当前电话号码driver.findElement(By.cssSelector("#setting_input_phoneNum")).clear();//输入要修改的电话号码driver.findElement(By.cssSelector("#setting_input_phoneNum")).sendKeys("151*****123");//点击修改driver.findElement(By.cssSelector("#setting_submit_phoneNum")).click();//提示修改成功String modifTelySuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifTelySuc.equals("成功");//个人简介driver.findElement(By.cssSelector("#settings_textarea_remark")).clear();driver.findElement(By.cssSelector("#settings_textarea_remark")).sendKeys("东海皇帝");driver.findElement(By.cssSelector("#settings_submit_remark")).click();//提示修改成功String modifTextSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifTextSuc.equals("成功");//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0123");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入新密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();getScreenShot(getClass().getName());//注册成功返回登录页面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//退出public void Exit(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击退出driver.findElement(By.cssSelector("#index_user_logout#index_user_logout")).click();}}
2.7 RunTest 类(测试运行)
import common.Utils;
import tests.ListPage;
import tests.LoginPage;
import tests.PageByNoLogin;
import tests.RegisterPage;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:论坛系统自动化测试* Author: WJW* Date: 2024-10-16* Time: 19:16*/
public class RunTests {public static void main(String[] args) throws IOException, InterruptedException {//未登录页面测试PageByNoLogin pageByNoLogin = new PageByNoLogin();pageByNoLogin.ListPageByNoLogin();RegisterPage register = new RegisterPage();
// //测试注册页面是否加载成功register.RegisterPageRight();
// //注册成功register.RegisterSuc();//注册失败register.RegisterFai01();register.RegisterFai02();register.RegisterFai03();register.RegisterFai04();register.RegisterFai05();LoginPage login = new LoginPage();//测试登录页面是否加载成功login.loginPageRight();//登录失败login.LoginFail01();login.LoginFail02();login.LoginFail03();// 登录成功login.LoginSuc();ListPage list = new ListPage();//测试列表页面是否加载成功list.ListByLoging();//测试站内信息回复成功list.MessageSuc();//测试站内信息回复失败list.MessageFail();//成功发布帖子list.PublishPostSuc();//发布帖子失败list.PublishPostFail();//显示个人帖子list.ShowPost();// 点赞list.LickCount();//编辑成功list.EditSuc();//编辑失败list.EditFail();//删除成功list.DeleteSuc();//删除失败list.DeleteFail();//回复成功list.RepleSuc();//回复失败list.RepleFail();//个人中心list.PersonalCenter();//个人中心修改失败list.PersonalCenterModifyFail01();list.PersonalCenterModifyFail02();list.PersonalCenterModifyFail03();//个人中心修改成功list.PersonalCenterModifySuc();//退出list.Exit();//释放driver对象Utils.driver.quit();}
}
3. 性能测试
性能测试码云链接:FourmPerformanceTest
使用 jmeter 进行简单性能测试:针对登录、编写并发布帖子以及删除帖子、退出等功能进行简单的性能测试。然后在实现的过程中,添加梯度压测线程组,来实现用户的并发操作。
3.1 HTTP请求默认值
论坛中涉及到的接口协议、IP、端口号全都⼀样,可以单独抽取出来存放在默认值中,其他接口就可以省略不写协议、IP、端口号口。
3.2 CSV数据文件设置
以登陆接口为例,当我们执⾏登陆接口的性能测试时,手动配置了用户名和密码为固定的username和password,然而实际使⽤中不可能只有⼀个用户登录陆,为了模拟更真实的登录环境,我们需要提供更多的用户username和password来实现登录操作
添加⽅式:线程组⸺⸺配置元件⸺⸺CSV数据⽂件设置
操作步骤:
1)CSV数据文件设置
- 文件名:填写csv文件的路径。建议使用绝对路径。
- 文件编码:UTF-8
- 变量名称:从csv数据⽂件中读起的数据需要保存到的变量名。有多个变量时⽤逗号分隔
- 是否忽略首行:是否从csv数据文件第⼀行开始读取。
- 分隔符:要求与csv数据文件中多列的分隔符⼀致
- 遇到文件结束符再次循环:若选择为True当数据不够的时候会从头取。若选择False,则需要勾选下面的配置,遇到⽂件结束符停止线程,这⾥如果不勾选,请求将会报错。
2)编写loginTest.csv⽂件:
3)修改登陆接口及其他涉及到username和password获取的参数。修改完该配置后,登陆接口发起请求时将从csv文件中获取配置好的username和password参数,获取顺序为从上往下依次获取
4)修改线程组中线程数,使得每次取到的username和password都不⼀样
5)运行结果
3.3 梯度压测
- 添加梯度压测线程组
对各个接口进行压力测试,设当前线程有100(小编的电脑上万的跑不起来,这里就以100为例)
- This group will start:启动多少个线程,同线程组中的线程数
- First,wait for:等待多少秒才开始压测,一般默认为0
- Then start:一开始有多少个线程数,一般默认为0
- Next,add:下一次增加多少个线程数
- threads every:当前运⾏多⻓时间后再次启动线程,即每⼀次线程启动完成之后的的持续时间
- using ramp-up:启动线程的时间;若设置为1秒,表示每次启动线程都持续1秒
- thenhold loadfor:线程全部启动完之后持续运行多长时间
- finally,stop/threadsevery:多长时间释放多少个线程;若设置为20个和1秒,表示持续负载结束之后每1秒钟释放20个线程
-
聚合报告
从聚合报告可以看到性能测试过程中整体的数据变化,没有发现异常
-
Response Times Over Time主要用于监听整个事务运⾏期间的响应时间,观察并分析响应时间的实时平均值以及整体响应时间的走向。通过这⼀监听器,能够更直观地了解系统在不同时间点的响应性能。
Response Times Over Time的图形展示中,横坐标通常代表运行时间,而纵坐标则代表响应时间(单位是毫秒)。 -
从性能测试报告中可以清晰的看到,所有接口的测试都通过!
本章到这里就结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!
Fighting!!!✊