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

网页聊天室-测试报告

一、项目介绍

RoomChat 是一个基于Spring Boot 3.5.13 + MyBatis + MySQL后端和Next.js 16 + React 19 + Tailwind CSS 4前端的实时网页聊天室应用。采用 WebSocket 实现实时消息推送,支持用户注册登录、好友管理、会话管理和实时消息收发等核心功能。


二、测试计划

本次测试主要从功能测试、界面测试、性能测试、易用性测试、兼容性测试、安全测试这六个方面来进行

2.1 设计测试用例

2.2 执行测试用例

2.2.1 登录页面测试

测试用例一:输入正确的账号和密码

预期结果和实际结果符合

测试用例二:输入正确的账号和错误的密码

预期结果和实际结果符合

测试用例三:输入不存在的用户

预期结果和实际结果符合

测试用例四:输入空的账号和密码

预期结果和实际结果符合

2.2.2 注册页面测试

测试用例一:输入正确的账号和密码

预期结果和实际结果符合

测试用例二:输入已有的账号

预期结果和实际结果符合

测试用例三:输入空的账号或密码

预期结果和实际结果符合

2.2.3 聊天页面测试

测试用例一:添加真实存在的好友

预期结果和实际结果符合

测试用例二:搜索不存在的用户

预期结果和实际结果符合

测试用例三:添加好友时输入空字符串

预期结果和实际结果符合

测试用例四:添加自己为好友

预期结果和实际结果符合

测试用例五:信息正常接收和发送

预期结果和实际结果符合

测试用例六:输入空字符串

无法发送

预期结果和实际结果符合

测试用例七:发送超长信息

自动滚动到最底部

预期结果和实际结果符合

测试用例九:登出功能测试

预期结果和实际结果符合

测试用例十:windows11使用不同浏览器进行测试

预期结果和实际结果符合

测试用例十一:使用手机端进行测试

预期结果和实际结果符合


三、自动化测试

自动化测试可以快速实际输出与预期结果是否一致。它可以大幅提升测试效率、降低重复劳动成本,并支持持续集成与快速回归。本次自动化测试使用的是selenium。

3.1 先引入所需要的依赖

<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>io.github.bonigarcia</groupId> <artifactId>webdrivermanager</artifactId> <version>5.8.0</version> <scope>test</scope> </dependency>

3.2 创建Utils.java基类

核心作用:为所有测试类提供浏览器驱动和截图工具。

关键设计:

public static WebDriver driver = null; // 单例驱动
public WebDriverWait wait = null; // 显式等待
public static String baseUrl = "http://1.14.186.164:8080";

