当前位置: 首页 > news >正文

【测试项目】——个人博客系统自动化测试

📖 前言:本文针对个人博客项目进行测试,个人博客主要由四个页面构成:登录页、列表页、详情页和编辑页,主要功能包括:登录、编辑并发布博客、查看详情、删除博客以及注销等功能。对于个人博客的测试就是针对主要功能进行测试,然后按照页面书写测试类。


目录

  • 🕒 1. 博客系统页面概览
  • 🕒 2. 实施流程
  • 🕒 3. 编写思路
    • 🕘 3.1 添加相关依赖
    • 🕘 3.2 包结构
  • 🕒 4. 代码编写
    • 🕘 4.1 公共类AutoTestUtils
    • 🕘 4.2 BlogLoginTest(登录页测试)
    • 🕘 4.3 BlogListTest(列表页测试)
    • 🕘 4.4 BlogEditTest(编辑页测试)
    • 🕘 4.5 BlogDetailTest(详情页测试)
    • 🕘 4.6 BlogDeleteTest(博客删除测试)
    • 🕘 4.7 BlogLogoutTest
    • 🕘 4.8 runSuite(测试套件)
  • 🕒 5. 测试结果
  • 🕒 6. 小结

🕒 1. 博客系统页面概览

登录页:

在这里插入图片描述

列表页:

在这里插入图片描述

详情页:

在这里插入图片描述

编辑页:

在这里插入图片描述

🕒 2. 实施流程

自动化项目实施的基本流程:

  1. 熟悉项目
  2. 设计手工测试用例
  3. 手工测试用例转换成自动化测试用例
  4. 部署

请添加图片描述

🕒 3. 编写思路

  • 依据思维导图编写测试用例:为每个页面创建一个测试类,并在各个测试类中编写测试用例。
  • 公共属性应单独归类以便代码复用。
  • 运用测试套件以简化运行和修改过程。
  • 由于启动和现场截图功能会被频繁复用,应单独建立一个类来存放这些功能。
  • 添加隐式等待以确保页面能正确完全地加载。

🕘 3.1 添加相关依赖

创建Maven空项目后,在pom.xml里添加需要的依赖

<dependencies><!--   添加selenium依赖  --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.24.0</version></dependency><!--   保存屏幕截图需要用到的包  --><!-- https://mvnrepository.com/artifact/commons-io/commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.16.1</version></dependency><!--   添加junit5依赖  --><!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.10.2</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.10.2</version></dependency><!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite --><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.11.0</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.10.2</version><scope>test</scope></dependency>
</dependencies>

🕘 3.2 包结构

在这里插入图片描述

🕒 4. 代码编写

🕘 4.1 公共类AutoTestUtils

功能:创建驱动、保存现场截图

注意:在保存现场截图时,应按日期对文件夹进行分类,并确保图片名称反映出测试类别的名称,以便于问题追踪。同时,要留意文件名的动态生成和时间格式的设定。

public class AutoTestUtils {public static WebDriver webDriver;@BeforeAllstatic void SetUp() {if(webDriver == null){webDriver = new ChromeDriver();}// 设置隐式等待时间为3秒webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);}public static void TearDown() {webDriver.quit();}// 保存截图的方法public static void saveScreenshot(String testName) {// 获取当前时间并格式化String timestamp = new SimpleDateFormat("yyyyMMdd-HHmmssSSS").format(new Date());String dateFolder = new SimpleDateFormat("yyyyMMdd").format(new Date());String fileName = String.format("%s-%s.png", testName, timestamp);// 创建文件夹File folder = new File("screenshots/" + dateFolder);if (!folder.exists()) {folder.mkdirs(); // 创建文件夹}// 保存截图File screenshot = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);try {Files.copy(screenshot.toPath(), Paths.get(folder.getPath(), fileName));} catch (IOException e) {e.printStackTrace();}}
}

在这里插入图片描述

🕘 4.2 BlogLoginTest(登录页测试)

