目录
一、项目介绍
这是一个基于Spring+前后端分离的论坛系统项目
个人角色:完成整个项目的后端开发、测试、部署到云服务器
项目主要分为用户模块、帖子模块、站内信模块
- 用户模块:实现登录、注册、个人信息的维护
- 帖子模块:帖子发布、删除、修改、点赞、评论、分类等功能
- 站内信模块:向指定用户发送站内信,对指定站内信进行回复
二、测试计划
2.1 功能测试
2.1.1 功能测试的测试用例
2.1.2 演示部分测试用例
(1)正常登录,输入用户名:sans 密码:123456,点击登录后会进入论坛首页
点击登录:
再举测试一个异常登录的例子
异常登录:用户名或密码错误,用户名:sans 密码:123
(2)进入论坛首页后,点击帖子,进入帖子详情页,如果帖子作者不是当前登录用户本人,则在帖子详情页不会显示删除和编辑按钮
进入帖子详情页,作者不是本人,无编辑删除按钮:
如果作者是本人,则会显示删除和编辑按钮
(3)点击不同板块,显示该板块下的所有帖子
(4)对帖子进行回复后,回复信息会展示在上方,回复详情包含:回复内容、回复者、回复时间、发私信按钮
(5)点击帖子详情页的"删除"按钮后,会出现提示框,提示是否确认删除,点击删除后,回到论坛首页,并提示删除成功
要删除的帖子:
点击帖子详情页的"删除"按钮
点击删除,目标帖子消失并提示删除成功,说明已经删除了
(6)在个人中心页面,填写昵称、电话、邮箱、个人简介后,点击修改按钮,可以直接进行修改
sans用户的邮箱为:666@qq.com
在个人中心页面,填写邮箱地址,并点击修改后:
此时sans用户的邮箱如下:
如果修改密码,需要原密码、新密码和确认密码,点击提交后会跳转至登录页面,让用户重新登录
点击提交修改按钮后,会跳转:
2.2 自动化测试
接下来会通过selenium完成该项目的自动化测试,以模拟真实用户的操作
2.2.1 公共类
由于每个界面都需要驱动、截图、登录,部分页面对某些元素进行操作时,需要将当前页面先滑动至目标元素处才能进行操作,所以将以上功能写进一个公共类Utils中
Utils类:
import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
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.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
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(2));
}
return driver;
}
public Utils(String url)
{
//调用driver对象
driver = createDriver();
//访问url
driver.get(url);
}
//屏幕截图
public void getScreenShot(String str) throws 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.png
String filename ="./src/test/image/"+ dirTime +"/" + str + "-" + fileTime+".png";
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
//srcFile放到指定位置
FileUtils.copyFile(srcFile,new File(filename));
}
//登录
public static void login() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys("sans");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
//检查点击登陆之后是否登陆成功
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));
driver.findElement(By.cssSelector("#article_list_board_title"));
//页面url来检查是否登陆成功
String expect = driver.getCurrentUrl();
//System.out.println(expect);
assert expect.equals("http://82.156.81.197:58080/index.html");
}
//滑动页面
public static WebElement slidePage(String selector) throws InterruptedException {
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement target = driver.findElement(By.cssSelector(selector));
js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", target);
//等待页面已经划至发布按钮处
Thread.sleep(500);
return target;
}
}
2.2.2 登录
LoginPage类中主要包含用户登录界面的相关测试方法,包括:
- loginPageRight():检查页面是否正常显示
- loginSuc():检查登录功能---成功登录
- loginFail():检查登录功能---登录失败,以用户名存在,密码错误和用户名不存在,密码非空作为测试用例
LoginPage类
import common.Utils;
import org.openqa.selenium.By;
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://82.156.81.197:58080/sign-in.html";
public LoginPage() {
super(url);
}
/**
* 检查页面是否正常显示
*/
public void loginPageRight() throws InterruptedException, IOException {
//通过查看页面元素是否存在来检查页面加载成功与否
driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2"));
//用户名输入框
driver.findElement(By.cssSelector("#username"));
}
/**
* 检查登录功能---成功登录
*/
public void LoginSuc() throws IOException, InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
driver.findElement(By.cssSelector("#username")).clear();
driver.findElement(By.cssSelector("#password")).clear();
driver.findElement(By.cssSelector("#username")).sendKeys("sans");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
//检查点击登陆之后是否登陆成功
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));
driver.findElement(By.cssSelector("#article_list_board_title"));
//页面url来检查是否登陆成功
String expect = driver.getCurrentUrl();
System.out.println(expect);
assert expect.equals("http://82.156.81.197:58080/index.html");
//截图
getScreenShot(getClass().getName());
// 回到登录界面
driver.navigate().back();
}
/**
* 检查登录功能---登录失败
*/
public void LoginFail() throws IOException {
driver.navigate().refresh();
//用户名存在, 密码错误
driver.findElement(By.cssSelector("#username")).sendKeys("sans");
driver.findElement(By.cssSelector("#password")).sendKeys("123"); //正确密码为:123456
driver.findElement(By.cssSelector("#submit")).click();
driver.navigate().refresh();
//用户名不存在, 密码非空
driver.findElement(By.cssSelector("#username")).sendKeys("aaa");
driver.findElement(By.cssSelector("#password")).sendKeys("123456");
driver.findElement(By.cssSelector("#submit")).click();
String curUrl = driver.getCurrentUrl();
getScreenShot(getClass().getName());
//如果点击登录后, 当前仍在登录界面, 则登录失败
assert curUrl.equals("http://82.156.81.197:58080/sign-in.html");
}
}
2.2.3 注册
RegisterPage类中包含了注册界面的相关测试方法,包括:
- RegisterPageRight():注册界面是否正常显示
- RegisterFail():注册失败,将用户名已存在以及密码和确认密码作为测试用例
- RegisterSuc():注册成功
RegisterPage类:
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.IOException;
import java.time.Duration;
public class RegisterPage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-up.html";
public RegisterPage() {
super(url);
}
/**
* 注册界面是否正常显示
*/
public void RegisterPageRight() {
//用户注册
driver.findElement(By.cssSelector("#signUpForm > div > h2"));
//昵称输入框
driver.findElement(By.cssSelector("#nickname"));
}
/**
* 注册失败, 以密码和确认密码不一致 & 用户名已存在 作为测试用例
*/
public void RegisterFail() throws InterruptedException {
driver.navigate().refresh();
//用户名已存在
driver.findElement(By.cssSelector("#username")).sendKeys("sans");
driver.findElement(By.cssSelector("#nickname")).sendKeys("sans");
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();
//刷新页面清空输入框
driver.navigate().refresh();
//密码和确认密码不一致
driver.findElement(By.cssSelector("#username")).sendKeys("papyrus");
driver.findElement(By.cssSelector("#nickname")).sendKeys("papyrus");
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();
String ele = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();
Thread.sleep(2000);
assert "请检查确认密码".equals(ele);
}
/**
* 注册成功
*/
public void RegisterSuc() throws IOException, InterruptedException {
//刷新页面, 清空输入框
driver.navigate().refresh();
driver.findElement(By.cssSelector("#username")).sendKeys("papyrus8");
driver.findElement(By.cssSelector("#nickname")).sendKeys("papyrus4");
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();
//点击注册后进入登录界面
//截图
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2")));
getScreenShot(getClass().getName());
//获取当前页面url
String ele = driver.getCurrentUrl();
//如果已经跳转至登录界面, 则注册成功
assert ele.equals("http://82.156.81.197:58080/sign-in.html");
}
}
2.2.4 论坛首页
HomePage类用来测试在登录状态和未登录状态下访问,结果如何,该类包括:
- HomePageFail():未登录状态下进入论坛首页
- HomePageSuc():登录后正常进入论坛首页
HomePage类:
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.io.IOException;
import java.time.Duration;
public class HomePage extends Utils {
public static String url = "http://82.156.81.197:58080/index.html";
public HomePage() {
super(url);
}
/**
* 未登录状态下, 进入论坛首页
*/
public void HomePageFail() throws IOException {
//直接跳转至用户登录界面
String curUrl = driver.getCurrentUrl();
assert curUrl.equals("http://82.156.81.197:58080/sign-in.html");
}
/**
* 登录后, 可以正常进入论坛首页
*/
public void HomePageSuc() throws IOException, InterruptedException {
Utils.login();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));
//检查Java板块是否存在
driver.findElement(By.cssSelector("#topBoardList > li:nth-child(2) > a > span.nav-link-title"));
//检查发布帖子按钮
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("#article_list_board_title"));
//截图
getScreenShot(getClass().getName());
}
}
2.2.5 发布帖子
PublishPage类中包含了发帖界面的相关测试方法,包括:
- publishPostPage():发帖界面是否正常显示
- publishPostSuc():测试正常发布帖子功能
- publishPostFail():测试发帖失败
PublishPage类:
import common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
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 PublishPage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-in.html";
public PublishPage() {
super(url);
}
/**
* 测试正常进入发布帖子界面
*/
public void publishPostPage() throws IOException, InterruptedException {
//先登录进入到论坛首页
Utils.login();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
wait.until(ExpectedConditions.presenceOfElementLocated(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")));
//Thread.sleep(1000);
//找到发布帖子的按钮
WebElement element = 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"));
element.click();
//进入页面后, 查看该页面的部分元素
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2")));
//发新帖
driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2"));
//发布按钮
driver.findElement(By.cssSelector("#article_post_submit"));
}
/**
* 测试正常发布帖子功能
*/
public void publishPostSuc() throws InterruptedException {
//点击板块下拉框
driver.findElement(By.cssSelector("#article_post_borad")).click();
//点击C++
driver.findElement(By.cssSelector("#article_post_borad > option:nth-child(2)")).click();
//点击标题, 输入内容
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题001");
//模拟输入内容
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//等待内容输入框加载完成
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i")));
WebElement element = driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i"));
element.click();
//将页面划至 发布 按钮处
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement publishButton = driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]"));
js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", publishButton);
//等待页面已经划至发布按钮处
Thread.sleep(1000);
publishButton.click();
//点击发布后, 回到论坛首页界面
String text = driver.findElement(By.cssSelector("#article_list_board_title")).getText();
assert "首页".equals(text);
}
/**
* 测试发布帖子失败
*/
public void publishPostFail() throws InterruptedException {
//找到发布帖子的按钮
WebElement element = 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"));
element.click();
//以内容为空作为测试用例
driver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题");
//将页面划至 发布 按钮处
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement publishButton = driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]"));
js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", publishButton);
//等待页面已经划至发布按钮处
Thread.sleep(1000);
publishButton.click();
//当前还在发帖界面则发帖失败
driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2"));
}
}
2.2.6 帖子详情
DetailsPage类中用来测试帖子详情页的相关功能,测试方法包括:
- DetailsPageRight():测试帖子详情页正常显示
- thumbsUp:测试点赞
- replyPost:测试回复帖子
- editPageRight:测试编辑帖子页面是否能够正常显示
- editSuc:测试成功编辑并发布帖子
DetailsPage类:
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 DetailsPage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-in.html";
public DetailsPage() {
super(url);
}
/**
* 测试帖子详情页正常显示
*/
public void DetailsPageRight() throws InterruptedException {
//先登录进入论坛首页
Utils.login();
//将页面划至 目标帖子 处
WebElement targetPost = Utils.slidePage("#artical-items-body > div:nth-child(5) > div > div.col > div.text-truncate > a");
//点击进入帖子详情页
targetPost.click();
driver.findElement(By.cssSelector("#details_article_title"));
driver.findElement(By.cssSelector("#details_btn_like_count"));
}
/**
* 测试点赞
*/
public void thumbsUp() throws IOException {
driver.findElement(By.cssSelector("#details_btn_like_count")).click();
getScreenShot(getClass().getName());
}
public void replyPost() throws InterruptedException, IOException {
WebElement target = Utils.slidePage("#article_details_reply > div.editormd-toolbar > div > ul > li:nth-child(12) > a");
target.click();
//页面滑动至回复按钮
target = Utils.slidePage("#details_btn_article_reply");
//点击回复
target.click();
getScreenShot(getClass().getName());
}
public void editPageRight() throws InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//将页面滑动至编辑按钮处
WebElement target = Utils.slidePage("#details_artile_edit");
//点击编辑进入博客编辑页
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#details_artile_edit")));
driver.findElement(By.cssSelector("#details_artile_edit")).click();
}
public void editSuc() throws InterruptedException {
WebElement title = driver.findElement(By.cssSelector("#edit_article_title"));
title.clear();
//修改标题
title.sendKeys("666");
//将页面滑动至提交按钮处
WebElement target = Utils.slidePage("#edit_article_submit");
target.click();
//点击提交后回到论坛首页
driver.findElement(By.cssSelector("#article_list_board_title"));
}
}
2.2.7 站内信
MessagePage类主要进行测试站内信相关功能,测试方法包括:
- postMessageRight:测试发送站内信界面是否正常显示
- postMessageSuc:测试成功发送站内信
- messageListRight:测试站内信列表界面正常显示
- replyMessage:测试回复站内信
MessagePage类:
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 MessagePage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-in.html";
public MessagePage() {
super(url);
}
/**
* 测试发私信界面是否正常显示
*/
public void postMessageRight() throws InterruptedException {
//先登录进入论坛首页
Utils.login();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));
WebElement target = Utils.slidePage("#artical-items-body > div:nth-child(7) > div > div.col > div.text-truncate > a");
//点击进入到帖子详情页
target.click();
//点击作者下面的发私信按钮, 出现发送站内信界面
driver.findElement(By.cssSelector("#btn_details_send_message")).click();
driver.findElement(By.cssSelector("#index_message_modal > div > div > div.modal-header > h5"));
driver.findElement(By.cssSelector("#btn_index_send_message"));
}
/**
* 测试成功发送私信
*/
public void postMessageSuc() throws IOException, InterruptedException {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//在发送私信窗口的输入框输入内容
driver.findElement(By.cssSelector("#index_message_receive_content")).sendKeys("你好,ff");
//点击发送按钮
Thread.sleep(1000);
driver.findElement(By.cssSelector("#btn_index_send_message")).click();
getScreenShot(getClass().getName());
}
public void messageListRight() throws InterruptedException, IOException {
WebElement target = Utils.slidePage("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a");
//点击右上角的铃铛
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();
//出现站内信列表
driver.findElement(By.cssSelector("#offcanvasEndLabel"));
getScreenShot(getClass().getName());
}
public void replyMessage() throws InterruptedException, IOException {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//找到某一条站内信, 点击
driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a")).click();
//点击回复按钮
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#btn_index_message_reply")));
WebElement replyButton = driver.findElement(By.cssSelector("#btn_index_message_reply"));
replyButton.click();
//向输入框输入内容
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_receive_content")));
driver.findElement(By.cssSelector("#index_message_reply_receive_content")).sendKeys("回复内容");
//点击发送
driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();
getScreenShot(getClass().getName());
}
}
2.2.8 我的帖子
MyPostPage类用来测试我的帖子界面是否正常显示,测试方法包括:
- MyPostPageRight:测试我的帖子界面是否正常显示
- DetailPageRight:测试帖子详情是否可以正常访问,详情页是否正常显示
MyPostPage类:
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 MyPostPage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-in.html";
public MyPostPage() {
super(url);
}
public void MyPostPageRight() throws IOException {
Utils.login();
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//点击右上角头像
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"));
element.click();
//点击我的帖子
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_user_profile")));
driver.findElement(By.cssSelector("#index_user_profile")).click();
//进入我的帖子界面
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#index_user_profile")));
//查看个人介绍
driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div.col-lg-4 > div > div > div > div > h2"));
//查看发私信
driver.findElement(By.cssSelector("#btn_profile_send_message")).click(); //发私信按钮
driver.findElement(By.cssSelector("#btn_index_send_message"));
// X
driver.findElement(By.cssSelector("#index_message_modal > div > div > div.modal-header > button")).click();
getScreenShot(getClass().getName());
}
public void DetailPageRight() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//点击进入帖子详情页
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();
//测试页面元素
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#details_article_title")));
driver.findElement(By.cssSelector("#details_article_title"));
driver.findElement(By.cssSelector("#details_btn_like_count"));
}
}
2.2.9 个人中心
PersonalCenterPage类用来测试个人中心界面相关功能,测试方法包括:
- PersonalCenterPageRight:个人中心界面是否正常显示
- modifyInfoSuc:测试修改个人信息
- modifyPasswordSuc:测试修改密码
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 PersonalCenterPage extends Utils {
public static String url = "http://82.156.81.197:58080/sign-in.html";
public PersonalCenterPage() {
super(url);
}
public void PersonalCenterPageRight() {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
//先登录进入论坛首页
Utils.login();
//点击右上角头像
driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.dropdown > a")).click();
//点击个人中心
driver.findElement(By.cssSelector("#index_user_settings")).click();
//检查页面是否正常加载
wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2")));
driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2"));
driver.findElement(By.cssSelector("#settings_nickname"));
}
public void modifyInfoSuc() throws InterruptedException, IOException {
//对于昵称,邮箱地址,电话,个人介绍, 任意一项都可以直接修改, 这里以昵称作为测试用例
driver.findElement(By.cssSelector("#setting_input_nickname")).clear();
//修改昵称
String oldNickname = driver.findElement(By.cssSelector("#settings_nickname")).getText();
//输入新昵称
driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(oldNickname + "1");
//点击修改
driver.findElement(By.cssSelector("#setting_submit_nickname")).click();
getScreenShot(getClass().getName());
//修改邮箱地址
WebElement email = Utils.slidePage("#setting_input_email");
email.clear();
email.sendKeys("6666@qq.com");
driver.findElement(By.cssSelector("#setting_submit_email")).click();
getScreenShot(getClass().getName());
//修改电话号码
WebElement phone = Utils.slidePage("#setting_input_email");
phone.clear();
phone.sendKeys("887654321");
driver.findElement(By.cssSelector("#setting_submit_phoneNum"));
getScreenShot(getClass().getName());
//修改个人简介
WebElement info = Utils.slidePage("#settings_textarea_remark");
info.clear();
info.sendKeys("今天也要加油!!!");
driver.findElement(By.cssSelector("#settings_submit_remark"));
getScreenShot(getClass().getName());
}
public void modifyPasswordSuc() throws InterruptedException, IOException {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
WebElement target = Utils.slidePage("#settings_submit_password");
driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("123456");
//模拟修改密码
driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123456");
driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123456");
//点击提交修改
driver.findElement(By.cssSelector("#settings_submit_password")).click();
//跳转至登录界面
getScreenShot(getClass().getName());
}
}
在RunTests类中执行所有测试方法:
import common.Utils;
import tests.*;
import java.io.IOException;
public class RunTests {
public static void main(String[] args) throws IOException, InterruptedException {
HomePage home = new HomePage();
//先测试未登录状态下进入论坛首页
home.HomePageFail();
//注意每个用例之间的依赖
LoginPage login = new LoginPage();
login.loginPageRight();
login.LoginSuc();
login.LoginFail();
//Thread.sleep(3000);
RegisterPage register = new RegisterPage();
register.RegisterPageRight();
register.RegisterFail();
register.RegisterSuc();
home.HomePageSuc();
PublishPage publish = new PublishPage();
publish.publishPostPage();
publish.publishPostSuc();
publish.publishPostFail();
DetailsPage details = new DetailsPage();
details.DetailsPageRight();
details.thumbsUp();
details.replyPost();
details.editPageRight();
details.editSuc();
MessagePage message = new MessagePage();
message.postMessageRight();
message.postMessageSuc();
message.messageListRight();
message.replyMessage();
MyPostPage myPost = new MyPostPage();
myPost.MyPostPageRight();
PersonalCenterPage person = new PersonalCenterPage();
person.PersonalCenterPageRight();
person.modifyInfoSuc();
person.modifyPasswordSuc();
Utils.driver.quit();
}
}
自动化测试全过程:
自动化测试
2.3 本次测试经验总结
- 一些需要被反复使用的方法,如创建驱动、截图等可以放在公共类中,避免代码冗长
- 由于测试时要考虑每个测试用例执行完后所处哪个页面以及页面的状态、登录状态、未登录状态,所以要调整好测试用例的执行顺序
- 像登录和注册这种界面需要反复向输入框中输入内容,所以在测试不同的用例之前要清空输入框或刷新页面
- 页面中一些元素虽然已经加载,但是并没有出现在当前界面中,所以需要先通过滑动使元素出现在界面中,才能进行交互
- 在自动化测试过程中报出异常后,如:NoSuchElementException、ElementNotInteractableException等,可以定位到报出异常的代码处,然后在代码之前加上Thread.sleep()强制等待再来运行代码,这么做之后异常通常就会消失,然后就可以加上显示等待或隐式等待,如果没有解决问题,可能是代码本身或测试用例顺序的问题
- 有时使用屏幕截图后,idea中没有生成图片,但点开文件夹后,图片是存在的,此时可以重新加载一下idea(右键包->点击Reload from Disk)
- 为了防止忘记释放驱动,可以将其放在finally语句中
三、总结
至此针对基于Spring+前后端分离的论坛系统项目测试完毕,本次测试覆盖所有页面,核心功能均可正常使用,部分功能存在缺陷,如:点赞没有限制、评论不支持楼中楼等,不影响用户体验;本次测试包括测试用例的编写、功能测试、自动化测试脚本的编写,功能测试过程中,通过手工执行用例完成,自动化测试方面,基于Selenium完成核心流程脚本开发,实现登录、发帖等操作的自动化回归测试,测试周期为2天
通过本次测试发现,项目还需要针对部分功能进行优化,自动化测试脚本的执行效率方面也需要优化和改进,本人通过此次测试积累了一定的测试经验,未来也会持续的学习测试相关知识