尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

网页聊天项目测试实战:WebSocket长连接与自动化测试经验总结

发布时间:2026/9/29 20:01:03

资讯中心
01
ARTICLE

网页聊天项目测试实战:WebSocket长连接与自动化测试经验总结

网页聊天项目测试实战:WebSocket长连接与自动化测试经验总结
网页聊天项目的测试和普通后台管理系统的项目测试真不是一回事。我近一年多接手过两三个带长连接的网页聊天项目从手工功能测试一路做到自动化测试项目落地踩了不少坑也沉淀了一套可复用的打法。这篇就把我在实际测试中的思路、细节、代码和排查经验完整写出来给准备做聊天类Web项目测试、或者刚被分到这类任务的自动化测试工程师做个参考。先说结论网页聊天项目的测试难点不在“点按钮”上而在消息收发链路、连接状态管理和异常场景处理上。普通Web页面是“发请求→等响应→看结果”聊天页面的核心是WebSocket长连接服务器会主动推送数据页面状态随时可能被远端事件改变。这就导致测试的观察维度更多、状态组合爆炸、偶发问题极难复现。如果你还是习惯性地把用例写成“打开页面→输入→点击→断言”那大概率会在消息时序和断线重连两个环节翻车。1. 想清楚再动手网页聊天项目的测试全貌拆解1.1 先认清网页聊天项目到底“难”在哪很多人接手聊天项目测试时会觉得功能无非就是登录、加好友、发消息、建群比电商系统还简单。这是典型的低估。聊天项目的复杂度隐藏在用户看不见的地方登录鉴权之后客户端要和服务端建立一条长连接这条连接什么时候建、什么时候断、断了之后怎么办都是测试点。消息不是“发出去就行”消息要经过客户端本地回显、服务端ack确认、接收端实时推送、离线消息补拉、未读计数更新等多个环节每一步都可能出问题。多端登录时A端发的消息B端、C端能不能同时收到被踢下线时连接是否立即关闭网络切换、App后台运行、服务器重启这些场景下客户端的重连策略是否符合预期是聊天项目最容易出线上事故的地方。举个例子。我接手的一个项目中用户A连续发送消息时服务端推送顺序偶尔会乱。手工测试时很难稳定复现因为需要消息足够密集、网络恰好有延迟。后来我在协议层测试里用脚本连续发送50条带序号的消息再断言客户端收到的服务端ack顺序与发送顺序一致才稳定复现并让开发定位到是网关层并发处理导致的乱序。这种测试思路在普通CRUD项目中是根本用不上的。1.2 测试分层与工具选型不要一把梭网页聊天项目测试我建议分成四个层级来做每层用不同的武器层级覆盖内容工具/手段稳定性手工探索测试交互体验、视觉还原、新功能冒烟人工 浏览器DevTools低靠人接口与协议层自动化登录鉴权、消息收发协议、WebSocket事件、离线补拉pytest requests websocket-client高UI端到端自动化用户视角的完整流程、多标签页双用户场景Playwright中高性能与稳定性测试长连接数量、消息吞吐、重连风暴、弱网Locust / JMeter 自写脚本中为什么我推荐Playwright而不是Selenium因为Playwright自带两个关键能力对于聊天项目测试非常有用一是多浏览器上下文BrowserContext可以在同一个测试进程里模拟两个完全隔离的用户天然适合做双用户聊天测试二是网络拦截与模拟离线context.setOffline可以很方便地模拟断网场景这是Selenium要做半天才能做到的事。Cypress也不错但它在多标签页和多浏览器上下文方面相对受限而且对WebSocket的原生调试支持没有Playwright顺手。1.3 测试矩阵设计先把场景列全再写自动化代码很多自动化项目失败不是因为代码写得不好而是因为场景没想清楚就开工。我建议在写任何自动化测试代码之前先输出一份测试矩阵把聊天项目的测试空间铺开。从用户视角切场景至少包括注册/登录/登出正常流程、错误密码、会话过期、多端登录互踢单聊文字消息、表情、图片/文件、撤回、删除、已读回执群聊成员管理、消息、全员消息、退群/被移出会话管理置顶、免打扰、未读计数、历史记录分页系统通知好友申请、群邀请、服务端公告从系统视角垂直切分层每类场景还要再补充协议层、异常层、合规层、性能层的用例。我习惯用一个表格来管理场景ID场景名称测试层级前置条件关键步骤预期结果优先级CHAT-001用户A发送文字消息给用户B协议层UI层A、B在线且已建立连接A发送“你好”B的聊天窗口显示“你好”服务端ack消息ID一致P0CHAT-002A发送消息过程中断网异常层A在线消息输入完成发送瞬间断网10秒后恢复消息不丢失恢复后自动重发且不产生重复消息P0CHAT-003未登录用户访问聊天页面安全合规层清空所有本地凭证直接访问聊天路由被重定向到登录页且不会发起WebSocket连接P0这里有一个实际遇到的情况有些演示环境为了图省事会临时放开登录限制做成“不用登录就能进聊天页”。如果你的测试环境也是这样请务必留个心眼在正式环境用例中把“未登录访问拦截”标为P0绝不能因为演示环境放开就跳过。聊天数据极其敏感没有鉴权的聊天页面本身就是严重事故。2. 核心细节解析聊天测试要盯死这几个关键环节2.1 登录与鉴权聊天项目的“第一道闸门”登录在聊天项目里不只是一个“输密码”的页面它决定了后续长连接的身份合法性。测试时要重点关注以下几件事第一token与会话的生命周期。聊天页面的WebSocket连接通常是在登录成功后、页面加载时建立的。token过期后页面是直接断开连接还是静默刷新token后重连这两种设计都有但结果完全不同。我们用Playwright做过一个用例把token的过期时间改为1分钟登录后等到token过期再发送一条消息断言页面是否自动重新连接、消息是否发送成功。结果发现这个项目的token刷新和WebSocket重连是分开实现的token刷新成功但连接没有重建导致发送的消息一直卡在“发送中”状态。这就是典型的生命周期割裂Bug。第二多端登录互踢。很多聊天产品支持同账号多端在线也有一部分产品会互踢。测试点是A端和B端同时在线时A端被踢下线B端还能不能正常收发消息被踢的提示是什么连接是否关闭被踢后重新登录是否有冲突这里有极容易出问题的点互踢逻辑如果只判断了“当前会话”而没有判断“连接状态”就可能导致踢掉一个端后另一个端的连接也被误关。第三会话保持期间的Cookie与本地存储。我建议在自动化测试中用Playwright的storageState存储状态来模拟已登录状态而不是每次都走一遍登录流程。这样既节省时间又可以把登录用例和聊天用例解耦。但要注意一个坑如果项目把token存在localStorage里而你的测试上下文之间不小心复用了同一个storageState文件那么两个“用户”就会变成同一个身份双用户测试直接失效。后面我会专门讲这个坑。2.2 消息收发顺序、幂等与丢失一个都不能少消息链路是聊天项目最核心的业务测试时我会拆成三段来看发送端用户输入内容→点击发送→本地立即回显灰色状态→收到服务端ack→本地消息状态变为“已发送”。服务端收到消息→校验内容→存储入库→推送接收端→返回ack。接收端收到推送→更新UI→更新未读数。每一段都有对应的测试断言。UI层测试只能看到最终结果而协议层测试能看到每个环节的消息Payload。我的习惯是UI层做用户视角的端到端用例协议层做详细的消息字段断言。消息顺序是必测项。消息顺序是必测项尤其在高频发送场景下。我先在协议层写一个脚本用户A连续发送50条消息每条消息带一个自增序号然后断言用户B收到的消息序号严格递增。如果发现乱序再配合服务端日志定位是网关并发导致还是数据库查询排序问题。这种“带序列号的消息风暴”测试是聊天项目测试的独门绝技。消息幂等性也值得单独立用例。用户快速双击发送按钮或者断线后重发消息是否会导致接收端收到两条相同消息我们在测试中就发现过一个场景弱网下客户端把一条消息重发了三次服务端没有做幂等校验接收端显示了三条一模一样的消息。这个Bug在手工测试里偶尔能碰到但无法稳定复现用脚本控制重发时间间隔后基本百分之百复现。2.3 断线重连与心跳最容易在线上翻车的环节如果说消息收发是聊天项目的面子那断线重连就是里子。用户不会没事断网但移动网络切换、Wi-Fi不稳、服务器发布重启随时都在发生。这些场景下的表现直接决定用户对产品的信任。断线重连的测试要点是客户端是否能感知到断线如果不能那么服务器推送的消息会一直“静默丢失”。重连策略是否符合预期是固定间隔重试还是指数退避最大重试次数是多少重试期间UI有没有提示重连成功后离线期间的消息能不能补拉补拉的顺序对不对未读数是否合并重连风暴问题大量客户端同时断线后如果都在同一时间点重连服务端可能直接被冲垮。测试时如果用脚本模拟100个客户端同时断网再同时恢复很容易暴露这个问题。我在测试中模拟断网通常用三种方式Playwright的context.setOffline(true)适合UI层测试能模拟浏览器级别的断网。直接用防火墙规则或代理工具断开指定端口适合模拟真实网络故障。在协议层测试中直接关闭WebSocket连接再重新连接适合测试客户端的重连逻辑是否健壮。心跳机制的测试比较容易被忽略。心跳是客户端和服务端维持连接的手段但心跳超时时间的设定很讲究太短会频繁误判太长会导致连接假死。测试时可以重点观察网络断开后客户端是否要等心跳超时才感知到断线这个“感知时间”是否符合预期如果心跳间隔是30秒那么用户断网后最多要等30秒才能看到“连接断开”的提示还不算更长的超时阈值这个体验问题只能通过测试暴露。2.4 合规与内容安全测试聊天项目必做且不能应付任何带用户生成内容的项目都会涉及内容安全聊天是重中之重。测试时不能只在后台配几个敏感词就完事要从用户视角和平台视角各测一遍。用户视角的测试点包括发送包含敏感词的文本系统是直接拦截还是替换拦截后是否有提示提示是否说明原因发送同音字、谐音变体、拼音、图片中的文字这些变体是否能被识别这部分的测试数据通常需要和安全策略团队确认不能凭感觉造数据。平台视角的测试点包括用户被处罚后应该看到什么提示被禁言后是仅限制发言还是也限制私聊封禁是否区分账号封禁和设备封禁申诉流程是否通畅举报一条消息后被举报方是否会收到通知这里我要专门提醒一点内容过滤不能只依赖前端或单次接口调用。有些项目为了提高响应速度会在前端先做一次过滤如果后端没有兜底用户绕过前端直接调WebSocket接口发送消息就能绕过内容过滤。协议层测试里一定有一条用例直接通过WebSocket发送一份包含敏感词的消息Payload断言服务端拦截或告警。我自己就曾经用websocket-client绕过前端页面成功发送了本该被拦截的消息当时开发还挺惊讶其实这类问题在协议层测试中非常常见。3. 自动化测试项目实操记录从环境搭建到测试报告3.1 环境准备造一个“脏而不乱”的测试环境自动化测试跑得稳不稳环境占一半。聊天项目的测试环境尤其需要隔离否则测试数据和开发数据混在一起用例必然翻车。我推荐用Docker Compose把整套服务拉起来前端Nginx容器、后端服务容器、Redis、数据库。关键点是配置隔离——数据库用独立的测试库、Redis用独立的db或key前缀、端口不要和开发环境冲突。测试环境里还要准备一份相对稳定的基础数据一个个位数数量的用户池、一些好友关系、一个带有几十条历史消息的会话。不要每次跑测试都从零注册用户那会让用例又慢又不稳定。基础数据建议用脚本统一初始化不要靠手工在页面里造数据。我在项目里写了一个seed_data.py通过后端接口批量创建用户和好友关系。这样任何开发或测试同事拉新环境跑一遍脚本就能获得一份可预期的测试数据。3.2 实战一双用户单聊全链路脚本Playwright这是我最常用也最推荐新手先写的一条用例两个隔离的浏览器上下文模拟用户A和用户B完成一次完整的单聊。from playwright.sync_api import sync_playwright def test_single_chat_between_two_users(): with sync_playwright() as p: # 创建两个隔离的浏览器上下文模拟两个用户终端 ctx_a p.chromium.launch().new_context() ctx_b p.chromium.launch().new_context() page_a ctx_a.new_page() page_b ctx_b.new_page() # 登录用户A和用户B实际项目建议复用storageState这里为了可读性直接走登录 page_a.goto(http://localhost:8080/login) page_a.fill(#username, alice) page_a.fill(#password, pass123) page_a.click(#login-btn) page_a.wait_for_selector(.chat-list) page_b.goto(http://localhost:8080/login) page_b.fill(#username, bob) page_b.fill(#password, pass123) page_b.click(#login-btn) page_b.wait_for_selector(.chat-list) # 用户A打开与B的会话窗口发送消息 page_a.click(textbob) page_a.fill(#message-input, 你好这是自动化测试消息) page_a.click(#send-btn) # 用户B的会话列表出现未读打开会话窗口验证消息内容 page_b.wait_for_selector(text你好这是自动化测试消息, statevisible) assert page_b.locator(.message-content).last.inner_text() 你好这是自动化测试消息这个脚本的核心在于两个隔离的context它们拥有独立的Cookie、localStorage和WebSocket连接能真实模拟两个用户在线。断言部分不要一开始就去检查复杂的消息状态位先把“消息能送达且展示正确”跑通再逐步增加断言。踩过的一个坑是因为两个context的浏览器进程是分开的如果用户A发送消息后用户B不是立即收到而是有几百毫秒的延迟此时如果断言写得太着急比如is_visible()立刻执行用例就会偶发失败。解决办法是用Playwright自动等待机制也就是wait_for_selector、expect(locator).to_contain_text这种带轮询的断言不要自己在代码里time.sleep(2)。固定等待是自动化测试不稳定的最大来源。3.3 实战二WebSocket协议层的自动化测试UI层用例稳定性再好也总有“鞭长莫及”的地方——比如直接验证服务端推送给客户端的消息内容。所以我始终建议聊天项目至少保留一套协议层测试。用websocket-client库写一个在线状态与消息推送的用例比UI层更轻量也更贴近真实网络行为import json import websocket import pytest WS_URL ws://localhost:8080/ws?tokentest_token_alice def test_websocket_receives_pushed_message(): ws websocket.create_connection(WS_URL, timeout10) try: # 模拟客户端发起一条聊天消息 ws.send(json.dumps({ type: chat.message, to: bob, content: 协议层测试消息, client_msg_id: msg_001 })) # 等待服务端ack断言消息ID一致 ack json.loads(ws.recv()) assert ack[type] chat.message_ack assert ack[client_msg_id] msg_001 # 等待服务端将消息推送给接收端这里需要另一个连接模拟bob接收实际测试中单独实现 # 此处仅演示ack链路 finally: ws.close()协议层测试的核心优势是稳。没有UI渲染、没有动画、没有定位器断言的就是数据本身。很多UI层偶发失败的问题在协议层能一次性定位到是前端渲染问题还是后端推送问题。断线重连测试在协议层写起来也非常顺手。大致的思路是创建连接→接收一条消息→主动断开→断言客户端在预期时间内发起了新的连接请求。如果你的客户端提供了WebSocket的心跳事件日志测试结果会非常清晰。3.4 测试报告Allure集成与失败定位聊天项目测试用例跑起来之后最痛苦的事是失败之后不知道是哪一环出了问题。所以我从第一天就要求所有自动化用例都要输出结构化报告用Allure。具体做法是在UI层用例的关键步骤加allure.attach把页面截图、控制台日志、网络请求记录挂到步骤下面在协议层用例中把发送和接收到的每条WebSocket消息原始Payload都记录下来作为附件加上。这样一次失败点开报告就能看到是页面元素没找到UI问题还是消息根本没推过来协议问题或是推过来了但内容不对业务逻辑问题Allure的命令也很简单在pytest运行后生成报告pytest tests/ --alluredir ./allure-results allure serve ./allure-results我给团队定的规矩是UI层用例失败必须能一眼看到截图协议层用例失败必须能一眼看到消息Payload。看不到这两样东西的用例干脆不要提交到CI里去省得挂了没人能查。4. 常见问题与排查技巧实录4.1 表格速查典型故障现象与排查路径问题现象可能原因排查方法解决方案UI用例偶发失败重跑就过固定sleep等待时间不足后台定时器刷新DOM查看失败截图对比页面加载时机改用Playwright的自动等待断言去除time.sleep双用户测试中A发的消息B没收到两个上下文不小心复用了同一份storageStateB用户实际没有建立WebSocket连接检查两个context的cookie及token加日志输出当前登录用户保证每个测试用独立的storageState文件消息偶发乱序服务端网关并发推送顺序没做保证协议层发送50条带序号消息断言顺序修复服务端有序推送增加序号校验字段断线重连后收不到离线消息重连成功但未触发消息补拉或补拉接口token失效抓取重连后的WebSocket消息及HTTP请求检查重连逻辑中是否重新注册消息同步大量客户端同时重连服务端CPU飙升重连风暴客户端退避策略失效用脚本模拟100个客户端同时断线恢复客户端增加抖动和指数退避服务端限流4.2 让自动化测试“稳如老狗”的实操经验第一能走协议层测试的不要到UI层做断言。消息推送、ack顺序、幂等、离线补拉这些在协议层测稳定且定位快。UI层只负责验证“用户看到的界面状态是正确的”。第二所有涉及时间的用例要预先设计好时间控制方案。聊天项目有一堆跟时间相关的逻辑会话过期、消息撤回超时、未读计数清理。如果直接用真实时间用例会非常难维护。一个办法是在测试环境注入一个可控的时间源比如让后端支持一个模拟时间参数测试时可以自由把时间快进到5分钟之后验证撤回是否失败。第三日志是一切排查的基础。聊天项目最怕“现象出现了但不知道发生了什么”。我要求测试环境必须能从后端日志中查到每一条消息的流转记录发送→入库→推送→ack并在用例失败时自动抓取对应时间段的后端日志。没有日志辅助的聊天项目测试就像蒙着眼睛排查故障效率极低。4.3 我亲自踩过的三个坑第一个坑是storageState复用导致的“双用户变单用户”。我一开始图省事让所有测试用例共用一份登录态的storageState文件结果跑双用户用例时用户B收到消息后页面上显示的用户名居然还是A。排查了半天才发现两个context加载了同一份localStoragetoken完全一样服务端把两个连接当成了同一个用户。从那以后我为每个测试用户单独维护storageState文件并在用例开头断言两个context的token不一致。第二个坑是WebSocket消息乱序导致的断言焦虑。有段时间UI用例跑一次挂一次失败原因都是“发送的消息和收到的消息不一致”。我一度以为是产品逻辑出问题了后来在协议层用带序号的消息脚本一测发现100条消息里偶尔有1-2条顺序颠倒。这个概率在UI手工测试里根本感觉不到但自动化脚本每次收消息都严格按顺序断言自然就频频亮红灯。现在我写断言时会区分“消息最终一致”和“消息严格有序”两个级别不会一上来就用最严格的断言把用例拖垮。第三个坑是测试环境与开发环境共用Redis导致未读计数时好时坏。开发同事在页面上的一次随意操作就能把我这边精心构造的测试数据冲掉。后来我把测试环境的所有基础设施完全独立出来并加了部署脚本一键重建这个问题才算根治。环境隔离这件事越早做越省心千万别等项目跑起来之后再补。最后分享一个我常用的“时间压缩”测试技巧如果你在测试网页聊天项目时觉得断线重连的用例很难测可以试着把服务端的心跳间隔参数从默认的30秒改成5秒把重连退避的初始间隔从5秒改成1秒。这样原本需要几分钟才能触发一次断线感知的用例现在十几秒就能稳定复现。我在两个项目里都用过这个办法效果立竿见影而且不需要改任何业务代码只需在测试环境增加一个配置项。网页聊天项目的测试做到最后拼的不是工具用得多花哨而是对聊天业务链路每一环的理解有多深。把登录鉴权、消息收发、断线重连、内容安全这些核心场景的测试矩阵铺完整再用协议层测试稳住底座用UI层测试验证体验这个项目的测试质量就差不到哪里去。希望这篇实战记录能给正在做类似项目的你一点参考。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。