  1. 创建驱动并打开网页。
  2. 检查网页是否正常加载。
  3. 进行正常登录测试:多参数测试,使用Enter键登录。
  4. 进行异常登录测试:用户名或密码错误,以及为空的情况。
  5. 使用Order注解确保测试按正确顺序执行,避免因顺序错误导致测试失败。
  6. 确保在重新输入用户名和密码前清空之前的内容。
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)public class BlogLoginTest extends AutoTestUtils {// 所有用例都需要先获取登录页面@BeforeAllstatic void baseControl() {webDriver.get("http://localhost:8080/blog_system/login.html");}/*** 检查登录页面是否正确* 右上角与左上角的显示、登录框等*/@Test@Order(1)void loginPageLoadRight() throws IOException {webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));webDriver.findElement(By.xpath("/html/body/div[1]/a[2]"));webDriver.findElement(By.cssSelector("body > div.login-container > form > div"));saveScreenshot(getClass().getName());}/*** 检查登录正常情况:使用多参数测试*/@Order(3)@ParameterizedTest@CsvFileSource(resources = "LoginSuccess.csv")void loginSuccess(String username, String password, String blog_list_url) throws IOException {// 在每次登录之后都要进行清空,然后才能重新输入webDriver.findElement(By.cssSelector("#username")).clear();webDriver.findElement(By.cssSelector("#password")).clear();webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.findElement(By.cssSelector("#login-button")).sendKeys(Keys.ENTER);saveScreenshot(getClass().getName());webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 以上是登录步骤,但是并不能确保就是登录成功的// 获取到当前页面的URL,如果URL匹配则测试通过String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals(blog_list_url, cur_url);// 列表页展示的用户信息是否是登录账号String cur_usr = webDriver.findElement(By.cssSelector("body > div.container > div.container-left > div > h3")).getText();Assertions.assertEquals(username, cur_usr);// 因为要多参数,所以在执行完一遍执行下一遍的时候需要进行页面的回退,否则找不到登录框webDriver.navigate().back();}/*** 测试完成后登录以便进行下一阶段测试*/@Order(4)@Testvoid loginSuccessAfter()  {webDriver.findElement(By.cssSelector("#login-button")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);}/*** 检查登录异常情况:使用多参数测试*/@Order(2)@ParameterizedTest@CsvSource({"admin,123", "lisi,12", "'',''"})       // 第三项为空情况void loginFail(String username, String password) throws IOException {// 在每次登录之后都要进行清空,然后才能重新输入webDriver.findElement(By.cssSelector("#username")).clear();webDriver.findElement(By.cssSelector("#password")).clear();webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.findElement(By.cssSelector("#login-button")).click();saveScreenshot(getClass().getName());webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 登录失败的检测,获取文本进行比对String expectNotNull = "为空"; // 为空字样String expectError = "错误"; // 错误字样String actual = webDriver.findElement(By.cssSelector("body")).getText();if (actual.contains(expectNotNull) ||  actual.contains(expectError)) {System.out.println("登录失败测试通过");} else {System.out.println("登录失败测试不通过");}// 导航回登录页webDriver.navigate().back();}
}

🕘 4.3 BlogListTest(列表页测试)

  1. 检验博客列表页面是否能够正常打开。
  2. 验证列表页面的“查看全文”按钮是否能正确跳转。
  3. 检查未登录时的直接链接是否会重定向到登录页面。
public class BlogListTest extends AutoTestUtils {@BeforeAllstatic void baseControl()  {webDriver.get("http://localhost:8080/blog_system/blog_list.html");}/** 博客列表页可以正常显示*/@Testvoid listPageLoadRight() throws IOException {// 可以多检查几个,确保正确webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)"));webDriver.findElement(By.cssSelector("body > div.container > div.container-left > div > img"));// 获取页面上所有博客标题对应的元素webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int title_num = webDriver.findElements(By.cssSelector(".title")).size();// 如果元素数量不为0,则测试通过Assertions.assertNotEquals(0,title_num);saveScreenshot(getClass().getName());}
}

🕘 4.4 BlogEditTest(编辑页测试)

