介绍
一、项目简介
本项目是一个论坛系统,采用前后端分离的方式实现,该系统旨在为用户提供一个基于 Web 的文章发布和讨论平台。
用户可以进行注册登录、查看和修改个人信息,进行帖子的增删改查等基础操作。
用户可以点赞、评论帖子,私信其他用户,并在帖子详情页上查看点赞数和阅读量等信息。
二、测试计划
目的:确保论坛系统功能符合设计需求,发现并修复系统中的bug
测试范围:包括功能测试,界面测试、兼容性测试、易用性测试、安全测试
测试范围
功能测试:覆盖用户注册、用户登录、帖子发布、帖子编辑、论坛主页、帖子详情、评论与私信自动化测试:关键业务流程,如登录、帖子浏览、评论与私信、发布帖子等功能
自动化测试:覆盖注册页、登录页、论坛首页、帖子详情页、帖子发布和编辑、私信与评论等页面
测试环境
Windows11
Chrome版本 134.0.6998.89(正式版本) (64 位)、Edge版本 131.0.2903.112 (正式版本) (64 位)
测试工具
功能测试:手动测试
自动化测试:IDEA+Selenium+java
测试任务:
编写用户注册、登录、帖子浏览、帖子发布与编辑、点赞评论与私信等模块的测试用例,保证主体功能完整
执行测试用例
功能测试
一、测试用例



二、手动测试
2.1登录页测试
2.1.1 页面正常打开

2.1.2 登录测试
场景一、正常登录
管理员登录

普通用户登录

场景二、异常登录




2.2 注册页面
2.2.1 正常注册

2.2.2 异常注册
场景一、用户名已存在
预期:提示用户已存在

场景二、用户名、昵称、密码均为空
预期:提示用户名、昵称、密码不能为空

场景三、源密码正确、重复密码错误
预期:请检查确认密码

预期:提示用户名不能为空、昵称不能为空
2.3 主界面
2.3.1 标签页
场景、点击对应标签页
预期:跳转对应模块帖子列表页

2.3.2 发布帖子按钮的测试
场景、点击发布帖子按钮
预期:跳转发布帖子详情页面


场景一、我的帖子按钮测试
预期:跳转到我的帖子页面

场景二、个人中心按钮测试
预期:跳转到个人中心

场景三、退出按钮测试
预期:退回到登录页

2.3.4 帖子详情按钮的测试
场景
点击帖子标题
预期:跳转帖子详情页面

2.4 帖子编辑
2.4.1 板块、标题、内容完整
场景
板块、标题、内容完整
预期:正确发布且在列表页新增

2.4.2 帖子编辑部分缺失
场景一
标题为空、内容完整
预期:请输入帖子标题

场景二
标题完整、内容为空
预期:请输入内容

场景三
标题、内容均为空
预期:请输入标题和内容

不足:提示不完整
2.5 帖子详情
2.5.1 作者本人
场景一
点赞按钮测试
预期:提示点赞成功

场景二
编辑按钮测试
预期:跳转到帖子编辑页面

场景三
删除按钮测试
预期:跳回首页并发现该帖子消失

场景四
楼中楼回复
2.5.2 其他用户

2.5.3 发送站内信功能
场景一
内容完整
预期:发布成功,且在对方站内信内可见


场景二
内容为空
预期发布失败

2.6 个人中心
2.6.1 头像修改
预期:修改成功
Bug:头像修改失败,没有更改
2.6.2 昵称修改
场景一、合法昵称
预期:修改成功

场景二、不合法昵称
预期:修改失败

Bug:没有提示修改失败,但不合法昵称无法进行修改操作
2.6.3 邮箱地址修改
场景一、合法邮箱地址
预期:修改成功

场景二、不合法邮箱地址
预期:修改失败

Bug:没有进行限制
2.6.4 电话号码修改
场景一、合法电话号码
预期:修改成功

场景二、不合法电话号码
预期:修改失败

Bug:没有进行限制
2.6.5 密码修改
场景一
新密码、确认密码相同
预期:跳转到登录页面,进行重新登录

场景二
新密码、确认密码不同
预期:提示两次输入的密码不相同

2.6.6 个人简介
场景一、内容完整
预期:操作成功

场景二、内容为空
预期:无法进行修改

