文章目录
一、项目背景
宣纸阁是一种基于互联网的社群交流平台,旨在为用户提供信息共享、观点讨论与兴趣互动的空间。其核心理念是通过结构化的话题组织和用户参与,构建开放、有序的在线社区生态。本项目致力于打造一个功能全面、界面简洁的现代化网络社区平台,旨在为用户搭建高效连接桥梁,促进知识共享,并汇聚志同道合的兴趣群体。
二、项目功能
- 注册页面:用户可通过输入有效的用户名和密码完成注册,注册成功后将自动跳转至登录页面。
- 登录页面:用户输入正确的用户名和密码即可登录,登录成功后将进入帖子列表页面。
- 帖子列表页面:用户可在选定板块中浏览帖子列表,点击任意帖子即可查看详情;通过"发布帖子"按钮进入编辑页面;点击个人头像后,选择"我的帖子"可查看个人发帖记录,选择"个人中心"可进入个人主页,选择"退出登录"可完成账号登出;页面右上角设有搜索框,支持帖子检索。管理员用户额外享有板块管理权限,可进行板块的增删操作。
- 帖子详情页面:管理员和作者可对帖子及回复进行编辑和删除操作;所有注册用户均享有向作者发送站内信、为帖子点赞以及参与回复的基本功能。
- 帖子编辑页面:用户可在此发布新内容。
- 站内信:点击页面右上角的铃铛图标,即可查看站内消息。通过该功能,用户不仅可以接收信息,还能便捷地发送和回复站内信。
- 个人帖子页面:展示用户发布的所有帖子。
- 个人中心页面:用户可以修改昵称、密码、邮箱地址、电话号码以及个人简介。
三、测试计划
1. 功能测试
1.1 注册页面
1.1.1 正常注册
- 输入合法用户名和密码,点击注册——显示注册成功
1.1.2 异常注册
-
未输入账号和密码,点击注册——显示注册失败
-
输入账号,但是未输入密码,点击注册——显示注册失败
-
未输入账号,但是输入密码,点击注册——显示注册失败
-
输入已注册的账号,输入密码,点击登录——显示注册失败
1.2 登录页面
1.2.1 正常登录
- 输入正确的账号和密码,点击登录——显示登录成功
1.2.2 异常登录
-
未输入账号和密码。点击登录——显示登录失败
-
输入账号但是未输入密码,点击登录——显示登录失败
-
未输入账号但是输入密码,点击登录——显示登录失败
-
输入正确的账号,错误的密码,点击登录——显示登录失败
1.3 帖子列表页面
1.3.1 帖子列表页面是否正常
-
若用户为管理员,是否显示新增板块和删除板块按钮
-
若用户为普通用户,是否显示新增板块和删除板块按钮
-
点击不同板块,帖子列表展示是否正常
-
搜索框中输入内容,搜索结果是否正常
1.3.2 页面跳转
-
点击帖子标题,是否能进入对应的帖子详情页面
成功 -
点击小铃铛图标,是否进入站内信页面
成功 -
点击个人头像 → 点击我的帖子,是否进入我的帖子页面
成功 -
点击个人头像 → 点击个人中心,是否进入个人中心页面
成功 -
点击个人头像 → 点击退出登录,是否跳转到登录页面
成功
1.4 帖子详情页面
1.4.1 功能验证
-
用户是否可以回复帖子
-
用户是否可以点赞帖子
-
点击发私信按钮,是否可以发送站内信
1.4.2 权限验证
-
若用户为作者或管理,编辑按钮和删除按钮是否正常显示
作者:
管理: -
若用户不是作者或管理,编辑按钮和删除按钮是否隐藏
1.5 帖子编辑页面
1.5.1 正常编辑
- 输入标题,输入内容,点击提交——发布成功
1.5.2 异常编辑
-
不输入标题,不输入内容,点击提交——发布失败
-
输入标题,不输入内容,点击提交——发布失败
1.6 站内信
1.6.1 发送功能
-
不输入内容,点击提交——发送失败
-
输入内容,点击提交——发送成功
1.6.2 回复功能
- 不输入内容,点击提交——回复失败
- 输入内容,点击提交——回复成功
2. 自动化测试
2.1 功能测试
2.1.1 枚举类
package com.example.forum.auto.common;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/12 14:58
* @Description
*/
public enum BrowserName {
CHROME("chrome"),
EDGE("edge");
String browserName;
public String getBrowserName() {
return browserName;
}
BrowserName(String browserName) {
this.browserName = browserName;
}
}
2.1.2 创建浏览器驱动类
package com.example.forum.auto.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 org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857 [原文地址,请尊重原创]
* @date 2025/4/20 22:22
* @Description
*/
public class Utils {
public static WebDriver driver = null;
public WebDriverWait wait;
/**
* Created by hanzishuai on 2025/4/20
*
* @param
* @return void
* @Description 创建 Driver
*/
private WebDriver createChromeDriver() {
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(15));
}
return driver;
}
private WebDriver createEdgeDriver() {
if (driver == null) {
WebDriverManager.edgedriver().setup();
EdgeOptions options = new EdgeOptions();
options.addArguments("--remote-allow-origins=*");
driver = new EdgeDriver(options);
// 隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(15));
}
return driver;
}
public Utils(String url) {
if(driver == null) {
driver = createChromeDriver();
driver.get(url);
}
wait = new WebDriverWait(driver, Duration.ofSeconds(15));
driver.manage().window().maximize();
}
public Utils(String url, BrowserName browserName) {
if (browserName.getBrowserName().equals(BrowserName.EDGE.getBrowserName())) {
driver = createEdgeDriver();
driver.get(url);
} else if (browserName.getBrowserName().equals(BrowserName.CHROME.getBrowserName())) {
driver = createChromeDriver();
driver.get(url);
}
wait = new WebDriverWait(driver, Duration.ofSeconds(15));
driver.manage().window().maximize();
}
public void sleep() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void sleep(Long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Created by hanzishuai on 2025/4/20
*
* @param str 截图名称的前缀
* @return
* @Description 屏幕截图
*/
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/com/example/forum/auto/images/" + dirTime + "/" + str + "_" + fileTime + ".png";
// 截图
File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile, new File(fileName));
}
}
2.1.3 注册页面测试
package com.example.forum.auto.tests;
import com.example.forum.auto.common.BrowserName;
import com.example.forum.auto.common.Utils;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.util.UUID;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/11 22:16
* @Description
*/
public class RegisterPage extends Utils {
public static final String url = "http://82.157.200.90:58081/sign-up.html";
public RegisterPage() {
super(url);
}
public RegisterPage(BrowserName browserName) {
super(url, browserName);
}
/**
* Created by hanzishuai on 2025/5/11
*
* @Description 检查注册页面是否加载完毕
*/
@SneakyThrows
public void checkPageRight() {
driver.findElement(By.cssSelector("#username"));
driver.findElement(By.cssSelector("#nickname"));
driver.findElement(By.cssSelector("#password"));
driver.findElement(By.cssSelector("#passwordRepeat"));
driver.findElement(By.cssSelector("#app > div:nth-child(6) > label > span"));
}
private void register(String username,String nickname,String passwordRepeat, String password,@NonNull Boolean policy) {
// 将输入框清空
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#nickname")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#passwordRepeat")).clear();
WebElement element = driver.findElement(By.cssSelector("#app > div:nth-child(6) > label > span"));
if(element.isSelected()) {
element.click();
}
// 输入账号密码,并点击提交
if (username != null) {
driver.findElement(By.cssSelector("#username")).sendKeys(username);
}
if(nickname != null) {
driver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
}
if (password != null) {
driver.findElement(By.cssSelector("#password")).sendKeys(password);
}
if (passwordRepeat != null) {
driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(passwordRepeat);
}
if(policy) {
WebElement element2 = driver.findElement(By.cssSelector("#app > div:nth-child(6) > label > span"));
if(element2.isSelected()) {
element2.click();
}
}
driver.findElement(By.cssSelector("#submit")).click();
}
@SneakyThrows
public void registerFail() {
// 不输入账号和密码,点击提交
register(null, null, null, null,false);
register("test2", null, null, null,false);
register("test2", "test2", null, null,false);
register("test2", "test2", "123456", null,false);
register("test2", "test2", "123456", "123",false);
register("test2", "test2", "123456", "123456",false);
register("awa", "awa", "123456", "123456",true);
}
@SneakyThrows
public void registerSuccess() {
String username = UUID.randomUUID().toString().replace("-", "").substring(0,7);
register(username, username, "123456", "123456",true);
// 截图
screenShot("registerSuccess");
// 注册成功会跳转到登录页面
String text1 = driver.findElement(By.cssSelector("#submit")).getText();
assert "登录".equals(text1);
}
public void intoLoginPage() {
WebElement element = driver.findElement(By.cssSelector("#app > div.text-center.text-muted.mt-3 > a"));
wait.until(ExpectedConditions.elementToBeClickable(element));
element.click();
}
}
2.1.4 登录页面测试
package com.example.forum.auto.tests;
import com.example.forum.auto.common.BrowserName;
import com.example.forum.auto.common.Utils;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/15 17:12
* @Description
*/
public class LoginPage extends Utils {
public static final String url = "http://82.157.200.90:58081/sign-in.html";
public LoginPage(BrowserName browserName) {
super(url, browserName);
}
public LoginPage() {
super(url);
}
@SneakyThrows
public void checkPageRight() {
driver.findElement(By.cssSelector("#username"));
driver.findElement(By.cssSelector("#password"));
driver.findElement(By.cssSelector("#submit"));
}
private void login(String username, String password) {
// 将输入框清空
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
// 输入账号密码,并点击提交
if (username != null) {
driver.findElement(By.cssSelector("#username")).sendKeys(username);
}
if (password != null) {
driver.findElement(By.cssSelector("#password")).sendKeys(password);
}
driver.findElement(By.cssSelector("#submit")).click();
}
@SneakyThrows
public void loginFail() {
// 不输入账号和密码,点击提交
login(null, null);
// 输入账号,不输入密码,点击提交
login("awa", null);
// 不输入账号,输入密码,点击提交
login(null, "123");
screenShot("LoginFail");
// 输入账号,输入错误的密码,点击提交
login("awa", "12");
}
@SneakyThrows
public void loginSuccess() {
login("awa", "123456");
// 如果登录成功会进入帖子列表页面
driver.findElement(By.cssSelector("#article_list_board_title"));
}
}
2.1.5 帖子列表测试
package com.example.forum.auto.tests;
import com.example.forum.auto.common.BrowserName;
import com.example.forum.auto.common.Utils;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.io.IOException;
import java.util.List;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/15 17:46
* @Description
*/
public class ArticleListPage extends Utils {
public static final String url = "http://82.157.200.90:58081/index.html";
public ArticleListPage(BrowserName browserName) {
super(url, browserName);
}
public ArticleListPage() {
super(url);
}
@SneakyThrows
public void checkPageRight() {
driver.findElement(By.cssSelector("#article_list_board_title"));
driver.findElement(By.cssSelector("#search-input"));
driver.findElement(By.cssSelector("#hzs-forum-content"));
}
public void changeBoard() {
List<WebElement> elements = driver.findElements(By.cssSelector("#topBoardList span.nav-link-title"));
for (WebElement element : elements) {
element.click();
}
elements.get(0).click();
}
public void intoArticleDetail() throws IOException {
try {
WebElement element = driver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong"));
String text = element.getText();
wait.until(ExpectedConditions.elementToBeClickable(element));
Thread.sleep(500);
element.click();
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#details_article_title")));
assert driver.findElement(By.cssSelector("#details_article_title")).getText().equals(text);
} catch (Exception e) {
screenShot("intoArticleDetailError");
}
}
public void intoMyArticlePage() {
WebElement element = driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.dropdown > a"));
wait.until(ExpectedConditions.elementToBeClickable(element));
sleep();
element.click();
WebElement element1 = driver.findElement(By.cssSelector("#index_user_settings"));
sleep();
wait.until(ExpectedConditions.elementToBeClickable(element1));
element1.click();
}
}
2.1.6 帖子详情页面测试
package com.example.forum.auto.tests;
import com.example.forum.auto.common.BrowserName;
import com.example.forum.auto.common.Utils;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.springframework.util.StringUtils;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/15 19:30
* @Description
*/
public class ArticleDetailPage extends Utils {
public static final String url = "http://82.157.200.90:58081/index.html";
public ArticleDetailPage(BrowserName browserName) {
super(url, browserName);
}
public ArticleDetailPage() {
super(url);
}
@SneakyThrows
public void checkPageRight() {
driver.findElement(By.cssSelector("#btn_details_send_message"));
driver.findElement(By.cssSelector("#details_btn_like_count"));
driver.findElement(By.cssSelector("#details_btn_article_reply"));
}
private void sendMessage(String content) {
WebElement element = driver.findElement(By.cssSelector("#btn_details_send_message"));
wait.until(ExpectedConditions.elementToBeClickable(element));
element.click();
WebElement element1 = driver.findElement(By.cssSelector("#index_message_receive_content"));
wait.until(ExpectedConditions.elementToBeClickable(element1));
if(StringUtils.hasLength(content)) {
element1.sendKeys(content);
}
driver.findElement(By.cssSelector("#btn_index_send_message")).click();
}
public void sendMessageFail() {
sendMessage(null);
sendMessage("");
}
public void sendMessageSuccess() {
sendMessage("test");
}
}
2.1.7 个人中心测试
package com.example.forum.auto.tests;
import com.example.forum.auto.common.BrowserName;
import com.example.forum.auto.common.Utils;
import lombok.SneakyThrows;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
/**
* @author hanzishuai
* Blog : https://blog.csdn.net/qrwitu142857
* @date 2025/5/15 18:07
* @Description
*/
public class PersonalCenterPage extends Utils {
public static final String url = "http://82.157.200.90:58081/index.html";
public PersonalCenterPage() {
super(url);
}
public PersonalCenterPage(BrowserName browserName) {
super(url, browserName);
}
@SneakyThrows
public void checkPageRight() {
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#setting_input_nickname")));
driver.findElement(By.cssSelector("#setting_input_nickname"));
driver.findElement(By.cssSelector("#setting_submit_nickname"));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#setting_submit_nickname")));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#setting_input_email")));
driver.findElement(By.cssSelector("#setting_input_email"));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#setting_submit_email")));
driver.findElement(By.cssSelector("#setting_submit_email"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#setting_input_phoneNum")));
driver.findElement(By.cssSelector("#setting_input_phoneNum"));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#setting_submit_phoneNum")));
driver.findElement(By.cssSelector("#setting_submit_phoneNum"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#settings_input_oldPassword")));
driver.findElement(By.cssSelector("#settings_input_oldPassword"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#settings_input_newPassword")));
driver.findElement(By.cssSelector("#settings_input_newPassword"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#settings_input_passwordRepeat")));
driver.findElement(By.cssSelector("#settings_input_passwordRepeat"));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#settings_submit_password")));
driver.findElement(By.cssSelector("#settings_submit_password"));
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#settings_textarea_remark")));
driver.findElement(By.cssSelector("#settings_textarea_remark"));
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#settings_submit_remark")));
driver.findElement(By.cssSelector("#settings_submit_remark"));
}
private void modify(String nickname, String email, String phoneNum, String oldPassword, String newPassword, String passwordRepeat, String remark) {
checkPageRight();
if (nickname != null) {
driver.findElement(By.cssSelector("#setting_input_nickname")).clear();
driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(nickname);
driver.findElement(By.cssSelector("#setting_submit_nickname")).click();
}
if (email != null) {
driver.findElement(By.cssSelector("#setting_input_email")).clear();
driver.findElement(By.cssSelector("#setting_input_email")).sendKeys(email);
WebElement emailSubmitButton = driver.findElement(By.cssSelector("#setting_submit_email"));
wait.until(ExpectedConditions.elementToBeClickable(emailSubmitButton));
sleep();
emailSubmitButton.click();
}
if (phoneNum != null) {
driver.findElement(By.cssSelector("#setting_input_phoneNum")).clear();
driver.findElement(By.cssSelector("#setting_input_phoneNum")).sendKeys(phoneNum);
WebElement element = driver.findElement(By.cssSelector("#setting_submit_phoneNum"));
wait.until(ExpectedConditions.elementToBeClickable(element));
element.click();
}
if (oldPassword != null) {
driver.findElement(By.cssSelector("#settings_input_oldPassword")).clear();
driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys(oldPassword);
}
if (newPassword != null) {
driver.findElement(By.cssSelector("#settings_input_newPassword")).clear();
driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys(newPassword);
}
if (passwordRepeat != null) {
driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).clear();
driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys(passwordRepeat);
}
if (remark != null) {
driver.findElement(By.cssSelector("#settings_textarea_remark")).clear();
driver.findElement(By.cssSelector("#settings_textarea_remark")).sendKeys(remark);
driver.findElement(By.cssSelector("#settings_submit_remark")).click();
}
if (oldPassword != null || newPassword != null || passwordRepeat != null) {
driver.findElement(By.cssSelector("#settings_submit_password")).click();
}
}
public void checkModify() {
modify(null, null, null, null, null, null, null);
modify("", "", "", "", "", "", "");
modify("awa1", "abcdef@a.com", null, "123456", null, null, "个人介绍");
modify("awa1", "abcdef@a.com", "123", "123456", null, null, "个人介绍");
modify("awa1", "abcdef@a.com", null, "123456", "1234", null, "个人介绍");
modify("awa1", "abcdef@a.com", null, "123456", "1234", "12", "个人介绍1");
modify("awa", "abcdef@a.com", null, "123456", "1234", "12", "个人介绍1");
modify("awa", "123456@qq.com", "123456", "123456", "123456", "123456", "个人介绍");
}
}
2.1.8 自动化测试视频
宣纸阁自动化测试
四、 附件
摘要: