news 2026/8/21 10:04:42

【获取WebSocket】使用 Playwright 监听 Selenium 自动化测试中的 WebSocket 消息(二)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【获取WebSocket】使用 Playwright 监听 Selenium 自动化测试中的 WebSocket 消息(二)

使用 Playwright 监听 Selenium 自动化测试中的 WebSocket 消息(二)

文章目录

  • 使用 Playwright 监听 Selenium 自动化测试中的 WebSocket 消息(二)
    • 六、Selenium 与 Playwright 的生命周期协同设计
      • 6.1 一个常见但不明显的问题
      • 6.2 一个相对稳妥的调用顺序
    • 七、为何需要“按操作切片”的 WebSocket 捕获机制
      • 7.1 问题本质
      • 7.2 基于序号的切片思路
    • 八、WebSocket 消息方向与 Action 字段的处理策略
      • 8.1 抽象消息方向
      • 8.2 关于“空消息”的处理
    • 九、从 WebSocket 消息中提取并统计 Action
      • 9.1 Action 提取与计数
      • 9.2 在测试中的使用方式
    • 十、实现过程中遇到的典型问题与取舍
      • 10.1 CDP 连接失败(ECONNREFUSED)
      • 10.2 关于方案边界的说明

六、Selenium 与 Playwright 的生命周期协同设计

在将 Playwright 引入到现有 Selenium 框架时,真正需要谨慎处理的并不是 API 使用本身,而是两个工具在生命周期上的协同关系

Playwright 的ConnectOverCDPAsync本质上是一个主动连接行为
它假设目标浏览器已经启动,并且在指定端口上暴露了 Chrome DevTools Protocol 服务。

如果在浏览器尚未完成启动、或者启动时未正确携带--remote-debugging-port参数的情况下尝试连接,连接失败是一个合理且可预期的结果。

6.1 一个常见但不明显的问题

在测试框架中,以下两段逻辑往往分散在不同层级:

  • Selenium WebDriver 的创建(通常发生在TestInitialize或更底层)
  • Playwright 的 CDP 连接(通常写在测试辅助类或工具类中)

如果不对调用顺序加以控制,很容易出现如下问题:

  • Playwright 连接逻辑执行得过早
  • 浏览器进程尚未监听调试端口
  • 最终表现为ECONNREFUSED

6.2 一个相对稳妥的调用顺序

在本文的实现中,采用了如下顺序:

  1. 类级别初始化(ClassInitialize)

    • 仅生成调试端口
    • 创建 WebSocket 监听器对象(不做连接)
  2. 用例初始化(TestInitialize)

    • 调用base.TestInitialize(),由 Selenium 启动浏览器
    • 浏览器携带--remote-debugging-port
    • 再显式调用 Playwright 的EnsureConnected()

我们必须选择在浏览器已经处于稳定运行状态后再附加监听。


七、为何需要“按操作切片”的 WebSocket 捕获机制

在真实的前端系统中,WebSocket 消息往往是持续产生的,并不严格对应某一个 UI 操作。

例如:

  • 页面加载完成后的初始化消息
  • 心跳包
  • 其他用户触发的协同事件

如果在测试中直接对“当前页面收到的所有 WS 消息”做断言,很容易引入噪音,难以判断精确地对指定的操作进行验证。

7.1 问题本质

测试关注的并不是“页面是否收到过某类消息”,而是:

“某一个明确的用户操作,是否触发了预期数量和类型的 WebSocket 消息”

因此,测试需要一种方式,将消息流按时间切割

7.2 基于序号的切片思路

在实现中,并未引入复杂的时间戳或异步同步机制,而是采用了一个简单但可控的方式:

  • 为每一条捕获到的 WebSocket 消息分配递增序号
  • 在执行 UI 操作前记录当前序号
  • 操作完成后,仅保留序号大于该值的消息

示例代码如下:

privateList<WsMessage>CaptureCore(ActionuiAction,intwaitMs){varstartSeq=Interlocked.Read(ref_seq);uiAction();Thread.Sleep(waitMs);return_messages.Where(m=>m.Seq>startSeq).OrderBy(m=>m.Seq).ToList();}

这种方式并不能保证“绝对只包含该操作的消息”,
但在大多数前端交互场景下,可以显著降低噪音并提高断言稳定性


八、WebSocket 消息方向与 Action 字段的处理策略

在 Chrome DevTools 中,WebSocket 消息通常以“方向”区分:

  • 客户端 → 服务端
  • 服务端 → 客户端

在 Playwright 中,这一差异体现在两个事件上:

  • FrameSent
  • FrameReceived

8.1 抽象消息方向

在监听器内部,将方向抽象为字符串标识:

