目录
一、项目介绍
基于Spring前后端分离的博客论坛系统,实现了注册、登录、显示帖子、编辑帖子、删除帖子、回复帖子、点赞帖子,修改个人信息等功能,并将其部署到云服务器上。
要点:
1、使用统⼀返回格式+全局错误信息定义处理前后端交互时的返回结果;
2、使用@ControllerAdvice+@ExceptionHandler实现全局异常处理;
3、使用拦截器实现用户登录校验;
4、集成Swagger实现⾃动⽣成API测试接口;5、对密码进行加密处理。
访问地址:http://124.71.152.247:8081/sign-in.html
二、测试计划
1、功能测试
(1)测试环境:
操作系统:Windows 10家庭版
项目运行环境:IIntelliJ IDEA Community Edition 2022.1.4、JDK1.8、MySQL5.7
浏览器:Chorme、Edge、FireFox、QQ浏览器
自动化脚本环境:IIntelliJ IDEA Community Edition 2022.1.4
访问链接:http://124.71.152.247:8081/index.html
测试技术: 主要手工进行单元测试和自动化测试
测试人员: 本人
(2)测试用例编写
功能测试:

非功能测试点:

(3)部分功能测试
对注册页面进行的测试
场景1:输入用户名存在,密码与确认密码一致,点击注册
预期结果:提示用户已经存在
实际结果:提示用户已经存在,与预期结果一致。
场景2:输入用户名不存在,密码与却密码一致,点击注册
预期结果:注册成功,跳转回登录界面
实际结果:注册成功,跳转回登录界面,与预期结果一致。
对登录页面进行的测试
场景1:输入用户名存在,密码与确认密码一致,点击登录
预期结果:登录成功,跳转到首页博客列表页面
实际结果:与预期结果一致。
场景2:输入用户名存在,密码与确认密码不一致,点击登录
预期结果:登录失败,给出错误提示
实际结果:登录失败,给出错误提示。
……
对首页进行的测试
场景1:未登录状态下,点击首页
预期结果:跳转回登录界面
实际结果:跳转回登录界面,与预期结果一致。
场景2:登录状态下,点击“首页”
预期结果:导航栏显示所有的版块名,下方显示所有帖子列表,右上方显示登录用户信息。
实际结果:与预期结果一致。
场景3:登录状态下,点击导航栏处的版块名“C++”
预期结果:下方显示C++名称,该版块下的帖子数量,版块下的所有帖子列表,右上方显示登录用户信息。
实际结果:与预期结果一致。
场景4:登录状态下,在搜索框输入关键字“数据库”搜索
预期结果:下方显示帖子正文中所有存在“数据库”这三个字的帖子;
实际结果:刷新回到首页界面,与预期不符。不支持搜索功能。
场景5:登录状态下,点击“月亮”按钮
预期结果:进入夜间模式的切换
实际结果:进入夜间模式的切换,与预期相符。
场景6:登录状态下,点击“发布帖子”按钮
预期结果:进入博客编辑页面,版块名默认选择Java
实际结果:与预期相符。
……
对编辑页面进行的测试
场景1:未登录状态下,进入编辑页面
预期结果:跳转回登录界面
实际结果:跳转回登录界面,与预期结果一致。
场景2:登录状态下,不输入帖子标题,输入帖子内容,点击发布
预期结果:给出提示:请输入帖子标题
实际结果:与预期相符。
场景3:登录状态下,输入帖子标题,不输入帖子内容,点击发布
预期结果:给出提示:请输入帖子内容
实际结果:与预期相符。
场景4:登录状态下,输入帖子标题,输入帖子内容,点击发布
预期结果:编辑成功,跳转回首页,最上方显示刚发布的帖子信息
实际结果:与预期相符。
……
对帖子详情页面进行的测试
场景1:未登录状态下,点击首页下的任意一条帖子内容
预期结果:跳转回登录界面
实际结果:跳转回登录界面,与预期结果一致。
场景2:登录状态下,点击首页下的一条帖子内容“西安”
预期结果:跳转到该帖子详情页面
实际结果:与预期相符。
场景3:登录状态下,点击首页下的一条帖子内容“西安”(帖子作者“小狐狸”,当前登录作者“小星星”)
预期结果:跳转到该帖子详情页面,最上方显示帖子信息,左侧显示帖子作者信息,下方显示该帖子的内容,下方只显示点赞按钮。
实际结果:与预期相符。
场景4:登录状态下,下方点赞按钮
预期结果:上方显示的点赞数加1
实际结果:与预期相符。
场景5:登录状态下,点击首页下的一条帖子内容“123”(帖子作者“小星星”,当前登录作者“小星星”)
预期结果:跳转到该帖子详情页面,最上方显示帖子信息,左侧显示帖子作者信息,下方显示该帖子的内容,下方显示点赞按钮,删除按钮、编辑按钮。
实际结果:与预期相符。
场景6:登录状态下,点击首页下的一条帖子内容“123”,观察访问数变化
预期结果:跳转到该帖子详情页面,最上方显示帖子信息中的访问数+1
实际结果:与预期相符。
场景7:登录状态下,点击发私信按钮,不输入文本内容,点击“发送”
预期结果:给出警告提示:请输入要发送的内容
实际结果:与预期相符。
场景8:登录状态下,点击发私信按钮,输入文本内容,点击“发送”
预期结果:给出成功提示,发送成功
实际结果:与预期相符。
场景9:登录状态下,在下方的回复框中不输入文本内容,点击“回复”
预期结果:给出警告提示,请输入回复内容
实际结果:与预期相符。
场景10:登录状态下,在下方的回复框中输入文本内容,点击“回复”
预期结果:给出成功提示,同时下方显示回复内容。
实际结果:与预期相符。
……
对个人中心页面进行的测试
场景1:未登录状态下,点击首页下的任意一条帖子内容
预期结果:跳转回登录界面
实际结果:跳转回登录界面,与预期结果一致。
场景2:登录状态下,点击“我的帖子”
预期结果:下方显示该登录用户的所有帖子信息
实际结果:与预期相符。
场景3:登录状态下,点击“个人中心”
预期结果:下方显示该登录用户的所有信息
实际结果:与预期相符。
场景4:登录状态下,“修改头像”
预期结果:打开 电脑,上传本地图片并更新头像。
实际结果:打开电脑,上传本地图片,但是没有反应。与预期不符。(不支持修改头像)
场景5:登录状态下,“修改昵称”
预期结果:输入修改后的昵称,并刷新成功
实际结果:与预期一致。
场景5:登录状态下,“修改密码”:原密码错误,新密码和确认密码一致,点击修改密码
预期结果:给出警告提示:原密码有误。
实际结果:输出后端具体代码信息,与预期不一致。
场景6:登录状态下,“修改密码”:原密码正确,新密码和确认密码不一致,点击修改密码
预期结果:给出警告提示:两次输入的密码不一致。
实际结果:与预期一致。
场景7:登录状态下,“修改密码”:原密码正确,新密码和确认密码一致,点击修改密码
预期结果:跳转回登录界面,要求重新登录
实际结果:与预期一致。
……
这里只给出部分测试,其他功能测试就不一一展示了。
2、自动化测试
🍑注册页面测试
验证注册成功的情况
场景1:注册用户名在数据库不存在,昵称,两次密码一致,注册成功,跳转回登录界面。
/** * 场景1:不存在的用户名,昵称,两次密码一致 */ @Order(1) @ParameterizedTest @CsvSource(value = "apple,apple,123,123") void Register(String username, String nickname,String password1,String password2) throws InterruptedException, IOException { // 打开注册页面 webDriver.get("http://124.71.152.247:8081/sign-in.html"); //点击注册按钮 webDriver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click(); 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("#nickname")).sendKeys(nickname); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); // 输入密码 webDriver.findElement(By.cssSelector("#password")).sendKeys(password1); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); // 确认密码 webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(password2); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); //点击复选框 webDriver.findElement(By.cssSelector("#policy")).click(); // 点击提交 webDriver.findElement(By.cssSelector("#submit")).click(); Thread.sleep(1000); // 显示等待 // 注册成功之后,判断是否会跳转回登录界面 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); // 进行截图,看当前是否跳转到了登录界面 webDriver.manage().timeouts().implicitlyWait(300, TimeUnit.MINUTES); Assertions.assertEquals(expect, actual); System.out.println("注册成功"); // 进行截图,看当前是否跳转到了登录界面 // 程序执行的速度和页面渲染的速度 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "RegisterTest.png"; FileUtils.copyFile(srcFile, new File(fileName)); Thread.sleep(1000); // 显示等待 //因为我们要测试多个账号,所有在一个账号检测完了后,还需要回退到登录界面 webDriver.navigate().back(); }
验证注册失败的情况
场景2:注册用户名在数据库存在,昵称,两次密码一致,注册失败,获取警告框信息。
代码同上。测试结果

🍑登录界面测试
登录成功测试
场景1:测试用户名正确,密码正确,登录成功
/** * 场景1:用户名和密码都正确 */ @Order(1) @ParameterizedTest @CsvSource(value = "cherry, 123") void Login1(String username, String password) throws InterruptedException, IOException { // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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 expect = "http://124.71.152.247:8081/index.html"; String actual = webDriver.getCurrentUrl();// // // 进行截图,看当前是否跳转到了登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); // 查看当前的url是否在博客详情页面 // 进行截图,看当前是否跳转到了登录界面 // 程序执行的速度和页面渲染的速度 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "loginTest.png"; FileUtils.copyFile(srcFile, new File(fileName)); Thread.sleep(1000); // 显示等待,等待弹窗出现 //因为我们要测试多个账号,所有在一个账号检测完了后,还需要回退到登录界面 webDriver.navigate().back(); }
登录失败测试
场景2:测试用户名正确,密码错误,登录失败
@Order(2) @ParameterizedTest @CsvSource(value = "cherry1, 123") void Login2(String username, String password) throws InterruptedException, IOException { // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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 msg = webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText(); System.out.println(msg); }
🍑显示博客列表测试
未登录状态下测试
场景1:未登录状态下进入博客列表页,直接跳转回登录界面。测试通过。
/** * 场景1:未登录状态下,进入博客列表页,是否跳转回登录页面 */ @Order(1) @Test void BlogList1() throws InterruptedException, IOException { //1-不登录,直接打开博客显示列表页 webDriver.get("http://124.71.152.247:8081/index.html"); //获取当前的url地址 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); //判断是否跳转到登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "BlogListFailed.png"; FileUtils.copyFile(srcFile, new File(fileName)); }
未登录,直接跳转回登录界面
登录状态下测试
场景2:登录后进入博客列表页,查看“首页”元素是否存在,查看是否含有“发布帖子”按钮。
/** * 场景2:登录状态下,进入博客列表页,是否正确显示帖子相应的控件信息 */ @Order(2) @ParameterizedTest @CsvSource(value = "cherry, 123") void BlogList2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); //2-查看页面的文本内容显示是否正确 String expect1 = "首页"; System.out.println(); String actual1 = webDriver.findElement(By.cssSelector("#nav_board_index > a > span.nav-link-title")).getText(); Assertions.assertEquals(expect1, actual1); // 断言 //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "BlogListSuccess.png"; FileUtils.copyFile(srcFile, new File(fileName)); //3-查看是否有发布帖子按钮,并点击 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 expectUrl = "http://124.71.152.247:8081/index.html"; String actualUrl = webDriver.getCurrentUrl(); Assertions.assertEquals(expectUrl, actualUrl); // 断言 System.out.println("跳转到边界帖子页面"); }

🍑 发布帖子测试
未登录状态下测试
场景1:未登录状态下发布帖子,直接跳转回登录界面。
/** * 场景1:未登录状态下,是否跳转回登录页面 */ @Order(1) @Test void WriteBlog1() throws InterruptedException, IOException { //1-不登录,直接打开博客编辑页 webDriver.get("http://124.71.152.247:8081/index.html"); //获取当前的url地址 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); //判断是否跳转到登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "WriteBlogFailed.png"; FileUtils.copyFile(srcFile, new File(fileName)); }
登录后测试
场景2:登录后,输入帖子标题,不输入帖子内容,点击发布按钮,给出提示信息。
/** * 场景2:登录状态下 */ @Order(2) @ParameterizedTest @CsvSource(value = "cherry, 321") void WriteBlog2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); //场景2:输入标题,内容为空,点击发布帖子按钮,获取警告信息 //2-点击 发布帖子按钮#article_post_submit 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(); //场景1:输入标题 webDriver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题"); Thread.sleep(1000); //不输入内容 //点击提交按钮 webDriver.findElement(By.cssSelector("#article_post_submit")).click(); //获取警告框信息 System.out.println(webDriver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div")).getText()); // 截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "WriteBlogFailed.png"; FileUtils.copyFile(srcFile, new File(fileName)); }
🍑帖子详情页测试
未登录状态下
场景1:未登录状态下,进入帖子详情页,直接跳转回登录界面。
/** * 场景1:未登录状态下,进入博客详情页,是否跳转回登录页面 */ @Order(1) @Test void BlogDetail1() throws InterruptedException, IOException { //1-不登录,直接打开博客详情页 webDriver.get("http://124.71.152.247:8081/index.html"); //获取当前的url地址 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); //判断是否跳转到登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "BlogListFailed.png"; FileUtils.copyFile(srcFile, new File(fileName)); }
登录状态下
/** * 场景2:登录状态下,进入博客详情页,是否正确显示对应帖子的信息 */ @Order(2) @ParameterizedTest @CsvSource(value = "cherry, 123") void BlogList2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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(); Thread.sleep(5000); // 2-场景1:点击帖子内容"西安",博客作者与登录作者不一致,只显示点赞按钮 webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(3) > div > div.col > div.text-truncate > a > strong")).click(); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.MINUTES); //是否跳转到 帖子详情页 //获取当前的url地址 String expect = "http://124.71.152.247:8081/index.html"; String actual = webDriver.getCurrentUrl(); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //帖子详情页是否含有 帖子 标题 System.out.println(webDriver.findElement(By.cssSelector("#details_article_content_title")).getText()); Thread.sleep(5000); //帖子内容 System.out.println(webDriver.findElement(By.cssSelector("#h1-u897Fu5B89u5927u5510u4E0Du591Cu57CE")).getText()); Thread.sleep(1000); //帖子作者 System.out.println(webDriver.findElement(By.cssSelector("#article_details_author_name")).getText()); Thread.sleep(1000); //点赞按钮 webDriver.findElement(By.cssSelector("#details_btn_like_count")).click(); Thread.sleep(1000); // 截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "BlogDetailSuccess1.png"; FileUtils.copyFile(srcFile, new File(fileName)); //2-场景2:点击帖子内容"测试",博客作者与登录作者一致,显示点赞按钮、编辑按钮,删除按钮 // 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); // //是否跳转到 帖子详情页 // //获取当前的url地址 // String expect2 = "http://124.71.152.247:8081/index.html"; // String actual2 = webDriver.getCurrentUrl(); // webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); // Assertions.assertEquals(expect2, actual2); // //帖子详情页是否含有 帖子 标题 // System.out.println(webDriver.findElement(By.cssSelector("#details_article_content_title")).getText()); // Thread.sleep(1000); // //帖子内容 // System.out.println(webDriver.findElement(By.cssSelector("#details_article_content > p")).getText()); // Thread.sleep(1000); // //帖子作者 // System.out.println(webDriver.findElement(By.cssSelector("#article_details_author_name")).getText()); // Thread.sleep(1000); // //点赞按钮 // webDriver.findElement(By.cssSelector("#details_btn_like_count")).click(); // //编辑按钮 // webDriver.findElement(By.cssSelector("#details_artile_edit")); // //删除按钮 // 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")); // Thread.sleep(1000); // System.out.println("测试成功2"); // // //截图 // File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); // String fileName = "BlogDetailSuccess2.png"; // FileUtils.copyFile(srcFile, new File(fileName)); }
场景1:登录后,登录用户与帖子作者不一致,获取帖子标题、帖子内容、帖子作者、点赞按钮。


场景2:登录后,登录用户与帖子作者一致,获取帖子标题、帖子内容、帖子作者、点赞按钮、编辑按钮、删除按钮。


🍑删除帖子测试
登录状态下测试
场景:登录后,进入帖子详情页,点击删除按钮,删除帖子成功,成功跳转回帖子列表页面。
/** * 场景2:登录状态下,进入博客详情页,是否正确显示对应帖子的信息,点击删除按钮并删除 */ @Order(2) @ParameterizedTest @CsvSource(value = "cherry, 123") void BlogList2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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(); Thread.sleep(5000); //2-场景2:点击帖子内容"测试",博客作者与登录作者一致,显示点赞按钮、编辑按钮,删除按钮 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); //是否跳转到 帖子详情页 //获取当前的url地址 String expect2 = "http://124.71.152.247:8081/index.html"; String actual2 = webDriver.getCurrentUrl(); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect2, actual2); //删除按钮 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); //判断是否跳转回博客列表页面 //是否跳转到 帖子详情页 //获取当前的url地址 String expect1 = "http://124.71.152.247:8081/index.html"; String actual1 = webDriver.getCurrentUrl(); webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect1, actual1); System.out.println("帖子删除成功"); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "BlogDeleteSuccess1.png"; FileUtils.copyFile(srcFile, new File(fileName)); }


🍑个人中心显示
未登录测试
未登录状态下,进入博客列表页,点击我的帖子(都走不到这一步),跳转回登录页面。
登录状态下测试
场景:登录状态下,进入博客列表页,点击我的帖子,跳转到个人中心页面,显示用户昵称等信息。
/** * 场景2:登录状态下,进入博客列表页,点击我的帖子,跳转到个人中心页面 */ @Order(2) @ParameterizedTest @CsvSource(value = "cherry, 123") void BlogList2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); //2-点击我的帖子 webDriver.findElement(By.cssSelector("#index_nav_avatar")).click(); Thread.sleep(1000); webDriver.findElement(By.cssSelector("#index_user_profile")).click(); Thread.sleep(1000); //是否有用户昵称 webDriver.findElement(By.cssSelector("#profile_nickname")); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "CenterInfoSuccess.png"; FileUtils.copyFile(srcFile, new File(fileName)); }


🍑显示个人信息并修改
未登录测试
场景1:未登录状态下,进入博客列表页,点击用户头像下的个人中心(都走不到这一步),跳转回登录页面。
登录显示个人信息测试
场景2:登录后点击用户头像下的个人中心,输入新昵称并修改,获取新昵称观察是否显示成功。
场景3:登录后点击用户头像下的个人中心,输入新密码并修改,其中两次密码一致,输入原密码也正确,观察是否跳转回登录界面。
@Order(2) @ParameterizedTest @CsvSource(value = "cherry, 123") void BlogList2(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); //2-点击我的帖子 webDriver.findElement(By.cssSelector("#index_nav_avatar")).click(); Thread.sleep(1000); webDriver.findElement(By.cssSelector("#index_user_settings")).click(); Thread.sleep(1000); //是否有用户昵称 webDriver.findElement(By.cssSelector("#settings_nickname")); //是否有“昵称”这两个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(4)")); //是否有“邮箱地址”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(7)")); //是否有“电话号码”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(10)")); //是否有“修改密码”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(13)")); //是否有“提交修改”按钮#settings_input_passwordRepeat webDriver.findElement(By.cssSelector("#settings_submit_password")); Thread.sleep(1000); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "CenterInfoListSuccess.png"; FileUtils.copyFile(srcFile, new File(fileName)); }


登录后修改昵称测试
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CenterInfoListTest extends InitAndEnd { /** * 场景1:用户名和密码都正确 */ @Order(1) @ParameterizedTest @CsvSource(value = "cherry, 123") void Login1(String username, String password) throws InterruptedException, IOException { // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); } /** * 场景2:登录状态下,进入博客列表页,点击个人中心,跳转到个人中心页面 */ @Order(2) @Test void BlogList2() throws InterruptedException, IOException { //2-点击我的帖子 webDriver.findElement(By.cssSelector("#index_nav_avatar")).click(); Thread.sleep(1000); webDriver.findElement(By.cssSelector("#index_user_settings")).click(); Thread.sleep(1000); //是否有用户昵称 webDriver.findElement(By.cssSelector("#settings_nickname")); //是否有“昵称”这两个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(4)")); //是否有“邮箱地址”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(7)")); //是否有“电话号码”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(10)")); //是否有“修改密码”这几个字 webDriver.findElement(By.cssSelector(" #bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > h3:nth-child(13)")); //是否有“提交修改”按钮#settings_input_passwordRepeat webDriver.findElement(By.cssSelector("#settings_submit_password")); Thread.sleep(1000); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "CenterInfoListSuccess1.png"; FileUtils.copyFile(srcFile, new File(fileName)); //3-修改昵称 //清除昵称的文本内容 webDriver.findElement(By.cssSelector("#setting_input_nickname")).clear(); //输入要修改的内容 webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys("newCherry"); //点击修改按钮 webDriver.findElement(By.cssSelector("#setting_submit_nickname")).click(); Thread.sleep(1000); //再次获取昵称,判断是不是修改后的昵称名 String actualNickName = webDriver.findElement(By.cssSelector("#settings_nickname")).getText(); Thread.sleep(1000); String exceptNickName = "newCherry"; Assertions.assertEquals(actualNickName, exceptNickName); // 断言 System.out.println("昵称修改成功!"); //截图 File srcFile1 = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName1 = "CenterInfoListSuccess2.png"; FileUtils.copyFile(srcFile1, new File(fileName1)); } }


登录后修改密码测试
//4-修改密码:原密码123正确,两次新密码321也一致 //输入原密码 webDriver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("123"); //输入新密码 webDriver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("321"); //输入确认密码 webDriver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("321"); //点击 提交修改 按钮 webDriver.findElement(By.cssSelector("#settings_submit_password")).click(); Thread.sleep(1000); //判断是否返回登录界面 //获取当前的url地址 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); //判断是否跳转到登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //截图 File srcFile2 = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName2 = "CenterInfoListSuccess3.png"; FileUtils.copyFile(srcFile2, new File(fileName2));
🍑退出测试
场景:登录后,点击用户头像下的退出按钮,跳转回登录界面,退出成功。
@Order(1) @ParameterizedTest @CsvSource(value = "cherry, 321") void LoginOut1(String username, String password) throws InterruptedException, IOException { //1-登录 // 打开登录页面 webDriver.get("http://124.71.152.247:8081/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); //2-点击我的帖子 webDriver.findElement(By.cssSelector("#index_nav_avatar")).click(); Thread.sleep(1000); //点击退出按钮 webDriver.findElement(By.cssSelector("#index_user_logout")).click(); Thread.sleep(1000); //获取当前的url地址 String expect = "http://124.71.152.247:8081/sign-in.html"; String actual = webDriver.getCurrentUrl(); //判断是否跳转到登录界面 webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); Assertions.assertEquals(expect, actual); //截图 File srcFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); String fileName = "LoginOutSuccess.png"; FileUtils.copyFile(srcFile, new File(fileName)); }

3、性能测试
对登录界面进行性能测试。
VUG录制脚本
Action() { web_url("sign-in.html", "URL=http://124.71.152.247:8081/sign-in.html", "Resource=0", "Referer=", "Snapshot=t1.inf", "Mode=HTML", EXTRARES, "Url=/sign-in.html", ENDITEM, LAST); web_add_cookie("__huid=119NsjOYxU6mdbuaWxJs2RsDkAbqvUbWoATer/xQupFzE=; DOMAIN=cloud.browser.360.cn"); lr_think_time(7); web_custom_request("sea", "URL=http://cloud.browser.360.cn/hp/sea", "Method=POST", "Resource=0", "Referer=", "Snapshot=t2.inf", "Mode=HTML", "EncType=text/plain", "Body=WQF5sG2A3G87Di1j/9lVU6tGpUxjbi8h9dOSKi0nx0bBqI3NhNjo%2BhJjBEgGG7vJpmWkPaE8H7VriNz9f/uQIcxcAQMslbR5BrNQFX%2BaLkMlu51TJYzYI03Ix9kMz7AGv5atKy3kF9YF86MaiowJ%2B88BdH2zke9LfjkSSOnDIB9pCrQEMhm%2BWy2gk8ziS7Izk7GF/IvqUyc5GvTM4PFYu3hjejRzs4fV", LAST); web_custom_request("safe_update", "URL=http://vconf.f.360.cn/safe_update", "Method=POST", "Resource=0", "RecContentType=application/octet-stream", "Referer=", "Snapshot=t3.inf", "Mode=HTML", "BodyBinary=\\x0E\\x06$!\\x01\\x08$\\xB8j\\xC4\\x00\\x00\\x00\\x00\\xF8\\xD7\\xFB\\xE5\\xFD\\x9A/\\xC2&\\x90\\x94$N\\x85R\\x1Br$2>b\\xB8\\x84\\xE5\\xE6\\xF8\\x18\\xF2\\xC1,\\x88\\xFC\t\\xF9\\x84\\xB1Ls)q\n\\x05\\x8Bw\\x8B,\\x066\\xE1\\xE50\\x11\\xB9\\xAF\\xD5!\\x18\\x14\\x8C,\\x86I_\\x1C\\xE81\\xFAE\\xB8L\\xD0\\x95\\x03\\x8E\\xCB\\xB9}\\xFCi,\\x18F\\xAD\\xF4\r\\x82'IqH\\xFD\\xF8\\x0CIe\\x84\\x1B\\xF8\\x00\\x9C\\x0Be]" "#\\xD0f\\x82\\xA6\\xE2c\\x7F\\xCC\\xC9.\\xE2\\x03\\xDB\\xBF\\xF5\\xBF3Mfu\\xF2\\xF2Hz\\x1B\\x02M\\xB7;\\xC9U\\xF9\\xED\\x90\\x06\\xB7\\x19\\xA1\\x96\\x98S\\xCF\\xB2\\x00LO\"\\xDD\\xD4S\\x11Zp\\xB1\\x9B\\x7F\\xDA\\x9C\\x03|\\x9B\\xCB\\xE9\\x96-T.3\\xF4\\xF8\\xE7O2DK\\x00\\xA0J\\xC5\\x06\\x9Cb \\xC8\\xA8\\xDF\\xBB3\\xA5\\x82\\x902\\x82\\xF4\\xB7nH\\x90\\xCAN<\\x07\\xC0\\x074l>4=\\x12\\x8D\\x8E9\\xDB}\\xA7\\xDA\\x05e\\x085V^#~\\x03%\\x07\\xD0\\xD4N\\x9C\\x98b\\x93g\\x84z\\xE2" "[x\\xB3E\\x10\\xDA\\x86w3fpk:\\x0E?B?_\\xF9\\xBB\\x8D(@\\xE9\\x1D\\x02D\\xFB\\xEC\\xFE\\xE8\\xA88\\xB6-\\xBA$6\\x8D\\x00\\x04\\xBC\\x06\\xFFN", EXTRARES, "Url=http://t.wg.360-api.cn/api/helpgame?app=hotrank", "Referer=", ENDITEM, "Url=http://t.wg.360-api.cn/ap/tips/browse?cver=&mid=9584dcf1d21227deae8dfc79c880b3cc", "Referer=", ENDITEM, "Url=http://t.wg.360-api.cn/ap/tips/guess?sence=browse_ai&mid=9584dcf1d21227deae8dfc79c880b3cc&cver=9.1.2.1018&gver=", "Referer=", ENDITEM, "Url=http://cseupdate.360safe.com/formal/360chrome.cab?ver=13.5.2044.0&mid=9584dcf1d21227deae8dfc79c880b3cc&guid=9584dcf1d21227deae8dfc79c880b3cc&pid=360CE", "Referer=", ENDITEM, LAST); web_add_cookie("__huid=11jHmC5E3q3/A2xfpl7ar/4QDK+68TzjQe82izYITuvsI=; DOMAIN=browser.360.cn"); web_custom_request("crx_game_2.html", "URL=http://browser.360.cn/se/config/crx_game_2.html", "Method=GET", "Resource=0", "RecContentType=text/html", "Referer=", "Snapshot=t4.inf", "Mode=HTML", LAST); web_add_cookie("__huid=11jHmC5E3q3/A2xfpl7ar/4QDK+68TzjQe82izYITuvsI=; DOMAIN=cloud.browser.360.cn"); web_submit_data("info", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t5.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=459029", ENDITEM, "Name=sitedata", "Value=6f1751515d170703091e5156591a1b6d", ENDITEM, LAST); web_submit_data("info_2", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t6.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=224189", ENDITEM, "Name=sitedata", "Value=691005030c1705031a000d0b1c0000060201020a051e4b50555c195856175a46595d1a64", ENDITEM, LAST); web_submit_data("info_3", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t7.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=112784", ENDITEM, "Name=sitedata", "Value=6a1303000a1a03051c050b071f0006040205010903184f5153655d424a471e136f", ENDITEM, LAST); web_submit_data("info_4", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t8.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=774065", ENDITEM, "Name=sitedata", "Value=6c150507041b05031a020506190600030c04070f041f415055635b454446156a", ENDITEM, LAST); web_submit_data("info_5", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t9.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=587854", ENDITEM, "Name=sitedata", "Value=6e1a5051415c405a195b5a591a5355425d555b5f070d05011765", ENDITEM, LAST); web_submit_data("info_6", "Action=http://cloud.browser.360.cn/site/info", "Method=POST", "EncType=multipart/form-data", "RecContentType=text/plain", "Referer=", "Snapshot=t10.inf", "Mode=HTML", ITEMDATA, "Name=rn", "Value=314153", ENDITEM, "Name=sitedata", "Value=6813585e56525f595b4241090b010c001a77565c5b076a7f5c565d5f7c5d116c", ENDITEM, EXTRARES, "Url=http://t.wg.360-api.cn/ap/bar/pull?mid=9584dcf1d21227deae8dfc79c880b3cc&cver=", "Referer=", ENDITEM, LAST); lr_start_transaction("1_login"); web_add_cookie("__huid=11jHmC5E3q3/A2xfpl7ar/4QDK+68TzjQe82izYITuvsI=; DOMAIN=upext.chrome.360.cn"); lr_think_time(8); web_url("intf.php", "URL=http://upext.chrome.360.cn/intf.php?method=ExtUpdate.query&os=win&arch=x86&os_arch=x86_64&nacl_arch=x86-64&prod=chromiumcrx&prodchannel=stable&prodversion=86.0.4240.198&lang=zh-CN&acceptformat=crx2,crx3&cse=13.5.2044.0&x=id%3Dcfbkpilajlmedibkjkhcckpkpphhhklm%26v%3D1.3.1%26installsource%3Dnotfromwebstore%26installedby%3Dinternal%26uc", "Resource=0", "RecContentType=text/xml", "Referer=", "Snapshot=t11.inf", "Mode=HTML", LAST); lr_think_time(8); web_submit_data("login", "Action=http://124.71.152.247:8081/user/login", "Method=POST", "RecContentType=application/json", "Referer=http://124.71.152.247:8081/sign-in.html", "Snapshot=t12.inf", "Mode=HTML", ITEMDATA, "Name=username", "Value=apple", ENDITEM, "Name=password", "Value=123", ENDITEM, LAST); web_url("index.html", "URL=http://124.71.152.247:8081/index.html", "Resource=0", "Referer=http://124.71.152.247:8081/sign-in.html", "Snapshot=t13.inf", "Mode=HTML", EXTRARES, "Url=/user/info", ENDITEM, "Url=/board/topList", ENDITEM, "Url=/message/getUnreadCount", ENDITEM, "Url=/message/getAll", ENDITEM, "Url=/article/getAllByBoardId", ENDITEM, LAST); web_url("article_list.html", "URL=http://124.71.152.247:8081/article_list.html", "Resource=0", "Referer=http://124.71.152.247:8081/index.html", "Snapshot=t14.inf", "Mode=HTML", LAST); lr_end_transaction("1_login",LR_AUTO); return 0; }


脚本录制通过
设置10个虚拟用户数量,防止电脑崩溃。

使用Controller
(1)创建性能测试场景
一次初始化一个用户,每次间隔15s初始化一个虚拟用户;

设置虚拟用户数量10个,每隔10S启动一个用户;

运行5分钟;

退出所有用户,每隔10s退出一个用户。

(2)点击运行,启动场景
运行过程截图

结束截图

生成测试报告

- 虚拟用户数为10:测试中使用了10个虚拟用户。
- 点击率为2928:在一定时间内发生的点击次数。测试中出现了2928次点击。
- 吞吐量为112738:系统在单位时间内处理的请求数量,测试期间处理了112738个请求。
- 标准差为23.316:系统不够稳定,后续应进一步优化系统以降低标准差,提高系统的可靠性和稳定性。
点击率:刚开始启动,点击率较少,后面慢慢开始增大。
吞吐量:点击数越多,要处理的数量就越多,和上图的趋势相似。


原创文章,作者:优速盾-小U,如若转载,请注明出处:https://www.cdnb.net/bbs/archives/30873