写在前:hello大家早中晚上好!这里是西西,前面我们已经学习了关于测试相关基础的介绍,点击链接直达前方内容~
测试内容 博客链接 初识软件测试 点击跳转 软件测试相关概念 点击跳转 测试生命周期、BUG、测试大体流程 点击跳转 测试用例、测试分类 点击跳转 自动化测试 点击跳转 在学习了这些知识的基础上,接下来就需要进行实操啦。这篇博客中我会完成对于我的简易博客系统的黑盒测试和自动化测试
完成的简易博客系统已经发布:西西简易博客系统链接
目录
“西西简易博客系统”自动化测试
1. 项目背景
2. 项目功能
2.1 主要页面实现
2.1.1 西西博客登录页
2.1.2 西西博客列表页
2.1.3 西西博客详情页
2.1.4 西西博客编辑页
2.2 主要功能实现
2.2.1 强制登录
2.2.2 列表页展示所有博客
2.2.3 详情页查看博客具体内容
2.2.4 博客详情页对应具体作者信息
2.2.5 编辑页可成功发布博客
2.2.6 正常退出
3. 黑盒测试导图
3.1 界面
3.2 功能
3.3 性能编辑
3.4 兼容
3.5 易用
3.6 安全
3.7 网络
4. 自动化测试
4.1 测试导图
4.1.1 登录页面
4.1.2 博客列表页
4.1.3 博客详情页
4.1.4 博客编辑页
4.2 代码编写
4.2.1 引入依赖
4.2.2 代码测试
(1) InitAndEnd 文件脚本
(2)BlogCases 文件脚本
A. 登录页
B. 列表页
C. 编辑页
D. 详情页
E. 退出
4.2.3 其余内容
4.3 测试结果
4.4 自动化测试小结
4.5 难点与亮点
4.5.1 实现
4.5.2 难点
4.5.3 亮点
“西西简易博客系统”自动化测试
1. 项目背景
西西简易博客系统主要采用了“前后端分离”方式。[这种方式下,服务器不关注页面的内容,只给网页端提供数据,网页端通过 ajax 的方式和服务器之间交互数据,网页拿到数据之后根据数据的内容渲染到服务器上],使用数据库进行数据的存储。项目的部署用到 Tomcat,最终通过 Xshell 上传到云服务器上,完成项目发布。
2. 项目功能
2.1 主要页面实现
2.1.1 西西博客登录页
2.1.2 西西博客列表页
2.1.3 西西博客详情页
2.1.4 西西博客编辑页
2.2 主要功能实现
2.2.1 强制登录
如果用户没有登录的话点击“主页”、“写博客”按钮,都不会跳转,都会强制的跳转到登录页。
2.2.2 列表页展示所有博客
用户输入用户名、密码,会自动跳转到博客列表页,博客列表页展示所有博客。
2.2.3 详情页查看博客具体内容
点击博客列表页的“查看全文”按钮,跳转到博客详情页,详情页展示此篇博客的全部内容【博客列表页做的截断处理,没有显示的内容后面展示为“...”】
2.2.4 博客详情页对应具体作者信息
点击博客详情页,左边的作者名字是对应的博客作者,而非登录者。
2.2.5 编辑页可成功发布博客
在博客编辑页中输入文章标题,文章内容,点击发布文章后,跳转到博客列表页,新发布的文章显示在博客列表页中的第一个位置。
2.2.6 正常退出
点击注销按钮,跳转到博客登录页。
3. 黑盒测试导图
需求分析 - 测试计划 - 测试设计 - 测试开发 - 测试执行 - 测试评估
3.1 界面
3.2 功能
3.3 性能
3.4 兼容
3.5 易用
3.6 安全
3.7 网络
按照上面的导图即可以进行博客系统的“黑盒测试”,具体操作这里不进行详细的介绍~~
4. 自动化测试
4.1 测试导图
4.1.1 登录页面
4.1.2 博客列表页
4.1.3 博客详情页
4.1.4 博客编辑页
4.2 代码编写
4.2.1 引入依赖
在进行项目的自动化测试之前,我们需要在pom.xml文件中引入所需要的依赖。
这里我用到的是selenium3 和Junit5。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>blog_test</artifactId><version>1.0-SNAPSHOT</version><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><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.5.2</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.5.2</version></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>
4.2.2 代码测试
在这里创建两个文件
将开始打开网页和最后的测试完成关闭页面放到 InitAndEnd 文件中;对于博客各个页面的自动化测试脚本放到文件 BlogCases 中。
在所有脚本执行之前进行初始化操作 -- 打开浏览器 ,创建驱动
在所有脚本执行完成后进行退出操作。
(1) InitAndEnd 文件脚本
public class InitAndEnd {static {System.setProperty("webdriver.chrome.driver","C:\\Program Files\\Java\\jdk1.8.0_192\\bin\\chromedriver.exe");}static WebDriver webDriver;@BeforeAllstatic void SetUp() {webDriver = new ChromeDriver();}@AfterAllstatic void TearDown() {webDriver.quit();}}
(2)BlogCases 文件脚本
A. 登录页
@Order(1)@ParameterizedTest@CsvFileSource(resources = "LoginSuccess.csv")void LoginSuccess(String username, String password, String blog_list_url) {System.out.println(username + password + blog_list_url);// 打开博客登录页面webDriver.get("http://49.232.51.45:8080/java109_blog_system/login.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入账号suxixiwebDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 输入密码123webDriver.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.SECONDS);// 跳转到列表页// 获取到当前页面urlString cur_url = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 如果url=http://49.232.51.45:8080/java109_blog_system/blog_list.html,测试通过,否则测试不通过Assertions.assertEquals(blog_list_url, cur_url);// 列表页展示用户信息是suxixi// 用户名是suxixi测试通过,否则测试不通过webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String cur_admin = webDriver.findElement(By.cssSelector("body > div.container > div.container-left > div > h2")).getText();Assertions.assertEquals(username, cur_admin);}
B. 列表页
@Order(2)@Testvoid BlogList() {// 打开博客列表页webDriver.get("http://49.232.51.45:8080/java109_blog_system/blog_list.html");// 获取页面上所有博客标题对应的元素webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int title_num = webDriver.findElements(By.cssSelector(".title")).size();// 如果元素数量不为0,测试通过Assertions.assertNotEquals(0 ,title_num);}
C. 编辑页
@Order(3)@Testvoid EditBlog() throws InterruptedException {// 找到写博客按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 通过Js讲标题进行输入((JavascriptExecutor)webDriver).executeScript("document.getElementById(\"title\").value=\"自动化测试\"");sleep(3000);// 点击发布webDriver.findElement(By.cssSelector("#edit")).click();sleep(3000);// 获取当前页面urlString cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://49.232.51.45:8080/java109_blog_system/blog_list.html", cur_url);}
/*** 校验已发布博客标题* 校验已发布博客时间*/@Order(5)@Testvoid BlogInfoChecked() {webDriver.get("http://49.232.51.45:8080/java109_blog_system/blog_list.html");// 获取第一篇博客标题String first_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title")).getText();// 获取第一篇博客发布时间String first_blog_time = webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[2]")).getText();// 校验博客标题是不是自动化测试Assertions.assertEquals("自动化测试", first_blog_title);// 如果时间是2024-3-19年发布的,测试通过if(first_blog_time.contains("2024")) {System.out.println("测试通过");} else {System.out.println("当前时间是:" + first_blog_time);System.out.println("测试不通过");}}
D. 详情页
/*** 博客详情页校验* url* 博客标题* 页面title是“博客详情页”*/@Order(4)@ParameterizedTest@MethodSource("Generator")void BlogDetail(String expected_url, String expected_title, String expected_blog_title) {// 找到第一篇博客对应的产看全文按钮webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();// 获取当前页面urlwebDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String cur_url = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 获取当前页面titleString cur_title = webDriver.getTitle();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 获取博客标题String cur_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.container-right > h3")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(expected_title ,cur_title);Assertions.assertEquals(expected_blog_title, cur_blog_title);if(cur_url.contains(expected_url)) {System.out.println("测试通过");} else {System.out.println(cur_url);System.out.println("测试不通过");}}
E. 退出
/*** 注销*/@Order(6)@Testvoid Logout() {webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 校验url(登录url)String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://49.232.51.45:8080/java109_blog_system/login.html", cur_url);// 校验提交按钮WebElement webElement = webDriver.findElement(By.cssSelector("#submit"));Assertions.assertNotNull(webElement);}
4.2.3 其余内容
在Order(1)中引入了 LoginSuccess.csv
suxixi,123,http://49.232.51.45:8080/java109_blog_system/blog_list.html
在 BlogCases 中引入的各种包
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.api.*; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvFileSource; import org.junit.jupiter.params.provider.MethodSource; import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebElement;import java.util.concurrent.TimeUnit; import java.util.stream.Stream;import static java.lang.Thread.sleep;
4.3 测试结果
测试前的详情页页面:
测试后:
列表页:
点击详情:
[测试发布的博客是“suxixi”,所以点击查看全文后,左边的作者信息应该显示的是“suxixi”]
控制台输出:
4.4 自动化测试小结
- 使用Order(x)确认自动化测试的执行顺序
- 对主要模块的测试一定要严谨,检查页面的元素保证页面的准确性
- 获取元素时建议获取固定的元素,如标题,链接等,内容是动态变化的,不建议获取
- 开启驱动和关闭驱动的位置需要注意,使用注解 @BeforeAll 和 @AfterAll
- 测试用例不是越多越好,抓住“主要矛盾”,本自动化测试针对主要流程进行全面测试
4.5 难点与亮点
4.5.1 实现
如何使用 selenium3 和Junit 5结合进行自动化测试?
根据此博客的具体实现功能进行自动化测试用例导图,根据导图通过自动化测试工具 selenium3 和 单元测试框架 Junit5 结合,实现web自动化测试。
对具体代码的细节进行讲解,按照执行的顺序详细的介绍每个部分都实现了什么测试用例。
4.5.2 难点
自动化测试脚本的编写的难度整体不高,但是脚本执行的速度很快,当出现报错的时候,测试人员需要及时定位问题,确定出现问题的原因,明确产生问题的原因,及时解决问题。
4.5.3 亮点
- 驱动只创建了一次,在每个测试用例执行的时候没有重复开启、关闭驱动,避免资源和时间的浪费
- 使用了参数化,保证用例的简洁性,提高了代码可读性
- 使用 Junit5 提供的注解,避免生成多对象,提高测试执行效率
- 使用等待,提高自动化测试的运行效率,提高了测试的稳定性,一定程度上降低了报错的可能性
自动化测试完结撒花啦 ~ 道虽迩,不行不至;事虽小,不为不成。前路虽道阻且长,希望我们都能找到自己的目标并且为之努力,一定会水到渠成的!