  1. 检验编辑页面是否能正确打开
  2. 检查博客发布是否正常:元素是否完整或部分缺失
  3. 验证“写博客”按钮的功能性
public class BlogEditTest extends AutoTestUtils {@BeforeAllstatic void baseControl()  {webDriver.get("http://localhost:8080/blog_system/blog_list.html");}/** 博客编辑页可以正常显示*/@Test@Order(1)void editPageLoadRight() throws IOException {// 找到写博客按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 可以多检查几个,确保正确webDriver.findElement(By.cssSelector("#submit"));webDriver.findElement(By.cssSelector("#blog-title"));saveScreenshot(getClass().getName());}/** 正确编辑并发布博客测试*/@Test@Order(2)void editAndSubmitBlog() throws IOException {// 通过JS输入标题((JavascriptExecutor) webDriver).executeScript("document.getElementById(\"blog-title\").value=\"自动化测试\"");// 编辑页的md是第三方插件,所以不可以直接使用sendKeys向编辑模块写入内容,但是可以通过点击上方按钮进行内容的插入webDriver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(30) > a > i")).click();webDriver.findElement(By.cssSelector("#editor > div.editormd-toolbar > div > ul > li:nth-child(5) > a > i")).click();saveScreenshot(getClass().getName());// 点击发布webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 获取当前页面的URLString cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://localhost:8080/blog_system/blog_list.html", cur_url);saveScreenshot(getClass().getName());}
}

🕘 4.5 BlogDetailTest(详情页测试)

  1. 正确打开测试详情页:分别测试有blogId和无blogId的情况
  2. 测试删除按钮是否可用,应比较时间而非标题,因为标题可能为空
  3. 注意操作时要确保能够导航回列表页
public class BlogDetailTest extends AutoTestUtils {@BeforeAllstatic void baseControl()  {webDriver.get("http://localhost:8080/blog_system/blog_list.html");}public static Stream<Arguments> Generator() {return Stream.of(Arguments.arguments("http://localhost:8080/blog_system/blog_detail.html","博客详情页","自动化测试"));}@ParameterizedTest@MethodSource("Generator")void BlogDetail(String expected_url,String expected_title,String expected_blog_title) {// 找到第一个博客对应的查看全文按钮webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();// 获取当前页面的URL、页面title、博客标题String cur_url = webDriver.getCurrentUrl();String cur_title = webDriver.getTitle();String cur_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.container-right > div > h3")).getText();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("测试不通过");}webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);saveScreenshot(getClass().getName());}
}

🕘 4.6 BlogDeleteTest(博客删除测试)

  1. 测试博客是否真正删除了
  2. 尝试删除别人的文章
  3. 删除完返回列表页
public class BlogDeleteTest extends AutoTestUtils {@BeforeAllstatic void baseControl()  {webDriver.get("http://localhost:8080/blog_system/blog_list.html");}@Testvoid DeleteBlog () {// 点击查看全文按钮webDriver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a")).click();// 点击删除按钮webDriver.findElement(By.cssSelector("#delete_button")).click();// 博客列表页第一篇博客不是“自动化测试”String first_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.title")).getText();// 校验当前博客标题不等于“自动化测试”Assertions.assertNotEquals(first_blog_title,"自动化测试");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);saveScreenshot(getClass().getName());// 尝试删除别人的文章// 点击查看全文按钮webDriver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > a")).click();// 点击删除按钮webDriver.findElement(By.cssSelector("#delete_button")).click();// 删除失败的检测,获取文本进行比对String expectError = "没有权限"; // 没有权限错误字样String actual = webDriver.findElement(By.cssSelector("body")).getText();if (actual.contains(expectError)) {System.out.println("删除失败测试通过");} else {System.out.println("删除失败测试不通过");}saveScreenshot(getClass().getName());webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 导航回列表页webDriver.navigate().back();}
}

🕘 4.7 BlogLogoutTest

  1. 测试注销后是否返回登录页
  2. 断开驱动连接
public class BlogLogoutTest extends AutoTestUtils {@BeforeAllstatic void baseControl()  {webDriver.get("http://localhost:8080/blog_system/blog_list.html");}@Testvoid Logout(){webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();// 校验当前页面URL是否是“http://localhost:8080/blog_system/login.html”String cur_url=webDriver.getCurrentUrl();Assertions.assertEquals("http://localhost:8080/blog_system/login.html",cur_url);// 校验提交按钮WebElement webElement = webDriver.findElement(By.cssSelector("#login-button"));Assertions.assertNotNull(webElement);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);saveScreenshot(getClass().getName());//webDriver.quit();TearDown();}
}

🕘 4.8 runSuite(测试套件)

测试套件按照测试类的顺序执行。

@Suite
@SelectClasses({BlogLoginTest.class, BlogListTest.class, BlogEditTest.class, BlogInfoChecked.class, BlogDetailTest.class, BlogDeleteTest.class, BlogLogoutTest.class})
public class runSuite {
}

🔎 自动化测试完整源码+博客项目

🕒 5. 测试结果

实际效果(无倍速):
请添加图片描述

在这里插入图片描述

🕒 6. 小结