classWsMessage{publiclongSeq{get;set;}publicstringMessageType{get;set;}// Sent / ReceivedpublicstringText{get;set;}}

这种抽象并不依赖具体协议细节,仅用于后续过滤与分析。

8.2 关于“空消息”的处理

在实际观察中,一部分 WebSocket 帧内容可能为:

  • {}
  • 空字符串
  • 不包含业务字段的控制帧

这些消息在多数业务断言中并不具备价值,因此在工具方法中提供了可选的过滤能力:

publicIEnumerable<string>OnlyReceived(IEnumerable<WsMessage>list,boolcontainEmpty=false){returnlist.Where(m=>m.MessageType=="Received").Where(m=>containEmpty||(!string.IsNullOrWhiteSpace(m.Text)&&m.Text!="{}")).Select(m=>m.Text);}

这种设计允许测试在“完整保留原始数据”和“聚焦业务字段”之间进行选择。


九、从 WebSocket 消息中提取并统计 Action

在许多实时系统中,WebSocket 消息的核心语义体现在某个字段上,例如:

{"Action":"EditRecord","Data":{...}}

测试关注的往往不是消息的完整结构,而是:

  • 是否出现了某种 Action
  • 出现了几次
  • 是否符合预期行为模型

9.1 Action 提取与计数

实现上,采用了较为保守的 JSON 解析方式:

  • 非 JSON 或结构异常的消息直接忽略
  • 只在存在Action字段时才参与统计
privateDictionary<string,int>CountActions(IEnumerable<string>messages){varresult=newDictionary<string,int>();foreach(vartextinmessages){if(string.IsNullOrWhiteSpace(text)||text=="{}")continue;try{varj=JObject.Parse(text);varaction=(string)j["Action"];if(string.IsNullOrEmpty(action))continue;result[action]=result.GetValueOrDefault(action)+1;}catch{// 非预期结构,忽略}}returnresult;}

9.2 在测试中的使用方式

vartexts=_wsCollector.CaptureTexts(()=>{UIAction();});varactionCount=CountActions(texts);Assert.AreEqual(1,actionCount.GetValueOrDefault("SelectionChange"));Assert.AreEqual(1,actionCount.GetValueOrDefault("EditRecord"));

这种断言方式的优势在于:

  • 明确表达“期望行为的次数”
  • 对多余或缺失消息都具备可观测性

十、实现过程中遇到的典型问题与取舍

10.1 CDP 连接失败(ECONNREFUSED)

通常由以下原因引起:

  • Playwright 连接过早
  • 调试端口未正确注入
  • 使用localhost导致 IPv6 解析问题

在实现中,采用了以下应对方式:

  • 延迟连接到TestInitialize之后
  • 使用127.0.0.1显式指定 IPv4

10.2 关于方案边界的说明

该方案的目标并非替代 Selenium,也不是尝试“全面接管浏览器调试能力”,而是在既有框架和版本约束下,提供一种可控、可维护的 WebSocket 可观测手段。

在以下情况下,可能需要重新评估方案:

  • 对性能指标有强需求
  • 需要跨浏览器(非 Chromium)
  • 希望统一迁移到 Playwright

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 8:36:55

常见模块式地源热泵机组

常见模块式地源热泵机组&#xff1a;灵活高效的清洁能源解决方案在追求节能减排与运营成本优化的今天&#xff0c;模块式地源热泵机组凭借其灵活配置、高效稳定等优势&#xff0c;成为商业建筑、农业恒温及区域能源项目的理想选择。作为地源热泵技术领先企业&#xff0c;瑞冬集…

作者头像 李华
网站建设 2026/8/20 3:31:55

MCP PL-600多模态Agent UI组件设计秘籍,仅限高级工程师知晓的3个技巧

第一章&#xff1a;MCP PL-600多模态Agent UI组件设计概述MCP PL-600 是一款面向复杂任务场景的多模态智能代理系统&#xff0c;其核心在于构建一个高度可交互、语义感知的用户界面&#xff08;UI&#xff09;组件体系。该系统融合视觉、语音、文本等多通道输入&#xff0c;要求…

作者头像 李华
网站建设 2026/8/19 17:12:05

为什么你的量子电路图难以理解?颜色配置错误是关键原因

第一章&#xff1a;量子电路可视化的颜色配置 在量子计算领域&#xff0c;电路可视化是理解量子门操作和量子态演化的重要手段。合理的颜色配置不仅提升电路图的可读性&#xff0c;还能帮助研究人员快速识别不同类型的量子门。许多量子编程框架&#xff08;如Qiskit&#xff09…

作者头像 李华
网站建设 2026/8/19 16:03:17

Docker中运行多模态Agent测试用例,90%团队忽略的3个关键陷阱

第一章&#xff1a;Docker中多模态Agent测试的现状与挑战在当前人工智能系统快速发展的背景下&#xff0c;多模态Agent&#xff08;如结合视觉、语音与自然语言处理能力的智能体&#xff09;逐渐成为复杂应用场景的核心组件。这些Agent通常依赖于高度集成的运行环境&#xff0c…

作者头像 李华
网站建设 2026/8/21 19:10:33

CopilotKit实时协作:重新定义多人AI交互的技术交响曲

想象一下&#xff0c;你正在与团队成员协作编辑一份重要文档&#xff0c;每个人都在向AI助手提出不同的问题&#xff1a;有人需要翻译某个段落&#xff0c;有人在修改格式&#xff0c;还有人要求生成摘要。这时你发现——AI的回复开始混乱&#xff0c;状态同步延迟&#xff0c;…

作者头像 李华
网站建设 2026/8/21 18:41:39

ReoGrid实战指南:轻松搞定.NET电子表格开发难题

还在为.NET应用中的表格功能头疼吗&#xff1f;数据展示不够直观&#xff1f;公式计算太复杂&#xff1f;别担心&#xff0c;ReoGrid这款神器将彻底改变你的开发体验&#xff01;作为一款功能强大的开源电子表格组件&#xff0c;它让复杂的表格开发变得像搭积木一样简单有趣。 …

作者头像 李华