【软件测试】个人博客项目测试报告
目录
1.报告概要
2、测试环境
3、手动测试用例编写
4、自动化测试用例
1.报告概要
测试对象:基于SSM项目的博客系统。
测试目的:检测博客项目是否符合预期,并且对测试知识进行练习和巩固。
测试点:主要针对常用的功能进行测试如:博客项目的注册、登录、博客列表页、博客编辑页、个人列表页、导航栏等进行测试。
测试结果及结论:测试的常用功能全部正常,测试注册页面的密码时,发现密码没有限制长度以及强度的限制。
2、测试环境
硬件:Lenovo Y7000 2020
软件:Windows 、Google Chrome、IDEA
测试工具:自动化测试工具Selenium3
浏览器版本:Google Chrome 118.0.5993.118
3、手动测试用例编写
用户注册页
用户登录页
个人列表页
博客列表页(主页)
博客详情页
博客编辑页
4、自动化测试用例
博客注册页面
package Blog;import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.openqa.selenium.By;import java.util.concurrent.TimeUnit;import static java.lang.Thread.sleep;
//根据程序员指定的顺序执行
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RegCases extends InitAndEnd{/** 注册成功* */@Order(1)@ParameterizedTest@CsvSource({"zhangsan,12345,12345"})void regSuccess(String username,String password,String conPassword ) throws InterruptedException {//打开主页面webDriver.get("http://154.8.139.1:48080/login.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//找到注册按钮webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);sleep(3000);//输入注册的用户名,密码webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.findElement(By.cssSelector("#password2")).sendKeys(conPassword);webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//点击提交webDriver.findElement(By.cssSelector("#submit")).click();sleep(3000);//处理弹窗String test = webDriver.switchTo().alert().getText();String except = "恭喜:注册成功!";webDriver.switchTo().alert().accept();Assertions.assertEquals(except,test);}/*** 用户名为空注册失败* */@Order(2)@ParameterizedTest@CsvSource(value = {"'',123,123","'',123,456","'',546,''","'','',456","'','',''","'张三','',''","'张三','123',''","'张三','123','123'",})void RegFail(String username,String password,String conPassword) throws InterruptedException {//打开主页webDriver.get("http://154.8.139.1:48080/login.html");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);sleep(3000);//找到注册点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//输入用户名、密码、确认密码webDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.findElement(By.cssSelector("#password2")).sendKeys(conPassword);webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);sleep(3000);//处理弹窗//获取弹窗信息String test = webDriver.switchTo().alert().getText();webDriver.switchTo().alert().accept();String except = "恭喜:注册成功!";//断言Assertions.assertNotEquals(except,test);}}
博客登录页面
import static java.lang.Thread.sleep;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogCases extends InitAndEnd{/** 输入正确的账号、密码登录成功* */@Order(1)@ParameterizedTest@CsvFileSource(resources = "LoginSuccess.csv")void LoginSuccess(String username,String password,String blog_list_url) throws InterruptedException {//打开博客登录页面webDriver.get("http://154.8.139.1:48080/login.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//输入账号adminwebDriver.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();sleep(3000);//处理弹窗//用于接受警告对话框(确认)webDriver.switchTo().alert().accept();//跳转到列表页//获取到当前的页面的urlString cur_url = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//判断url是否和预期相等Assertions.assertEquals(blog_list_url,cur_url);}/** 输入错误的密码和账号* */@Disabled@Order(2)@ParameterizedTest@CsvSource(value = {"张帆,123","lisi,123","'',123456","张帆,''","'',''"})void LoginFail(String username,String password) throws InterruptedException {//打开博客登录页面webDriver.get("http://154.8.139.1:48080/login.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();sleep(3000);//处理弹窗//获取弹窗内容String test = webDriver.switchTo().alert().getText();String except = "恭喜,登录成功!";//用于接受警告对话框(确认)webDriver.switchTo().alert().accept();//断言两个字符串的内容不相等,测试通过Assertions.assertNotEquals(except,test);System.out.println("登录不成功");}
个人列表页
/** 博客列表页* */@Testvoid BlogList(){//打开博客列表页webDriver.get("http://154.8.139.1:48080/myblog_list.html");//获取页面上所有博客标题对应的元素webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int title_num = webDriver.findElements(By.cssSelector("title")).size();//如果元素数量不为0,测试通过System.out.println(title_num);Assertions.assertNotEquals(0,title_num);}
博客详情页
/** 博客详情页校验* url* 博客标题* 页面title是"博客详情页"* 用户名* 文章数* */@Order(4)@ParameterizedTest@MethodSource("Generator")void BlogDetail(String expect_url,String expected_title,String expected_blog_title,String except_username ) throws InterruptedException {//找到第一篇博客对应的查看全文按钮webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.xpath("//*[@id=\"artListDiv\"]/div[1]/a[1]")).click();//获取当前页面的URLString cur_url = webDriver.getCurrentUrl();//获取当前页面的titleString cur_title = webDriver.getTitle();//获取博客标题webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String cur_blog_title = webDriver.findElement(By.cssSelector("#title")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//获取用户名String cur_username = webDriver.findElement(By.cssSelector("#username")).getText();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//获取文章数String cur_blog_count = webDriver.findElement(By.cssSelector("#artcount")).getText();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);Assertions.assertEquals(except_username,cur_username);Assertions.assertNotEquals(0,cur_blog_count);if(cur_url.contains(expect_url)){System.out.println("测试通过");}else{System.out.println(cur_url);System.out.println("测试不通过");}Assertions.assertEquals(expected_title,cur_title);Assertions.assertEquals(expected_blog_title, cur_blog_title);}public class BlogCases extends InitAndEnd{public static Stream<Arguments> Generator() {return Stream.of(Arguments.arguments("http://154.8.139.1:48080/blog_content.html","博客正文","自动化测试","张帆"));}
博客编辑页,文章发布完成之后进入博客列表页检测发布文章的标题和时间。
/** 博客编辑页* */@Order(5)@Testvoid EditBlog() throws InterruptedException {//打开博客列表页//webDriver.findElement(By.cssSelector("http://154.8.139.1:48080/myblog_list.html"));webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//找到写博客按钮,点击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("body > div.blog-edit-container > div.title > button")).click();sleep(3000);String cur_text = webDriver.switchTo().alert().getText();webDriver.switchTo().alert().dismiss();String except_text = "恭喜:添加成功!是否继续添加文章?";Assertions.assertEquals(except_text,cur_text);}/** 校验已发布博客标题* 校验已发布博客时间* */@Order(6)@Testvoid BlogInfoChecked(){webDriver.get("http://154.8.139.1:48080/blog_list.html");//获取第一篇博客标题String first_blog_title = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title")).getText();//获取第一篇博客发布时间String first_blog_time= webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.date")).getText();Assertions.assertEquals("自动化测试",first_blog_title);if(first_blog_time.contains("2023-11-02")){System.out.println("测试通过");}else{System.out.println("文章发布时间是:"+first_blog_time);System.out.println("测试不通过");}}
删除功能
/** 测试博客列表页上删除功能* */@Order(7)@Testvoid DeleteCases() throws InterruptedException {//进入个人列表页webDriver.get("http://154.8.139.1:48080/myblog_list.html");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//点击删除按钮webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > a:nth-child(6)")).click();sleep(3000);String text = webDriver.switchTo().alert().getText();webDriver.switchTo().alert().accept();String except_text = "恭喜:删除成功";sleep(3000);String first_blog_title = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title")).getText();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String except_title = "自动化测试";webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);Assertions.assertEquals(except_text,text);Assertions.assertEquals(first_blog_title,except_title);}
注销功能
/** 注销功能测试* */@Order(8)@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);//获取alert()文字String text = webDriver.switchTo().alert().getText();String except_text = "是否确定注销?";webDriver.switchTo().alert().accept();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//校验URL(登录)String cur_url = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//校验提交按钮WebElement webElement = webDriver.findElement(By.cssSelector("#submit"));webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);Assertions.assertEquals(except_text,text);Assertions.assertEquals("http://154.8.139.1:48080/login.html",cur_url);Assertions.assertNotNull(webElement);}
InitAndEnd类
package Blog;import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;import java.util.concurrent.TimeUnit;public class InitAndEnd {static WebDriver webDriver;@BeforeAllstatic void SetUp(){webDriver = new ChromeDriver();}@AfterAllstatic void TearDown(){webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.quit();}
}
问题总结:
❓在测试程序执行报unexpected alert open: {Alert text : 恭喜:删除成功}这种异常,那么就是你没有将这个弹窗关闭掉
✨可以使用accept()方法接受或者dismiss()拒绝
相关文章:

【软件测试】个人博客项目测试报告
目录 1.报告概要 2、测试环境 3、手动测试用例编写 4、自动化测试用例 1.报告概要 测试对象:基于SSM项目的博客系统。 测试目的:检测博客项目是否符合预期,并且对测试知识进行练习和巩固。 测试点:主要针对常用的功能进行测…...

Express框架开发接口之今日推荐等模块
1.初始化 const handleDB require(../handleDB/index) // 获取全部模块 exports.allModule (req, res) > {(async function () {})() } // 更新或者添加模块 exports.upModule (req, res) > {(async function () {})() } // 根据id删除模块 exports.delModule (req, …...

UTONMOS:元宇宙顺势而上,重构数字化发展新形态
元宇宙(Metaverse)是一个虚拟的、且与现实世界平行的虚拟世界,由一系列相互关联的技术组成。在这个虚拟世界中,人们可以通过 VR、 AR等设备进入其中,与虚拟人物进行互动。 随着新一代信息技术的飞速发展,元…...

【Nginx37】Nginx学习:SSL模块(一)简单配置与指令介绍
Nginx学习:SSL模块(一)简单配置与指令介绍 又是一个重点模块,SSL 模块,其实就是我们常见的 HTTPS 所需要的配置模块。HTTPS 的重要性不用多说了吧,现在所有的 App、小程序 都强制要求是 HTTPS 的࿰…...
CompletableFuture 异步调用,获取返回值
ExecutorService executor new ThreadPoolExecutor(8, 16, 60,TimeUnit.MINUTES,new ArrayBlockingQueue<>(100));Random randomnew Random(10);//模拟查询用户列表List<User> listselectUsers();//需要执行的任务列表// 任务列表List<CompletableFuture<Us…...

excel利用正则匹配和替换指定内容
上班中, 突然接到电话, 屋里的上司大人发来个excel, 说要替换里面x-x-xxx列的内容为x栋x单元xxx. 大致表格如下, 原表格我就不发了 身为程序猿的我, 肯定第一就想到了 正则! 打开excel-开始-查找和替换, 我擦, 只能完全匹配和替换 比如一次只能替换1-1- -> 为1栋1单元 1-2…...

IPv4首部格式
IPv4首部格式 IPv4数据报的首部格式及其内容是实现IPv4协议各种功能的基础。 在TCPIP标准中,各种数据格式常常以32比特(即4字节)为单位来描述。 IPv4首部格式图 ## IPv4数据报的组成 主要由固定部分(20字节)可变部分(最大40字节) - 固定部分是指每个IPv4数据报都必…...
点云从入门到精通技术详解100篇-基于 3D 激光雷达的车厢冻煤存量检测
目录 前言 研究意义 研究现状(Research status) 3D 激光雷达检测技术研究现状...

idea使用MyBatisX插件
1.MyBatisX功能 (1).实现mapper和xml的跳转 (2).自动生成java文件,比如mapper、service、dao、pojo 2.安装MyBatisX插件 install后然后重启idea即可 3.使用MyBatieX实现mapper和xml跳转 (1).点击mapper中的红色图标即可跳转到对应的xml方…...

Open3D(C++) 最小二乘拟合平面(间接平差法)
目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。 一、算法原理 1、原理概述 通过传统最小二乘法对点云数据进行平面拟合时,可将误差只归因于一个方向上,本文假设误差只存在于 Z Z...

Linux中搭建coturn服务器
1、下载coturn源码 git clone https://github.com/coturn/coturn.git2、进入到coturn路径下,执行一下命令。 ./configure出现以下错误: 问题1:ERROR: OpenSSL Crypto development libraries are not installed properly in required locati…...

【Proteus仿真】【Arduino单片机】SG90舵机控制
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用SG90舵机等。 主要功能: 系统运行后,舵机开始运行。 二、软件设计 /* 作者:嗨小易(QQ&#x…...

程序员有哪些规避风险的合法兼职渠道?
近期,承德程序员事件冲上热搜,这对许多程序员的心灵是多么大的伤害啊! 人人自危,大家开始顾虑自己接私活、找兼职的方式和前景了。毕竟,谁也不想”辛辛苦苦几十年,一把回到解放前“。那有什么办法既可以接私…...

OpenGL_Learn04
我这边并不是教程,只是学习记录,方便后面回顾,代码均是100%可以运行成功的。 1. 渐变三角形 #include <glad/glad.h> #include <GLFW/glfw3.h>#include <iostream> #include <cmath>void framebuffer_size_callba…...

【嵌入式】HC32F07X CAN通讯配置和使用配置不同缓冲器以连续发送
一 背景说明 使用小华(华大)的MCU HC32F07X实现 CAN 通讯配置和使用 二 原理分析 【1】CAN原理说明(参考文章《CAN通信详解》): CAN是控制器局域网络(Controller Area Network, CAN)的简称,是一种能够实现…...

Linux的常见指令(一)
目录 一、文件 二、常见指令 1、pwd 2、ls 1、ls -a 2、ls -l 3、ls -i 编辑 3、touch 4、mkdir 5、cd 6、rmdir 和 rm 7、man 8、cp 一、文件 目录和文件是在磁盘上建立的,空文件是在磁盘上占用空间的(文件包括文件内容和文件的各种属…...
Jenkins 参数动态获取目录里面的内容
Jenkins 参数动态获取目录里面的内容 假如我们想把一个目录下面的tar.gz文件作为jenkins参数,这个目录会实时更新,每次运行job的时候需要把目录里面的文件作为输入,这时候我们可以使用jenkins自带的Active Choices Parameter参数 在参数中写…...
centos 搭建内网ntp时间服务器
在 CentOS 搭建内网 NTP 时间服务器,你可以按照以下步骤操作: 安装 NTP 服务: 打开终端并以 root 用户身份登录。使用以下命令安装 NTP 服务: sudo yum install ntp配置 NTP 服务器: 打开 NTP 配置文件 /etc/ntp.conf&…...
FreeRTOS-消息队列的使用
1. 定义队列传输的内容和队列结构体对象 使用 xQueueHandle结构体创建对象 typedef struct {u8 TaskNum;u8 Cmd;u8 * buf;}QueueObject_t;xQueueHandle xQueue NULL; 2. 调用xQueueCreate API创建队列 xQueueCreate()函数:用于创建一个消息队列。 QueueHan…...

喜欢 Android 14 的 14 个理由
和去年 8 月中旬发布的 Android 13 正式版不同,今年的 Android 14 正式版延后到了 10 月 4 日——也就是 Pixel 8 系列发布的同一天。原因我们似乎也能从 Google 宣传新特性中略窥一二: 除了明确表示会率先向特定 Pixel 机型推送的 AI 壁纸生成…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...