软件测试相关内容第六弹 -- 测试实战

写在前: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 提供的注解,避免生成多对象,提高测试执行效率
  • 使用等待,提高自动化测试的运行效率,提高了测试的稳定性,一定程度上降低了报错的可能性

自动化测试完结撒花啦 ~ 道虽迩,不行不至;事虽小,不为不成。前路虽道阻且长,希望我们都能找到自己的目标并且为之努力,一定会水到渠成的!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/768869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据结构·排序

1. 排序的概念及运用 1.1 排序的概念 排序&#xff1a;排序是将一组“无序”的记录序列&#xff0c;按照某个或某些关键字的大小&#xff0c;递增或递减归零调整为“有序”的记录序列的操作 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同关键字的记…

day03_mysql_课后练习 - 参考答案

文章目录 day03_mysql_课后练习mysql练习题第1题第2题第3题第4题第5题 day03_mysql_课后练习 mysql练习题 第1题 案例&#xff1a; 1、创建一个数据库&#xff1a;day03_test01_school 2、创建如下表格 表1 Department表的定义 字段名字段描述数据类型主键外键非空唯一D…

Docker 笔记(七)--打包软件生成镜像

目录 1. 背景2. 参考3. 文档3.1 使用docker container commit命令构建镜像3.1.1 [Docker官方文档-docker container commit](https://docs.docker.com/reference/cli/docker/container/commit/)Description&#xff08;概述&#xff09;Options&#xff08;选项&#xff09;Exa…

【Redis】Redis特性

Redis 认识redisRedis特性在内存中存储数据可编程可扩展性持久化Clustering高可用性 认识redis Redis&#xff0c;英文全称是Remote Dictionary Server&#xff08;远程字典服务&#xff09;&#xff0c;是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志…

【JAVA】封装与包

。何为封装呢&#xff1f;简单来说 就是套壳屏蔽细节 封装&#xff1a;将数据和操作数据的方法进行有机结合&#xff0c;隐藏对象的属性和实现细节&#xff0c;仅对外公开接口来和对象进行 交互 访问限定符 public&#xff1a;可以理解为一个人的外貌特征&#xff0c;谁都可以…

【webpack】----错误解决【Cannot read properties of undefined (reading ‘tap‘)】

1. 报错场景 安装 webpack-obfuscator 后&#xff0c;进行 js 代码混淆编译的时候报错。 2. 报错截图 3. 错误原因 通常是由于版本不兼容或配置错误引起的。 4. 查询本地 webpack 版本 4.1 查询命令 npm 查询 npm view webpack versionyarn 查询 yarn info webpack ver…

Java学习笔记 | JavaSE基础语法 | 04 | 数组

文章目录 0.前言1.数组2.数组声明2.1 数组定义2.2 数组初始化1.静态初始化2.动态初始化3.区别4.数组的默认初始化值&#xff1a; 2.3 数组名 3.访问数组3.1 索引3.2 访问数组3.3 length属性 4.数组常见问题5.数组内存分析5.1 内存分配5.2 数组内存分配 6.数组的练习练习1&#…

吴恩达深度学习笔记:神经网络的编程基础2.1-2.4

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第二周&#xff1a;神经网络的编程基础 (Basics of Neural Network programming)2.1 二分类(Binary Classification)2.2 逻辑回归(Logistic Regression)2.3 逻辑回归的代价函数&#xff08;Lo…

MySQL:数据类型

文章目录 数据类型分类数值类型越界访问bit类型小数类型floatdecimal 字符串类型charvarchar 日期enum和set 数据类型分类 在MySQL数据库中&#xff0c;存在各种各样的数据类型&#xff1a; 针对于上述的这么多类型&#xff0c;本篇就对于这些类型的数据进行一一解释&#xff…

STM32--RC522学习记录

一&#xff0c;datasheet阅读记录 1.关于通信格式 2.读寄存器 u8 RC522_ReadReg(u8 address) {u8 addr address;u8 data0x00;addr((addr<<1)&0x7e)|0x80;//将最高位置一表示read&#xff0c;最后一位按照手册建议变为0Spi_Start();//选中从机SPI2_ReadWriteByte(ad…

javaSwing宿舍管理系统(三个角色)

一、 简介 宿舍管理系统是一个针对学校宿舍管理的软件系统&#xff0c;旨在方便学生、宿管和管理员进行宿舍信息管理、学生信息管理以及宿舍评比等操作。该系统使用 Java Swing 进行界面设计&#xff0c;分为三个角色&#xff1a;管理员、宿管和学生。 二、 功能模块 2.1 管…

面向中文大模型价值观的评估与对齐研究:“给AI的100瓶毒药”并解毒,守护AI纯净之心

面向中文大模型价值观的评估与对齐研究&#xff1a;“给AI的100瓶毒药”并解毒&#xff0c;守护AI纯净之心 1.简介 随着Large Language Models&#xff08;LLMs&#xff09;的快速发展&#xff0c;越来越多的人开始担心它们可能带来风险。因此&#xff0c;围绕大模型的“安全…

Collection与数据结构 数据结构预备知识(一) :集合框架与时间空间复杂度

1.集合框架 1.1 什么是集合框架 Java集合框架,又被称为容器,是定义在java.util包下的一组接口和接口实现的一些类.其主要的表现就是把一些数据放入这些容器中,对数据进行便捷的存储,检索,管理.集合框架底层实现原理其实就是各种数据结构的实现方法,所以在以后的学习中,我们会…

QT(3/22)

1>使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数&#xff0c;将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#…

StarRocks 助力金融营销数字化进化之路

作者&#xff1a;平安银行 数据资产中心数据及 AI 平台团队负责人 廖晓格 平安银行五位一体&#xff0c;做零售金融的领先银行&#xff0c;五位一体是由开放银行、AI 银行、远程银行、线下银行、综合化银行协同构建的数据化、智能化的零售客户经营模式&#xff0c;这套模式以数…

【Hadoop大数据技术】——Hadoop高可用集群(学习笔记)

&#x1f4d6; 前言&#xff1a;Hadoop设计之初&#xff0c;在架构设计和应用性能方面存在很多不如人意的地方&#xff0c;如HDFS和YARN集群的主节点只能有一个&#xff0c;如果主节点宕机无法使用&#xff0c;那么将导致HDFS或YARN集群无法使用&#xff0c;针对上述问题&#…

值得参考的golang语言开发规范:Uber Go 语言编码规范,一些优秀的技巧可以提升代码的质量、避免代码缺陷和bug漏洞

值得参考的golang语言开发规范&#xff1a;Uber Go 语言编码规范&#xff0c;一些优秀的技巧可以提升代码的质量、避免代码缺陷和bug漏洞。 Uber Go 语言编码规范 Uber 是一家美国硅谷的科技公司&#xff0c;也是 Go 语言的早期 adopter。其开源了很多 golang 项目&#xff0c;…

UE5 LiveLink 自动连接数据源,以及打包后不能收到udp消息的解决办法

为什么要自动连接数据源&#xff0c;因为方便打包后接收数据&#xff0c;这里我是写在了Game Instance,也可以写在其他地方&#xff0c;自行替换成Beginplay和Endplay 关于编辑器模式下能收到udp消息&#xff0c;打包后不能收到消息的问题有两点需要排查&#xff0c;启动打包后…

Jmeter脚本优化——CSV数据驱动文件

使用 CSV 数据文件设置实现参数化注册 1&#xff09; 本地创建 csv 文件&#xff0c;并准备要使用的数据&#xff0c;这里要参数化的是注册的用户名和邮箱。所以在 csv 文件中输入多组用户名和邮箱。 2&#xff09; 通过测试计划或者线程组的右键添加->配置元件->CSV…

亚信安慧AntDB解析:数据库技术的新里程碑

AntDB简化了开发运维&#xff0c;更提高了数据库的易用性。AntDB是一种创新的数据库管理系统&#xff0c;其设计理念旨在让用户能够更便捷地进行数据库操作&#xff0c;减少繁琐的配置和管理工作&#xff0c;提升工作效率。 通过AntDB&#xff0c;用户可以快速部署和管理数据库…