一、项目简介:
基于SpringBoot前后端分离-个人论坛系统
开发环境:JDK1.8 + IDEA + Maven + Git 技术栈:Spring + SpirngMVC + SpringBoot + Mybatis + MyriaDB(MySQL)
项目描述:个人论坛系统是一种在线社交平台,允许用户创建自己的帖子,同时可以与其他用户分享信息、讨论 话题、和互动交流。
主要的业务功能:用户注册,用户登录,论坛主界面(可以切换各个板块、显示当前用户信息、可以发布帖 子),帖子详情页(可以进行点赞、编辑、删除操作),用户中心页(可以进行用户信息修改操作,站内信(可 以收到他人的信息,也可以在帖子下面回复信息)。
主要的实现逻辑: 使用统一返回格式+全局错误信息定义处理前后端交互时的返回结果,使用实现全局异常处 理,使用拦截器实现用户登录校验,使用MybatisGeneratorConfig生成常用的增删改查方法,集成Swagger实现 自动生成API测试接口,使用jQuery完成AJAX请求,并处理HTML页面标签。
体验地址:http://123.57.66.157:58080/sign-in.html
二、测试方案:
1、功能测试:
1.1 测试环境:
操作系统:Windows 10专业版
项目运行环境:IIntelliJ IDEA Community Edition 2021.3.2、JDK1.8、MySQL5.7
浏览器:Chorme115.*
自动化脚本环境:IIntelliJ IDEA Community Edition 2021.3.2
访问链接:Pharaoh论坛 - 用户登录
测试技术: 主要手工进行单元测试和自动化测试
测试人员: 自己
1.2 测试用例:
1.2.1 功能测试用例:
1.2.2 非功能测试用例:
2、自动化测试:
2.1 测试之前准备:
(1)向pom.xml中导入相关依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.1</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
(2)创建驱动初始化和结束类
//初始化和结束
public class InitAndEnd {
static WebDriver webDriver;
@BeforeAll
static void Init() {
webDriver = new ChromeDriver();
}
@AfterAll
static void End() {
webDriver.quit();
}
}
(3)创建用于自动化测试类
2.2 注册页面测试:
代码思想:注册后查看当前URL与登录页面URL是否对应
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class ForumTestCases extends InitAndEnd{
@Order(1)
@ParameterizedTest
@CsvFileSource(resources = "RegisterTest.csv")
void register(String username,String nickname,String password,String repeatpassword,String exp_url) throws InterruptedException {
// 打开注册页面
webDriver.get("http://123.57.66.157:58080/sign-up.html");
// 输入用户名
webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 输入昵称
webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 输入密码
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 确认密码
webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(repeatpassword);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
//同意论坛协议
webDriver.findElement(By.cssSelector("#policy")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
//点击注册按钮
webDriver.findElement(By.cssSelector("#submit")).click();
Thread.sleep(1000); // 等待浏览器页面刷新
String cur_url = webDriver.getCurrentUrl();
Assertions.assertEquals(exp_url,cur_url);
}
}
情况1:用户名和密码均合法,成功跳转至登录界面
情况2:用户名重复,密码输入合法。
情况3:用户名输入合法,两次密码不一致
2.3 登录页面测试:
代码思想:登录后查看当前URL与论坛主页URL是否对应。
@Order(2)
@ParameterizedTest
@CsvSource(value = "Pharaoh, 123,'http://123.57.66.157:58080/index.html'")
void Login(String username,String password,String exp_url) throws InterruptedException {
webDriver.get("http://123.57.66.157:58080/sign-in.html");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 输入用户名
webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 输入密码
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 点击提交
webDriver.findElement(By.cssSelector("#submit")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
Thread.sleep(1000); // 显示等待,等待弹窗出现
String cur_url = webDriver.getCurrentUrl();
Assertions.assertEquals(exp_url,cur_url);
}
情况1:用户名和密码输入均合法,页面成功跳转至论坛主页。
情况2:用户名或者密码输入错误,页面提示参数校验失败。
情况3:用户名或者密码为空,页面提示用户名或密码不得为空。
2.4 论坛主页显示:
代码思想:登录后进入论坛主页,查看“首页”元素是否存在,查看是否含有“发布帖子”按钮并点击查看能否正确跳转至帖子编辑页。
@Order(3)
@ParameterizedTest
@CsvSource("首页,发新贴")
void index(String exp_text, String exp_text2) throws InterruptedException {
String cur_text = webDriver.findElement(By.cssSelector("#article_list_board_title")).getText();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
Assertions.assertEquals(exp_text, cur_text);
webDriver.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();
Thread.sleep(1000);
String cur_text2 = webDriver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2")).getText();
Assertions.assertEquals(exp_text2, cur_text2);
}
情况1:未登录状态下访问论坛主页,强制重定向回登录界面。
情况2:登录状态下,正常访问。
注:由于设置了登录拦截器,除登录页面和注册页面不拦截以外,后续所有操作均需在登录情况下访问,于是不再赘述。
2.5 发布帖子测试
代码思想:选择板块(默认为Java板块),填写标题,填写正文,测试点击发布帖子按钮能否正常发送帖子,并返回到论坛主界面
@Order(4)
@Test
void Publish() throws InterruptedException {
webDriver.findElement(By.cssSelector("#article_post_title")).sendKeys("自动化测试标题");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.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")).sendKeys("自动化测试内容");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#article_post_submit")).click();
Thread.sleep(1000);
String text = webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).getText();
Assertions.assertEquals("自动化测试标题",text);
}
情况1:帖子标题和帖子内容均输入合法,成功发布
情况2:帖子标题或帖子内容为空,提示 帖子标题或帖子内容不得为空
经实测此处有BUG,webDriver在定位到帖子内容时候失败,导致写入帖子内容失败。
2.6 帖子详情界面测试
代码思想:点击帖子标题进入详情页后,查看当前标题是否与首页页面的帖子标题相同,并会显示帖子创建时间、点赞数、访问量、回复数
@Order(5)
@Test
void Detail() {
String a_text = webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).getText();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
String c_text = webDriver.findElement(By.cssSelector("#details_article_content_title")).getText();
Assertions.assertEquals(a_text,c_text);
webDriver.findElement(By.cssSelector("#details_btn_like_count")).click();
}
情况1:进入详情页面,如果是该文作者,则会显示点赞、编辑、删除按钮。
情况2:进入详情页面,如果不是该文作者,则只会显示点赞按钮。
2.7 删除帖子测试
代码思想:点击删除按钮,查看当前帖子是否被成功删除。
@Order(6)
@Test
void Delete() throws InterruptedException {
webDriver.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();
Thread.sleep(1000);
webDriver.findElement(By.cssSelector("#details_artile_delete")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
String text = webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).getText();
Assertions.assertNotEquals("自动化测试标题",text);
}
情况1:是该文作者,点击删除按钮,提示删除成功,返回论坛主页。
情况2:不是该文作者,界面上没有删除按钮,同时也无权限删除。
2.8 个人中心测试
代码思想:
在论坛主页,点击用户头像显示下拉框,分别测试用户中心和我的帖子是否能跳转到正确的页面。
@Order(7)
@Test
void Personal() {
String text = webDriver.findElement(By.cssSelector("#index_nav_nickname")).getText();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#index_user_settings")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
String cur_text = webDriver.findElement(By.cssSelector("#settings_nickname")).getText();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
Assertions.assertEquals(text,cur_text);
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#index_user_profile")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
String title = webDriver.findElement(By.xpath("//*[@id=\"profile_article_body\"]/li[3]/div[2]/div/div/div/div/div[1]")).getText();
Assertions.assertEquals("欢迎来到Pharaoh论坛",title);
}
情况1:跳转成功。
2.9 修改个人信息测试
代码思想:在个人主页,点击修改昵称、邮箱地址、电话号码能否成功修改信息。
@Order(8)
@Test
void modify() {
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#index_user_settings")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#setting_input_nickname")).clear();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys("测试2.0");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.navigate().refresh();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
String text = webDriver.findElement(By.cssSelector("#index_nav_nickname")).getText();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
Assertions.assertEquals("测试2.0",text);
}
情况1:当修改用户为当前用户时,用户信息修改成功。
情况2:当修改用户补位当前用户时,用户信息无法修改。
2.10 退出测试
@Order(10)
@Test
void logout() throws InterruptedException {
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
webDriver.findElement(By.cssSelector("#index_user_logout > span")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES);
Thread.sleep(3000);
String currentUrl = webDriver.getCurrentUrl();
Assertions.assertEquals("http://123.57.66.157:58080/sign-in.html",currentUrl);
}
情况1:点击退出按钮,注销成功,界面跳转到登录页面。