改进:可以进行提示
2.7 站内信

2.7.1 回复功能
场景一、
内容完整
预期:发布成功

场景二、
内容为空
预期:发布失败
2.8 搜索功能
2.8.1 输入内容进行搜索
场景
匹配帖子的关键字
预期:相关帖子显示且可点击跳转详情页

三、自动化测试
Utils工具类
java
package common;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.RetrySessionRequestException;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
public class Utils {
public static WebDriver driver = null;
public static String DetailUrl = null;
public WebDriverWait wait = null;
public Utils(String url){
driver = createWebDriver();
wait = new WebDriverWait(driver,Duration.ofSeconds(3));
driver.get(url);
}
public static WebDriver createWebDriver(){
if (driver == null) {
// System.setProperty("wdm,edgeDriverUrl","http://msedgedriver.microsoft.com/");
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 void screenShot(String str) throws IOException {
SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");
String dirTime = sim1.format(System.currentTimeMillis());
String fileTime = sim2.format(System.currentTimeMillis());
String filename = "./src/test/java/images/" + dirTime + "/" + str + "_" + fileTime + ".png";
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile,new File(filename));
}
public static void quit(){
driver.quit();
}
}
ArticleDetail
java
package test;
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;
public class ArticleDetail extends Utils {
public static String url = "http://120.25.194.223:58080/index.html";
public ArticleDetail() {
super(url);
}
public void articleDetailTest (){
driver.findElement(By.xpath("//*[@id=\"artical-items-body\"]/div[1]/div/div[2]/div[1]/a")).click();
authorArticleJob();
personArticleJob();
}
private void personArticleJob(){
// 这里我们需要重新换普通用户身份进入系统
// 由于上个 测试 作者文章详情测试
// 我们需要先重新进入登录页面
// 这里需要 写入 浏览器导航相关的代码
driver.navigate().to("http://120.25.194.223:58080/sign-in.html");
driver.findElement(By.cssSelector("#username")).sendKeys("小明");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
// 重新进入文章界面
driver.findElement(By.xpath("//*[@id=\"artical-items-body\"]/div[1]/div/div[2]/div[1]/a")).click();
// 点赞按钮
driver.findElement(By.cssSelector("#details_btn_like_count")).click();
// 查看是否有编辑按钮
driver.findElement(By.cssSelector("#details_artile_edit"));
// 查看是否有删除按钮
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[2]/div/div/div[1]/div[2]/div[2]/div/div[3]/div/a"));
// 在此界面 继续测试发送站内信功能
driver.findElement(By.cssSelector("#btn_details_send_message")).click();
// 站内信内容完整
sendMessage("你好");
// 站内信发送内容为空
sendMessage(" ");
}
private void authorArticleJob(){
// 作者本人操作
// 点赞按钮
driver.findElement(By.cssSelector("#details_btn_like_count")).click();
// 删除按钮
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[2]/div/div/div[1]/div[2]/div[2]/div/div[3]/div/a")).click();
// 因为 删除时弹出新的窗口,这里我们需要切换窗口
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
// 等待js组件加载完成后,再进行点击窗口操作
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"details_delete_modal\"]/div/div/button")));
driver.findElement(By.xpath("//*[@id=\"details_delete_modal\"]/div/div/button")).click();
// 编辑按钮
driver.findElement(By.cssSelector("#details_artile_edit")).click();
// 楼中楼回复
// 内容完整
// 内容为空
}
/**
* 发送站内信功能
*/
private void sendMessage(String message){
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w : allWindow){
if (w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.cssSelector("#index_message_receive_content")).sendKeys(message);
driver.findElement(By.cssSelector("#btn_index_send_message")).click();
}
}
IndexMessage
java
package test;
import common.Utils;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;
public class IndexMessage extends Utils {
private static String url = "http://120.25.194.223:58080/index.html";
public IndexMessage() {
super(url);
}
public void indexMessageTest(){
// 站内信回复
indexMessageReply("你好");
}
private void indexMessageReply(String message) {
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")).click();
// 切换窗口
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1)")).click();
String curWindow1 = driver.getWindowHandle();
Set<String> allWindow1 = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.cssSelector("#btn_index_message_reply")).click();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_receive_content")));
driver.findElement(By.cssSelector("#index_message_reply_receive_content")).sendKeys(message);
driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();
}
}
LoginPage
java
package test;
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.IOException;
import java.time.Duration;
public class LoginPage extends Utils {
public static String url = "http://120.25.194.223:58080/sign-in.html";
public LoginPage() {
super(url);
}
public void checkPasswordLogin() throws InterruptedException, IOException {
// 检验密码登录页面元素
// checkPasswordLoginElement();
// -----异常登录-----
// checkLoginAbnormalLogin();
// -----正常登录-----
checkLoginNormalLogin();
}
private void checkPasswordLoginElement() {
// 用户名
driver.findElement(By.cssSelector("#username"));
// 密码
driver.findElement(By.cssSelector("#password"));
// 登录
driver.findElement(By.cssSelector("#submit"));
// 注册
driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a"));
}
private void checkLoginNormalLogin() throws InterruptedException, IOException {
// 正常登录 密码 用户名都正确
driver.findElement(By.cssSelector("#username")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#password")).sendKeys("111111");
driver.findElement(By.cssSelector("#submit")).click();
// screenShot(getClass().getName());
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.textToBe(By.id("article_list_board_title"),"首页"));
}
private void checkLoginAbnormalLogin() throws InterruptedException {
// 异常登录
// 错误用户名
driver.findElement(By.cssSelector("#username")).sendKeys("1");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
// Thread.sleep(2000);
allClear();
// 错误密码
driver.findElement(By.cssSelector("#username")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#password")).sendKeys("123");
driver.findElement(By.cssSelector("#submit")).click();
// Thread.sleep(2000);
allClear();
// 用户名为空
driver.findElement(By.cssSelector("#username")).sendKeys(" ");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
// Thread.sleep(2000);
allClear();
// 密码为空
driver.findElement(By.cssSelector("#username")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#password")).sendKeys(" ");
driver.findElement(By.cssSelector("#submit")).click();
// Thread.sleep(2000);
allClear();
// 用户名和密码都为空
driver.findElement(By.cssSelector("#username")).sendKeys(" ");
driver.findElement(By.cssSelector("#password")).sendKeys(" ");
driver.findElement(By.cssSelector("#submit")).click();
// Thread.sleep(2000);
allClear();
}
private void allClear(){
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
}
}
MainListPage
java
package test;
import common.Utils;
import org.openqa.selenium.*;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;
public class MainListPage extends Utils {
public static String url = "http://120.25.194.223:58080/index.html";
public MainListPage() {
super(url);
}
public void mainListTest(){
checkMainList();
}
public void checkMainList(){
checkIndex();
checkPublish();
personCenter();
}
/**
* 标签测试
*/
private void checkIndex(){
// 检测标签按钮
driver.findElement(By.cssSelector("#nav_board_index")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(2) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(3) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(4) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(6) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(7) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(8) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(9) > a > span.nav-link-title")).click();
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(10) > a > span.nav-link-title")).click();
// 返回首页
driver.findElement(By.cssSelector("#nav_board_index > a > span.nav-link-title")).click();
}
/**
* 测试发布功能
*/
private void checkPublish(){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[1]/div/div/div[2]/div/a[1]")).click();
normalPublishArticle();
abnormalPublishArticle();
}
private void abnormalPublishArticle() {
// 帖子部分缺失
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[1]/div/div/div[2]/div/a[1]")).click();
// 标题为空、内容完整
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("");
WebElement title_label = driver.findElement(By.cssSelector("#article_post_title"));
title_label.sendKeys(Keys.TAB);
WebElement ele = driver.switchTo().activeElement();
ele.sendKeys("你好");
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
// 页面滑动到最顶端
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
// 标题完整,内容为空
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试");
WebElement title_label2 = driver.findElement(By.cssSelector("#article_post_title"));
title_label2.sendKeys(Keys.TAB);
WebElement ele2 = driver.switchTo().activeElement();
// 模拟Ctrl + A 键
ele2.sendKeys(Keys.CONTROL, "a");
// 删除键
ele2.sendKeys(Keys.DELETE);
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
// 标题、内容为空
driver.findElement(By.cssSelector("#article_post_title")).clear();
WebElement title_label3 = driver.findElement(By.cssSelector("#article_post_title"));
title_label3.sendKeys(Keys.TAB);
WebElement ele3 = driver.switchTo().activeElement();
ele3.sendKeys("");
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
}
private void normalPublishArticle() {
// 板块、标题、内容完整
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试");
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(1) > a > i")));
// 方法1
// 由于编辑器是 markdown 所以普通 sendKeys 无法 输入内容
// 这里要借助action 模拟鼠标 进行输入
// WebElement ele = driver.findElement(By.cssSelector("#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre > span"));
// Actions action = new Actions(driver);
// action.keyDown(Keys.ALT)
// .sendKeys(ele,Keys.ARROW_RIGHT)
// .keyUp(Keys.ALT)
// .keyDown(Keys.SHIFT)
// .sendKeys(Keys.ARROW_UP)
// .keyUp(Keys.SHIFT)
// .sendKeys(Keys.DELETE)
// .perform();
// action.sendKeys("这是通过selenium自动化输入的新的博客内容!!!").perform();
// 方法2
// # 定位到输入标题的位置
WebElement title_label = driver.findElement(By.cssSelector("#article_post_title"));
//# tab键跳转到输入内容的位置
title_label.sendKeys(Keys.TAB);
WebElement ele = driver.switchTo().activeElement();
//# 正常输入内容
ele.sendKeys("你好");
// 执行 JavaScript 滑动 下滑到页面最低端
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
}
/**
* 个人中心测试
*/
private void personCenter(){
// 昵称修改
alterNickname("小v");
// 邮箱地址修改
alterEmail("2714381197@qq.com");
// 电话号码修改
alterPhoneNumber("15518662993");
// 密码修改
alterPassword("123456","1234567","1234567");
// 个人简介修改
alterProfile("永无bug");
// 头像修改
alterPicture();
}
private void alterProfile(String profile) {
driver.findElement(By.xpath("//*[@id=\"settings_textarea_remark\"]")).clear();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"settings_textarea_remark\"]")).sendKeys(profile);
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"settings_submit_remark\"]")));
driver.findElement(By.xpath("//*[@id=\"settings_submit_remark\"]")).click();
}
private void alterNickname(String nickname) {
// 界面重新导航到主页面
driver.navigate().to("http://120.25.194.223:58080/index.html");
driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]")).click();
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.xpath("//*[@id=\"index_user_settings\"]")).click();
driver.findElement(By.xpath("//*[@id=\"setting_input_nickname\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_nickname\"]")).sendKeys(nickname);
driver.findElement(By.xpath("//*[@id=\"setting_submit_nickname\"]")).click();
}
private void alterPhoneNumber(String phoneNumber) {
driver.findElement(By.xpath("//*[@id=\"setting_input_phoneNum\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_phoneNum\"]")).sendKeys(phoneNumber);
driver.findElement(By.xpath("//*[@id=\"setting_submit_phoneNum\"]")).click();
}
private void alterPassword(String oldPassword, String newPassword, String repeatPassword) {
driver.findElement(By.xpath("//*[@id=\"settings_input_oldPassword\"]")).sendKeys(oldPassword);
driver.findElement(By.xpath("//*[@id=\"settings_input_newPassword\"]")).sendKeys(newPassword);
driver.findElement(By.xpath("//*[@id=\"settings_input_passwordRepeat\"]")).sendKeys(repeatPassword);
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"settings_submit_password\"]")).click();
}
private void alterEmail(String email) {
driver.findElement(By.xpath("//*[@id=\"setting_input_email\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_email\"]")).sendKeys(email);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"setting_submit_email\"]")).click();
}
private void alterPicture() {
// 界面重新导航到主页面
driver.navigate().to("http://120.25.194.223:58080/index.html");
driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]")).click();
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.xpath("//*[@id=\"index_user_settings\"]")).click();
// WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
// wait.until(ExpectedConditions.textToBe())
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[2]/div/div/div/div[2]/div/div[1]/div[2]/a")).click();
}
}
PersonCenter
java
package test;
import common.Utils;
import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
import java.util.Set;
public class PersonCenter extends Utils {
public static String url = "http://120.25.194.223:58080/index.html";
public PersonCenter() {
super(url);
}
public void personCenterTest() throws InterruptedException {
// 昵称修改
alterNickname("小v");
// 邮箱地址修改
alterEmail("2714381197@qq.com");
// 电话号码修改
alterPhoneNumber("15518662993");
// 密码修改
alterPassword("123456","1234567","1234567");
// 个人简介修改
alterProfile("永无bug");
// 头像修改
alterPicture();
}
private void alterProfile(String profile) {
driver.findElement(By.xpath("//*[@id=\"settings_textarea_remark\"]")).clear();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"settings_textarea_remark\"]")).sendKeys(profile);
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id=\"settings_submit_remark\"]")));
driver.findElement(By.xpath("//*[@id=\"settings_submit_remark\"]")).click();
}
private void alterNickname(String nickname) {
// 界面重新导航到主页面
driver.navigate().to("http://120.25.194.223:58080/index.html");
driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]")).click();
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.xpath("//*[@id=\"index_user_settings\"]")).click();
driver.findElement(By.xpath("//*[@id=\"setting_input_nickname\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_nickname\"]")).sendKeys(nickname);
driver.findElement(By.xpath("//*[@id=\"setting_submit_nickname\"]")).click();
}
private void alterPhoneNumber(String phoneNumber) {
driver.findElement(By.xpath("//*[@id=\"setting_input_phoneNum\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_phoneNum\"]")).sendKeys(phoneNumber);
driver.findElement(By.xpath("//*[@id=\"setting_submit_phoneNum\"]")).click();
}
private void alterPassword(String oldPassword, String newPassword, String repeatPassword) {
driver.findElement(By.xpath("//*[@id=\"settings_input_oldPassword\"]")).sendKeys(oldPassword);
driver.findElement(By.xpath("//*[@id=\"settings_input_newPassword\"]")).sendKeys(newPassword);
driver.findElement(By.xpath("//*[@id=\"settings_input_passwordRepeat\"]")).sendKeys(repeatPassword);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"settings_submit_password\"]")).click();
}
private void alterEmail(String email) {
driver.findElement(By.xpath("//*[@id=\"setting_input_email\"]")).clear();
driver.findElement(By.xpath("//*[@id=\"setting_input_email\"]")).sendKeys(email);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"setting_submit_email\"]")).click();
}
private void alterPicture() {
// 界面重新导航到主页面
driver.navigate().to("http://120.25.194.223:58080/index.html");
driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]")).click();
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for (String w: allWindow) {
if ( w != curWindow){
driver.switchTo().window(w);
}
}
driver.findElement(By.xpath("//*[@id=\"index_user_settings\"]")).click();
// WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
// wait.until(ExpectedConditions.textToBe())
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[2]/div/div/div/div[2]/div/div[1]/div[2]/a")).click();
}
}
PublishArticlePage
java
package test;
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class PublishArticlePage extends Utils {
public static String url = "http://120.25.194.223:58080/index.html";
public PublishArticlePage() {
super(url);
}
public void publishArticleTest() throws InterruptedException {
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[1]/div/div/div[2]/div/a[1]")).click();
normalPublishArticle();
abnormalPublishArticle();
}
private void abnormalPublishArticle() {
// 帖子部分缺失
driver.findElement(By.xpath("//*[@id=\"bit-forum-content\"]/div[1]/div/div/div[2]/div/a[1]")).click();
// 标题为空、内容完整
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("");
WebElement title_label = driver.findElement(By.cssSelector("#article_post_title"));
title_label.sendKeys(Keys.TAB);
WebElement ele = driver.switchTo().activeElement();
ele.sendKeys("你好");
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
// 页面滑动到最顶端
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
// 标题完整,内容为空
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试");
WebElement title_label2 = driver.findElement(By.cssSelector("#article_post_title"));
title_label2.sendKeys(Keys.TAB);
WebElement ele2 = driver.switchTo().activeElement();
// 模拟Ctrl + A 键
ele2.sendKeys(Keys.CONTROL, "a");
// 删除键
ele2.sendKeys(Keys.DELETE);
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, 0);");
// 标题、内容为空
driver.findElement(By.cssSelector("#article_post_title")).clear();
WebElement title_label3 = driver.findElement(By.cssSelector("#article_post_title"));
title_label3.sendKeys(Keys.TAB);
WebElement ele3 = driver.switchTo().activeElement();
ele3.sendKeys("");
((JavascriptExecutor) driver).executeScript("window.scrollTo(0, document.body.scrollHeight);");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]")).click();
}
private void normalPublishArticle() throws InterruptedException {
// 板块、标题、内容完整
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试");
WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));
wait.until(ExpectedConditions.textToBe(By.xpath("//*[@id=\"bit-forum-content\"]/div[1]/div/div/div/h2"), "发新帖"));
WebElement ele = driver.findElement(By.cssSelector("#editor > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre > span > span"));
Actions action = new Actions(driver);
action.keyDown(Keys.ALT)
.sendKeys(ele,Keys.ARROW_RIGHT)
.keyUp(Keys.ALT)
.keyDown(Keys.SHIFT)
.sendKeys(Keys.ARROW_UP)
.keyUp(Keys.SHIFT)
.sendKeys(Keys.DELETE)
.perform();
action.sendKeys("这是通过selenium自动化输入的新的博客内容!!!").perform();
driver.findElement(By.cssSelector("#article_post_submit")).click();
}
}
RegisterPage
java
package test;
import common.Utils;
import org.openqa.selenium.By;
public class RegisterPage extends Utils {
public static String url = "http://120.25.194.223:58080/sign-up.html";
public RegisterPage() {
super(url);
}
public void checkRegister( ){
// 异常注册
checkAbnormalRegister();
// 正常注册
checkNormalRegister("小明","小明","123456","123456");
}
private void checkAbnormalRegister( ) {
// 用户名、昵称为空
driver.findElement(By.cssSelector("#username")).sendKeys(" ");
driver.findElement(By.cssSelector("#nickname")).sendKeys(" ");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123456");
driver.findElement(By.cssSelector("#policy")).click();
driver.findElement(By.cssSelector("#submit")).click();
allClear();
// 用户名已存在
driver.findElement(By.cssSelector("#username")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#nickname")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123456");
driver.findElement(By.cssSelector("#policy")).click();
driver.findElement(By.cssSelector("#submit")).click();
allClear();
// 源密码正确 重复密码错误
driver.findElement(By.cssSelector("#username")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#nickname")).sendKeys("阿泽");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");
driver.findElement(By.cssSelector("#policy")).click();
driver.findElement(By.cssSelector("#submit")).click();
allClear();
}
private void checkNormalRegister(String user, String nickname, String password, String repeatPassword) {
driver.findElement(By.cssSelector("#username")).sendKeys(user);
driver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
driver.findElement(By.cssSelector("#password")).sendKeys(password);
driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(repeatPassword);
driver.findElement(By.cssSelector("#policy")).click();
driver.findElement(By.cssSelector("#submit")).click();
}
private void allClear(){
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#nickname")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#passwordRepeat")).clear();
}
}
MainTest
java
import org.openqa.selenium.support.ui.WebDriverWait;
import test.*;
import java.io.IOException;
public class MainTest {
public static void main(String[] args) throws InterruptedException, IOException {
RegisterPage registerPage = new RegisterPage();
registerPage.checkRegister();
LoginPage loginPage = new LoginPage();
loginPage.checkPasswordLogin();
MainListPage mainListPage = new MainListPage();
mainListPage.mainListTest();
PublishArticlePage pubArticlePage = new PublishArticlePage();
pubArticlePage.publishArticleTest();
ArticleDetail articleDetail = new ArticleDetail();
articleDetail.articleDetailTest();
PersonCenter personCenter = new PersonCenter();
personCenter.personCenterTest();
IndexMessage indexMessage = new IndexMessage();
indexMessage.indexMessageTest();
}
}
四、接口测试
1、jmeter








2、Swagger UI





3、postman
用户接口
登录界面


注册页面


个人信息


五、性能测试
5.1聚合报告

5.2 TPS

5.3响应时间可视化

5.4 活跃线程

5.5 性能报告






六、界面UI测试
1. 白天、夜间页面切换

++++问题:夜间模式,论坛logo图片出现异常++++
2. 页面布局合理,视觉元素一致


3. 站内信状态显示正常

七、兼容性测试
1.edge浏览器

2. ios系统下
Safari浏览器和Chrome浏览器


八、易用性测试
1. 密码不可视状态

九、安全测试
1. 密码连续输入多次,仍可继续输入

2. 直接访问除登录、注册页面外的界面直接跳回登录界面


3. 手机号和密码都经过加密处理