  1. 关注测试用例的执行顺序
  2. 检查页面元素是否存在,以确保正确性。
  3. 注意多参数测试中的页面导航问题。
  4. 多参数(多用户登录)可能导致高并发服务器错误,需交由开发处理。
  5. 登录页面测试的最后一步应为登录成功状态,以便后续测试顺利进行。
  6. 驱动关闭应在最后一个用例结束后进行。
  7. 在公共类中定义保存截图方法以保存所有用例的执行结果,便于后续查错。截图保存时使用动态时间戳,按照天或周分类保存。
  8. @SelectClasses可指定执行类的顺序。
  9. 建议获取固定元素(如时间、标题)时,使用 XPath 定位。因为 XPath 可以基于元素的层级关系和属性进行查找,所以它适合用于固定元素的定位,特别是在复杂的 DOM 结构中。
  10. 可以适当关注用例执行时间,排查是否为性能问题。
  11. 可创建单独类存放驱动释放方法,放在套件测试的最后。
  12. 测试用例数量并非越多越好。
  13. 可以使用无头模式创建驱动。

【面试题】使用Selenium 4 自动化测试工具和JUnit 5 单元测试框架结合,如何实现的,以及有什么亮点?

1)实施:
① 设计测试用例是基于个人项目的需求,通过结合Selenium 4自动化测试工具和JUnit 5单元测试框架来执行Web自动化测试(功能、步骤和技术必须明确)。
② 需要对代码中的每个包提供概要介绍(公共属性[可复用]、测试用例[基于每个页面设计]),并使用测试套件来加载所有测试类。

2)特点:
① 利用JUnit 5提供的注解,避免创建过多对象,节省资源和时间,提升自动化测试的执行效率。
只创建一次驱动对象,减少每个测试用例重复创建驱动对象,节约时间和资源。
③ 采用参数化测试,使测试用例保持简洁,提高代码可读性。
④ 通过测试套件,减少了测试人员的工作量,一次性执行所有测试用例。
⑤ 使用隐式等待机制,确保页面加载完成,提升了自动化测试的运行效率和稳定性,减少了误报的可能性。
⑥ 采用屏幕截图功能,便于问题追踪和解决。
⑦ 使用无头模式,专注于测试结果,节省屏幕空间。

编写自动化测试不难,但要提高执行速度、更有效地发现问题并避免误报才是挑战。


OK,以上就是本期知识点“个人博客系统测试”的知识啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉如果觉得收获满满,可以点点赞👍支持一下哟~

❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页


http://www.mrgr.cn/news/36159.html

相关文章:

  • 脏读查询SQL SELECT查询配置(DM8:达梦数据库)
  • 第L2周:机器学习|线性回归模型 LinearRegression:1. 简单线性回归模型
  • QT创建线程,QT多线程的创建和使用,QT线程池
  • Kolmogorov-Arnold——代替 MLP以提高模型的代表性和性能
  • 替换jar包中class文件
  • 去年营收增速仅1.4%,成长性恐不足,这家批发业公司终止了
  • 代码随想录冲冲冲 Day55 图论Part7
  • 节点分类、链路预测和社区检测的评价指标
  • 【C++ Primer Plus习题】17.7
  • DBAPI如何实现插入数据前先判断数据是否存在,存在就更新,不存在就插入
  • 机器学习算法与Python实战 | 三万字详解!GPT-5:你需要知道的一切(上)建议收藏!
  • OpenCV4.8 开发实战系列专栏之 01- 环境搭建与图像读写
  • 使用 from __future__ import annotations 语句来允许在类型注释中使用尚未定义的类名
  • centos7安装Redis单机版
  • AI时代下的程序员:如何应对技术变革与提升竞争力
  • 先进封装技术 Part01---“凸块”(Bump)科普
  • 小孩真的需要手机上学吗?怎样远程了解他在学校用iPhone干什么?
  • 工作安排 - 华为OD统一考试(E卷)
  • Educational Codeforces Round 20 F. Coprime Subsequences(DP+容斥)
  • 深入解析网络通信关键要素:IP 协议、DNS 及相关技术