公司网站建设 邮箱潍坊网站开发
目录
相关链接
一、项目背景
二、测试计划
1.测试用例
2.结构设计
2.1Utils类
3.测试登录页面
4.测试列表页面
5. 测试详情页面
6.测试编辑页面
测试结果:
整体测试结果 :
相关链接
博客系统代码:spring-blogs · jialixuan/博客系统 - 码云 - 开源中国
自动化测试代码/性能测试报告:BlogAutoTest · jialixuan/博客系统 - 码云 - 开源中国
已上线博客地址:http://8.140.60.17:8080/blog_login.html
一、项目背景
对于一个程序员来说,定期整理总结并写博客是不可或缺的步骤,在学习技术的过程中,总是学一点忘一点,如果把学习的过程记录在一个网站上,自己在学习技术的时候就能访问该网站,进行回顾、复习,回顾大学学习技术这里,我发现不管当时记忆多么深刻,到一定时间后,都会忘得一干二净。
二、测试计划
针对个人博客项目进行测试,个人博客主要由四个页面构成:登录页、列表页、详情页和编辑页,主要功能包括:登录、编辑并发布博客、查看详情、删除博客以及注销等功能。对于个人博客的测试就是针对主要功能进行测试。
1.测试用例
下面根据编写的测试用例对功能测试一一进行自动化测试
2.结构设计
2.1Utils类
package com.example.blogautotest.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 java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;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);//隐式等待(全局情况,查找元素的时候都让它等待2秒)
// driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));}return driver;}public Utils(String url){//调用driver对象driver = createDriver();//访问urldriver.get(url);}public void printscreen(String test) throws NoSuchMethodException, 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/blogautotest/image/"+ dirTime +"/"+test +"-" + fileTime+".png";System.out.println("filename:"+filename);File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);//srcFile放到指定位置FileUtils.copyFile(srcFile,new File(filename));}
}
3.测试登录页面
严格按照测试用例进行
- 是否能正常打开页面
- 登录失败 所有用例
- 登录成功 所有用例
代码:
package com.example.blogautotest.test;import com.example.blogautotest.common.Utils;
import org.junit.jupiter.api.Assertions;
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.io.IOException;public class LoginPage extends Utils {// 登录页面的urlpublic static final String url ="http://8.140.60.17:8080/blog_login.html";//创建显示等待对象private WebDriverWait wait = new WebDriverWait(driver, java.time.Duration.ofSeconds(20));// 初始化页面public LoginPage(){super(url);}public void check() throws IOException, NoSuchMethodException, InterruptedException {//1.查看是否正常打开页面loginFail();//2.登录成功loginSuccess();//3.登录失败loginFail();}//1.查看是否正常打开页面private void login() throws IOException, NoSuchMethodException {//1)// 获取页面的UrlString CurUrl = driver.getCurrentUrl();// 判断是否与url一致Assertions.assertEquals(this.url, CurUrl);//2)//检查logo图片元素Assertions.assertNotNull(driver.findElement(By.cssSelector("body > div.nav > img")));//检查“博客系统”字样Assertions.assertNotNull(driver.findElement(By.cssSelector("body > div.nav > span")));//检查是否有输入框、提交按钮Assertions.assertNotNull(driver.findElement(By.cssSelector("#username"))); //用户名框Assertions.assertNotNull(driver.findElement(By.cssSelector("#password")));//密码框Assertions.assertNotNull(driver.findElement(By.cssSelector("#submit")));//提交按钮}//2.登录成功private void loginSuccess() throws IOException, NoSuchMethodException, InterruptedException {driver.findElement(By.cssSelector("#username")).clear(); //清空输入框driver.findElement(By.cssSelector("#password")).clear(); //清空输入框driver.findElement(By.cssSelector("#username")).sendKeys("西贝"); //在输入框中输入用户名driver.findElement(By.cssSelector("#password")).sendKeys("123456"); //在输入框中输入密码driver.findElement(By.cssSelector("#submit")).click(); //点击提交按钮Thread.sleep(500);//检查是否跳转到blog_list.htmlAssertions.assertEquals("http://8.140.60.17:8080/blog_list.html",driver.getCurrentUrl());driver.navigate().back(); //返回上一页driver.findElement(By.cssSelector("#username")).clear(); //清空输入框driver.findElement(By.cssSelector("#password")).clear(); //清空输入框driver.findElement(By.cssSelector("#username")).sendKeys("西贝贝"); //在输入框中输入用户名driver.findElement(By.cssSelector("#password")).sendKeys("123456"); //在输入框中输入密码driver.findElement(By.cssSelector("#submit")).click(); //点击提交按钮Thread.sleep(500);//检查是否跳转到blog_list.htmlAssertions.assertEquals("http://8.140.60.17:8080/blog_list.html",driver.getCurrentUrl());//点击注销按钮driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();}//3.登录失败private void loginFail() throws IOException, NoSuchMethodException, InterruptedException {// driver.navigate().back(); //返回上一页wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username"))).clear();//清空输入框wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password"))).clear();//清空输入框//情况一 账号错误 密码正确wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username"))).sendKeys("11");//在输入框中输入用户名wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password"))).sendKeys("123456"); //在输入框中输入密码wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();//点击提交按钮Alert alert = wait.until(ExpectedConditions.alertIsPresent());Assertions .assertEquals("用户不存在",alert.getText());alert.accept();driver.findElement(By.cssSelector("#username")).clear(); //清空输入框driver.findElement(By.cssSelector("#password")).clear(); //清空输入框//情况一 账号错误 密码正确driver.findElement(By.cssSelector("#username")).sendKeys("西贝"); //在输入框中输入用户名driver.findElement(By.cssSelector("#password")).sendKeys("1"); //在输入框中输入密码driver.findElement(By.cssSelector("#submit")).click(); //点击提交按钮Thread.sleep(500);alert = wait.until(ExpectedConditions.alertIsPresent());Assertions .assertEquals("密码错误",alert.getText());alert.accept();// driver.quit();}
}
测试结果:
4.测试列表页面
- 测试未登录状态下的博客列表页面
- 测试已登录状态下的布局的一致性
- 测试列表页面中的按钮
- 测试注销功能
代码:
package com.example.blogautotest.test;import com.example.blogautotest.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import java.io.IOException;
import java.time.Duration;public class ListPage extends Utils {// 列表页面的urlprivate static String listUrl = "http://8.140.60.17:8080/blog_list.html";// 创建一个显式等待对象private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));public ListPage() throws IOException, NoSuchMethodException {super(listUrl);}public void checkList() throws InterruptedException, IOException, NoSuchMethodException {//测试未登录状态下的博客列表页面ListNotLogin();//测试已登录状态下布局的一致性ListByLogin();//测试查看全文按钮和点击写博客按钮和GitHub按钮ListCheckButton();//测试注销功能ListCheckQuit();}private void ListNotLogin() throws InterruptedException {wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));}private void ListByLogin() throws IOException, NoSuchMethodException, InterruptedException {// 清除用户名和密码输入框driver.findElement(By.cssSelector("#username")).clear();driver.findElement(By.cssSelector("#password")).clear();// 输入指定的用户名和密码driver.findElement(By.cssSelector("#username")).sendKeys("西贝");driver.findElement(By.cssSelector("#password")).sendKeys("123456");// 点击登录按钮driver.findElement(By.cssSelector("#submit")).click();// 截取屏幕图像printscreen("ListByLogin");try {// 等待导航元素出现,包括文本和图像,确保页面已加载到可以进行交互的状态wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > span")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > img")));// 确保URL包含预期的列表页面URL部分,以验证页面正确加载wait.until(ExpectedConditions.urlContains(listUrl));// 等待左侧栏的特定元素出现,以验证博客列表页面的关键内容已加载wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > div:nth-child(4) > span:nth-child(1)")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > div:nth-child(4) > span:nth-child(2)")));// 等待左侧栏的标题和图像元素出现,进一步验证页面内容的正确性wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > h3")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > img")));// 如果所有预期元素都出现,打印成功验证的消息System.out.println("验证博客列表页面成功");} catch (TimeoutException e) {// 如果在规定时间内未找到指定元素,捕获TimeoutException并打印错误消息System.out.println("在规定时间内未找到指定元素:" + e.getMessage());}}//private void ListCheckButton() throws IOException, NoSuchMethodException, InterruptedException {try {// 点击查看全文按钮和点击写博客按钮// 解释:此部分代码等待特定元素出现并点击,以验证页面功能的可操作性wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(1)")));// 返回上一页,点击导航栏的第五个链接和提交按钮// 解释:此部分代码模拟用户返回并选择导航栏中的其他选项,以测试页面导航功能driver.navigate().back();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(5)"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));// 返回上一页,点击Gitee链接// 解释:此部分代码模拟用户返回并点击GitHub链接,以验证外部链接功能driver.navigate().back();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > a"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#userSkin > div.user-profile-head > div.user-profile-head-info > div.user-profile-head-info-t > div > div.user-profile-head-info-rr > div.user-profile-head-info-r-t > div.user-profile-head-name > div:nth-child(1)")));driver.navigate().back();System.out.println("点击 全文按钮、写博客按钮、GitHub按钮 均正常运行"); } catch (TimeoutException e) {// 处理超时异常,打印错误信息// 解释:此部分代码捕获超时异常,并输出错误信息,以方便问题定位System.out.println("规定时间内未找到指定元素:" + e.getMessage());}}//点击注销按钮 验证结果:跳转到博客登录界面private void ListCheckQuit() {try {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();driver.findElement(By.cssSelector("#username"));driver.findElement(By.cssSelector("#password"));System.out.println("退出成功");} catch (Exception e) {System.out.println("退出失败");}}
}
测试结果:
5. 测试详情页面
- 测试未登录状态下的博客详情页面
- 测试已登录状态下的布局的一致性
- 测试详情页面中的按钮
- 测试注销功能
代码:
package com.example.blogautotest.test;import com.example.blogautotest.common.Utils;
import org.junit.jupiter.api.Assertions;
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.io.IOException;
import java.time.Duration;public class DetailPage extends Utils {//博客详情页面的urlpublic static final String url = "http://8.140.60.17:8080/blog_detail.html";//创建显示等待对象private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));public DetailPage(){super(url);}public void check() throws InterruptedException, IOException, NoSuchMethodException {DetailNotLogin();DetailBylogin();DetailButton();DetailCheckQuit();}//测试未登录状态下的博客详情页面public void DetailNotLogin() throws InterruptedException {Thread.sleep(2000);wait.until(ExpectedConditions.urlToBe("http://8.140.60.17:8080/blog_login.html"));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));}//测试布局的一致性public void DetailBylogin(){//1.在登录页面输入账号密码并点击登录wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username"))).sendKeys("西贝");wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password"))).sendKeys("123456");wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();//2.点击查看全文跳转到博客详情页面wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a"))).click();//3.查看布局的一致性wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.title"))); //文章标题wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.date"))); //发布文章时间wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#detail > p > a")));//文章内容wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(1)")));//文章编辑按钮wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)")));//文章删除按钮}//测试博客详情页面的按钮可用性private void DetailButton() throws InterruptedException, IOException, NoSuchMethodException {// 点击主页wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(4)"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a")));driver.navigate().back();//点击写博客按钮wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(5)"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(25) > a")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));driver.navigate().back();//点击Giteewait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.left > div > a"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#userSkin > div.user-profile-head > div.user-profile-head-info > div.user-profile-head-info-t > div > div.user-profile-head-info-rr > div.user-profile-head-info-r-t > div.user-profile-head-name > div:nth-child(1)")));driver.navigate().back();//点击编辑wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(1)"))).click();wait.until(ExpectedConditions.titleIs("博客编辑页"));driver.navigate().back();//点击删除wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)"))).click();Alert alert = driver.switchTo().alert();String text = alert.getText();Assertions.assertEquals("确定删除?",text);alert.dismiss();}//点击注销按钮 验证结果:跳转到博客登录界面private void DetailCheckQuit() {try {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();driver.findElement(By.cssSelector("#username"));driver.findElement(By.cssSelector("#password"));System.out.println("退出成功");} catch (Exception e) {System.out.println("退出失败");}}
}
测试结果:
6.测试编辑页面
- 测试未登录状态下的博客编辑页面
- 测试已登录状态下的布局的一致性
- 测试详情页面中的按钮
- 测试发布成功用例
- 测试发布失败用例
- 测试注销功能
代码:
package com.example.blogautotest.test;import com.example.blogautotest.common.Utils;
import org.junit.jupiter.api.Assertions;
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.io.IOException;
import java.time.Duration;public class EditPage extends Utils {//博客编辑页面urlprivate static final String url = "http://8.140.60.17:8080/blog_edit.html";//创建显示等待对象private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));public EditPage(){super(url);}public void check() throws InterruptedException, IOException, NoSuchMethodException {EditNotLogin(); //测试未登录状态下的博客编辑页面EditLogin(); //测试已登录状态下的布局的一致性EditButton(); //测试详情页面中的按钮PublishSucceed(); //测试发布成功用例Publishfail(); //测试发布失败用例EditCheckQuit(); //测试注销功能}//测试未登录状态下的博客编辑页面private void EditNotLogin() throws InterruptedException, IOException, NoSuchMethodException {Alert alert = wait.until(ExpectedConditions.alertIsPresent());alert.accept();printscreen("EditNotLogin");wait.until(ExpectedConditions.urlToBe("http://8.140.60.17:8080/blog_login.html"));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));}//测试布局的一致性private void EditLogin() throws InterruptedException, IOException, NoSuchMethodException {wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username"))).sendKeys("西贝");wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password"))).sendKeys("123456");wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();Thread.sleep(500);wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(" body > div.nav > a:nth-child(5)"))).click();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > span"))); //wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > img"))); //wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))); //发布按钮wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#editor > div.editormd-toolbar > div > ul")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(1) > a > i")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(4)")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(5)")));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(6)")));}private void EditButton() throws IOException, NoSuchMethodException {// 点击主页wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(4)"))).click();printscreen("EditButton");wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a")));driver.navigate().back();//点击写博客按钮wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(5)"))).click();printscreen("EditButton");wait.until(ExpectedConditions.urlToBe(url));}//发布文章成功private void PublishSucceed() throws IOException, NoSuchMethodException, InterruptedException {wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#title"))).sendKeys("自动化测试标题");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"));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();}//发布文章失败private void Publishfail() throws IOException, NoSuchMethodException, InterruptedException {//Thread.sleep(500);//点击写博客按钮wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.nav > a:nth-child(5)"))).click();//1.未填写标题wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#title"))).clear();wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();Alert alert = wait.until(ExpectedConditions.alertIsPresent());Assertions .assertEquals("标题不能为空!",alert.getText());alert.accept();//2.未填写内容wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#title"))).clear();driver.findElement(By.cssSelector("#editor > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll > div:nth-child(2)"));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();alert = wait.until(ExpectedConditions.alertIsPresent());Assertions .assertEquals("标题不能为空!",alert.getText());alert.accept();//3.未填写标题和内容wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#title"))).clear();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"));wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit"))).click();alert = wait.until(ExpectedConditions.alertIsPresent());Assertions .assertEquals("标题不能为空!",alert.getText());alert.accept();driver.quit();}//点击注销按钮 验证结果:跳转到博客登录界面private void EditCheckQuit() {try {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();driver.findElement(By.cssSelector("#username"));driver.findElement(By.cssSelector("#password"));System.out.println("退出成功");} catch (Exception e) {System.out.println("退出失败");}}
}
测试结果:
整体测试结果 :