package 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 org.openqa.selenium.support.ui.WebDriverWait; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.time.Duration; public class Utils { public static WebDriver driver = null; public WebDriverWait wait = null; public static String baseUrl = "http://1.14.186.164:8080"; public Utils(String url) { driver = createDriver(); if (url != null && !url.isEmpty()) { driver.get(url); } wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } // 单例创建驱动对象 public static WebDriver createDriver() { if (driver == null) { WebDriverManager.chromedriver().setup(); ChromeOptions options = new ChromeOptions(); options.addArguments("--remote-allow-origins=*"); driver = new ChromeDriver(options); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3)); } return driver; } // 截图保存到 images/日期/方法名-时间戳.png public void screenShot(String str) throws 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/images/" + dirTime + "/" + str + "-" + fileTime + ".png"; File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(srcFile, new File(filename)); } }

3.3 LoginPage.java — 登录页测试

继承关系:LoginPage extends Utils,构造函数 super(url) 导航到登录页。

三个测试方法:

(1) checkPageRight() — 页面元素校验
用 CSS Selector 定位三个关键元素,能找到就说明页面渲染正常。

(2) loginFail() — 登录失败场景

(3) loginSuc() — 登录成功场景

package tests; import common.Utils; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import java.io.IOException; public class LoginPage extends Utils { public static String url = baseUrl + "/"; public LoginPage() { super(url); } // 校验登录页元素是否正常显示(用户名输入框、密码输入框、登录按钮) public void checkPageRight() throws IOException { driver.findElement(By.cssSelector("#username")); driver.findElement(By.cssSelector("#password")); driver.findElement(By.cssSelector("button[type='submit']")); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } // 异常的登录场景:正确的用户名 + 错误的密码 public void loginFail() throws IOException { // driver.findElement(By.cssSelector("#username")).clear(); // driver.findElement(By.cssSelector("#password")).clear(); // React 受控组件用 Ctrl+A 全选覆盖 driver.findElement(By.cssSelector("#username")).sendKeys(Keys.chord(Keys.CONTROL, "a"), "张三"); driver.findElement(By.cssSelector("#password")).sendKeys(Keys.chord(Keys.CONTROL, "a"), "wrongpassword"); driver.findElement(By.cssSelector("button[type='submit']")).click(); String errorMsg = driver.findElement(By.cssSelector( "body > div.min-h-screen.grid.lg\\:grid-cols-2 > div.flex.items-center.justify-center.p-8.bg-background > div > form > div.p-3.text-sm.text-red-400.bg-red-950\\/20.border.border-red-900\\/30.rounded-lg")) .getText(); assert errorMsg.equals("用户名或密码错误"); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } // 正确的用户名和密码登录, 验证跳转到 /chat public void loginSuc() throws IOException { // driver.findElement(By.cssSelector("#username")).clear(); // driver.findElement(By.cssSelector("#password")).clear(); // React 受控组件用 Ctrl+A 全选覆盖 driver.findElement(By.cssSelector("#username")).sendKeys(Keys.chord(Keys.CONTROL, "a"), "张三"); driver.findElement(By.cssSelector("#password")).sendKeys(Keys.chord(Keys.CONTROL, "a"), "123"); driver.findElement(By.cssSelector("button[type='submit']")).click(); // 登录成功会弹出 alert "登录成功!", 接受后跳转到 /chat wait.until(ExpectedConditions.alertIsPresent()); driver.switchTo().alert().accept(); // 等待页面跳转到聊天页 wait.until(ExpectedConditions.urlContains("/chat")); assert driver.getCurrentUrl().contains("/chat"); } }

3.3.1 页面元素校验

3.3.2 登陆失败场景

3.3.3登陆成功场景

3.4 ChatPage.java — 聊天页测试

(1) checkPageRight() — 聊天页加载校验

等 React 渲染出三个关键元素:会话 Tab、好友 Tab、登出按钮。用 XPath 绝对路径定位(从浏览器直接复制的)。

(2) checkSessionList() — 会话列表校验

用 CSS 选择器定位左侧第一个会话按钮,验证会话列表已加载。

(3) checkFriendList() — 好友列表校验

点击"朋友"Tab,等待好友列表中的李四出现。

(4) sendMessage() — 发送消息测试

package tests; import common.Utils; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import java.io.IOException; import java.text.SimpleDateFormat; public class ChatPage extends Utils { public static String url = baseUrl + "/chat"; public ChatPage() { super(url); } // 校验聊天页已加载(会话/朋友Tab、登出按钮) public void checkPageRight() throws IOException { //会话按钮 wait.until(ExpectedConditions.presenceOfElementLocated( By.xpath("/html/body/div[2]/div[4]/div[1]/div[2]/button[1]/div") )); //好友列表 driver.findElement(By.xpath("/html/body/div[2]/div[4]/div[1]/div[2]/button[2]/div[1]")); //登出按钮 driver.findElement(By.xpath("/html/body/div[2]/div[4]/div[1]/div[1]/div/button")); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } // 验证会话列表中包含至少一个会话 public void checkSessionList() throws IOException { WebElement sessionItem = wait.until(ExpectedConditions.presenceOfElementLocated( By.cssSelector("body > div.h-screen.bg-gradient-to-br.from-\\[\\#1a1a2e\\].via-\\[\\#16213e\\].to-\\[\\#0f3460\\].flex.flex-col > div.relative.z-10.flex.flex-1.overflow-hidden > div.w-80.flex-shrink-0.flex.flex-col.bg-white\\/5.backdrop-blur-sm.border-r.border-white\\/10 > div.flex-1.overflow-y-auto.scrollbar-thin > button") )); assert sessionItem.isDisplayed(); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } // 切换到朋友Tab, 验证好友列表包含李四 public void checkFriendList() throws IOException { driver.findElement(By.xpath("/html/body/div[2]/div[4]/div[1]/div[2]/button[2]/div[1]")).click(); WebElement friendItem = wait.until(ExpectedConditions.presenceOfElementLocated( By.xpath("/html/body/div[2]/div[4]/div[1]/div[3]/div/div[2]/button") )); assert friendItem.isDisplayed(); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } // 发送消息给李四, 验证消息出现在聊天区域 public void sendMessage() throws IOException, InterruptedException { // 切回到会话Tab driver.findElement(By.xpath("/html/body/div[2]/div[4]/div[1]/div[2]/button[1]/div")).click(); // 点击李四的会话 WebElement sessionBtn = wait.until(ExpectedConditions.elementToBeClickable( By.cssSelector("body > div.h-screen.bg-gradient-to-br.from-\\[\\#1a1a2e\\].via-\\[\\#16213e\\].to-\\[\\#0f3460\\].flex.flex-col > div.relative.z-10.flex.flex-1.overflow-hidden > div.w-80.flex-shrink-0.flex.flex-col.bg-white\\/5.backdrop-blur-sm.border-r.border-white\\/10 > div.flex-1.overflow-y-auto.scrollbar-thin > button") )); sessionBtn.click(); // 等待聊天区域加载(textarea出现) wait.until(ExpectedConditions.presenceOfElementLocated( By.tagName("textarea") )); // 等待 WebSocket 连接上(聊天头部显示"在线") wait.until(ExpectedConditions.presenceOfElementLocated( By.xpath("//*[contains(text(), '在线')]") )); // 用时间戳生成唯一消息内容, 方便断言 SimpleDateFormat sim = new SimpleDateFormat("HHmmssSS"); String message = "AutoTest消息-" + sim.format(System.currentTimeMillis()); // 输入消息 WebElement textarea = driver.findElement(By.tagName("textarea")); textarea.sendKeys(message); // 点击发送按钮(textarea后面的兄弟button) WebElement sendBtn = textarea.findElement(By.xpath("./following-sibling::button")); sendBtn.click(); // 等待消息出现在聊天区域并截图 Thread.sleep(2000); wait.until(ExpectedConditions.presenceOfElementLocated( By.xpath("//*[contains(text(), '" + message + "')]") )); screenShot(Thread.currentThread().getStackTrace()[1].getMethodName()); } }

3.4.1 聊天页正常加载

3.4.2 会话列表检验

3.4.3 好友列表检验

3.4.4 发送消息测试

3.5 测试入口

main() 方法按顺序执行所有测试,最后关闭浏览器:

[测试] 登录页元素校验...
[测试] 登录失败场景...
[测试] 登录成功场景...
[测试] 聊天页元素校验...
[测试] 会话列表...
[测试] 好友列表...
[测试] 发送消息...

package tests; import common.Utils; import java.io.IOException; public class RunTests { public static void main(String[] args) throws IOException, InterruptedException { System.out.println("===== Roomchat AutoTest 开始 ====="); // 登录模块测试 System.out.println("[测试] 登录页元素校验..."); LoginPage login = new LoginPage(); login.checkPageRight(); System.out.println("[测试] 登录失败场景..."); login.loginFail(); System.out.println("[测试] 登录成功场景..."); login.loginSuc(); // 聊天页模块测试 System.out.println("[测试] 聊天页元素校验..."); ChatPage chat = new ChatPage(); chat.checkPageRight(); System.out.println("[测试] 会话列表..."); chat.checkSessionList(); System.out.println("[测试] 好友列表..."); chat.checkFriendList(); System.out.println("[测试] 发送消息..."); chat.sendMessage(); System.out.println("===== Roomchat AutoTest 结束 ====="); // 关闭浏览器 if (Utils.driver != null) { Utils.driver.quit(); } } }

四、项目bug总结

4.1 密码没有设计加密存储(bug级别:严重)

4.2 无登录防暴力破解(bug级别:严重)

4.3 添加好友的时候可以搜索全部好友(bug级别:一般)

五、性能测试

5.1梯度压测线程组

图解:

00:00 ~ 01:15 0 → 200 阶梯式逐步加压,每步约增加 10-20 线程
01:15 ~ 01:45 保持 200 最大并发持续约 30 秒
01:45 ~ 02:06 200 → 0 快速释放线程

5.2线程的活跃数

加压策略执行正常,符合梯度测试预期

5.3响应时间

整体表现:
低并发阶段(0-100 线程):各接口响应时间基本在 50-200ms 之间,表现良好
中高并发阶段(100-200 线程):响应时间逐渐上升,波动加大
异常峰值:约 01:28 时刻,获取用户信息接口(粉色) 出现 ~1650ms 的尖峰,同时其他接口也有明显抖动

这个表现说明了在1:28时刻,系统达到过载,主要是由于获取用户信息的接口

5.4 吞吐量(TPS 每秒处理的事务)

各接口的 success/failure 曲线在 01:28 后混乱交织,说明:
大量请求开始失败或超时
系统可能出现了线程阻塞、连接池耗尽、数据库锁或服务崩溃
01:28 时刻 TPS 先有一个冲顶(~350+),随后立即崩盘

5.5 聚合报告分析

在线程数为达到最大值时未出现异常

在时间为1:28左右开始出现异常

六、性能测试报告

综合上面分析来看,主要出现在获取用户信息这一接口

该接口变慢 → 占用连接/线程不释放 → 其他接口受影响 → 整体雪崩
崩溃临界点:约 180-200 并发(01:28 左右)

优化点:检查 SQL 执行计划、加索引、优化查询逻辑、增加缓存(Redis)

七、测试总结

本次测试通过 Selenium 编写自动化脚本 对登录、聊天页加载、好友列表、发送消息等核心功能进行了端到端验证;通过 JMeter对主要 REST 接口进行了压力测试,定位到 /userInfo 为性能瓶颈。测试结果表明现有系统在 180并发以下可正常运行,超过该阈值需进行 SQL 优化和引入缓存来提升性能。

附上gitee仓库

网页聊天室:https://gitee.com/wuminzong/spring_boot_roomchat.git

网页聊天室性能测试报告:https://gitee.com/wuminzong/spring_boot_roomchat_performance_test.git

已部署到云服务器:http:1.14.186.164:8080

http://www.gsyq.cn/news/1400433.html

相关文章:

  • 现代作品集重构指南:从展示到论证,打造高价值个人品牌
  • 别再只用if-else了!用Simulink Relay模块给你的控制逻辑加个‘防抖’缓冲区(附C代码生成分析)
  • 宿迁泗洪县黄金 白银 名表 名包 银元 奢侈品回收就选金佑福 - huangjinhs
  • 超时重试:设置请求超时与自动重试机制(Retry策略),爬虫优雅降级之道:超时重试机制的深度实践与源码解析
  • skynet——服务发现学习
  • 腾讯元宝复制带符号文字怎么快速删改?手贱星人有救了!这款“AI导出鸭”气哭CTRL+C/V党
  • 用Unity和C#实现人群疏散模拟:手把手教你搭建社会力模型(附完整代码)
  • WSL2 吃掉我 25GB C 盘空间:一次完整的排查与回收记录
  • AI框架选型新指标:用行为承诺度量化项目健康度
  • UniApp 快速集成个推推送(UniPush2.0)完整实战教程
  • 谁在定义AI硬件的2026?
  • 告别命令行!ESP32-S3安全三件套(Flash加密+Secure Boot V2+NVS加密)的图形化工具配置避坑指南
  • 【Linux】Ext 系列文件系统
  • MTKClient 从入门到精通:联发科设备刷机与逆向工程完全指南
  • 新手避坑指南:在RHEL 6.10上安装Cadence IC618和Verdi 2018.09的完整流程(含依赖库检查)
  • 顺序统计量不等式:Bootstrap与保形预测的理论基石
  • 基于STCO框架构建类型安全提示工程,降低LLM幻觉率30%
  • 基于Whisper、Groq与Streamlit构建本地语音AI助手:从原理到实践
  • UVa 295 Fatman
  • 开发者如何克服完美主义陷阱,构建内在交付体系实现项目上线
  • 2026年5月北京十大装修公司排行榜推荐:十大专业公司评测夜间施工防噪音 - 品牌推荐
  • 为AI编码助手集成运行时日志:从日志采集到智能诊断的工程实践
  • 2026年Python学习指南:从零基础到实战项目,掌握核心语法与工具
  • 苏州可靠的宠物店怎么选 关键因素解析 - 品牌排行榜
  • Tomato-Novel-Downloader:三步构建你的个人小说图书馆
  • 深度解析:3步实现Wallpaper Engine资源逆向工程与高效提取
  • Linux系统重启后,Kubernetes集群核心服务kube-apiserver启动失败的排查与修复
  • 2026年4月国内比较好的AI无损测糖选果机品牌推荐,小柿子选果机/冬枣选果机,AI无损测糖选果机制造商哪家权威 - 品牌推荐师
  • EFM32开发板SWD通信故障排查与优化
  • Python循环不会写?for和while实战技巧大公开