乐于分享
好东西不私藏

Claude Code 的 webapp-testing 到底怎么验收网页?从 CDP 原理到脚本断言讲透

Claude Code 的 webapp-testing 到底怎么验收网页?从 CDP 原理到脚本断言讲透

笔者在大半个月基本属于高度AI编程,为保证效率一直强调少即是多的高效完整工作流闭环的构建。所以对于claude code的使用,也是以日常使用并和AI高度沟通反馈的方式获取最佳高效实践。

本文是笔者近期和claude code高度协作后,工作复盘所感知到的一个skill,注意笔者的说法——自我复盘感知。这也是AI时代的一个技巧,学会和强大的LLM进行沟通反馈,双向进化。

本文将针对Anthropic官方提供的web自动化测试skill webapp-testing展开详细的分析和介绍,我们将从webapp-testing的基本概念进行逐步分析,用一个完整的交互流程串联这个概念,再以一个博客功能改造的完成开发和验收流程介绍该技能的工作原理和直观的视角感知其工作流程。

webapp-testing是什么

webapp-testing是Anthropic官方提供的一个skill(来自anthropics/skills仓库),随官方skill即可用、无需额外安装,是一款web自动化测试技能。其底层是通过python脚本驱动playwright以无头模式操作浏览器内核,完成页面操作与前后端交互的测试验收闭环。

webapp-testing工作原理分析

可能大部分读者听着有些突兀,基于上述的介绍,笔者这里简单介绍一下这里面的核心概念:

  1. Chromium:浏览器内核,我们在页面上看到的点击、输入等交互,本质上都是驱动这个内核去操作html dom、完成前后端网络请求与数据渲染
  2. playwright:微软开源的一款端到端自动化测试工具,能以无头模式驱动Chromium完成页面点击操作。它和Google的Puppeteer师出同门——核心团队就是原Puppeteer团队转投微软后另起的项目,所以两者API很像,别记串成Google的。注意笔者这里强调的无头模式,该模式下浏览器页面是看不到对应的点击交互,一切都是以后台进程的方式完成交互
  3. cdp:全称Chrome DevTools Protocol(Chrome调试协议),是Chromium内核自带的一个"遥控/调试接口",由Chromium项目定义。Edge因为也基于Chromium,所以同样支持它。playwright正是通过CDP给Chromium下达"点击/导航/截图"等指令,你脚本里写的每一句操作,最终都被翻译成CDP指令发给浏览器执行

这三者的关系用一张图串起来更直观,playwright 作为"手"经 CDP 操控 Chromium 内核,结果再回传给脚本做断言:

我们以一个完整的流程介绍一下webapp-testing是如何做到一个完整的自动化测试,假设我们现在驱动claude code完成页面的一个多维度列表查询的功能测试验收,通过webapp-testing其底层操作流程为:

  1. 加载页面后等待networkidle(网络空闲),也就是页面不再发起新的网络请求、JS已把内容渲染填充完毕的那一刻,再开始操作
  2. 编写py脚本,编写要操作的dom
  3. 执行脚本,驱动playwright以cdp协议交互的方式操作页面,触发列表查询
  4. 说到页面反馈数据,claude code读取页面渲染后的dom,断言列表数据是否符合预期(如条数、某行的值),同时截图留档供肉眼复核。验收靠的是对dom的结构化断言,截图是证据、不参与自动判定

整个流程从加载、等渲染到断言验收,串成一条主线如下:

webapp-testing安装与配置

当然,有了AI后,我们完全可以让其主动完成安装然后输出一份安装报告供我们审查,如下所示:

对应执行的命令和脚本如下:

当然,如果不放心的话,我们可以通过terminal终端自行键入指令验收:

➜  ~ ~/.venvs/pw/bin/python -c "import playwright; print(' 库 OK')"

库 OK
➜  ~ ~/.venvs/pw/bin/playwright --version

Version 1.60.0

playwright工作模式

上文我们提到playwright默认是以无头模式执行的,是否可以理解为关闭无头就可以直接感知到浏览器的操作呢?这两种模式的区别如下图:

对此笔者让claude code编写一段关闭无头的浏览器操作脚本。

对应内容如下,可以看到,该脚本执行的如下步骤:

  1. 弹窗打开浏览器
  2. 输入搜索引擎打开百度
  3. 输入nba
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
# 关无头 + 放慢:第 5 步的核心,弹出真窗口让你看清
    b = p.chromium.launch(headless=False, slow_mo=800)
    pg = b.new_page()
# 打开一个能搜索的公开页
    pg.goto("https://www.baidu.com")
# 等页面渲染好(SPA 必做)
    pg.wait_for_load_state("networkidle")
# 你会看到它自己在搜索框打字
    pg.fill("#kw""playwright")
# 自己点"百度一下"
    pg.click("#su")
    pg.wait_for_load_state("networkidle")
# 存张截图当证据
    pg.screenshot(path="/tmp/feel.png")
# 多停 2 秒,让你看清画面
    pg.wait_for_timeout(2000)
    b.close()

完成后我们直接键入如下指令执行:

~/.venvs/pw/bin/python feel.py

可以看到Playwright自带的Chromium顺利打开,且准确键入百度搜索nba:

实践——基于博客发表功能改造详解webapp-testing完整工作流

需求说明

为了直观的演示webapp-testing,笔者就拿一个近期个人专用的写作后台一个功能迭代为例,演示一下webapp-testing的使用。笔者日常维护的文章为了直观看到内容,一般都会选择文章中的一张图作为预览页面。但是既有迭代中并没有考虑到发表封面时给出图片选择这一操作:

所以,本次示例就要求claude code完成如下调整:

  1. 封面url改为图片选择标签
  2. 支持选择文章中任意图片
  3. 修改完成后下次编辑,同时门户页面的封面支持预览

整理上述提示词与claude code进行简单交互后,我们很直观的得到改造方案,整体页面交互的前端思路正确:

同时,针对前端的改法也有做一些去重的处理,因为整体方案都在前端,所以笔者只能默默点击同意(笑):

基于webapp-testing进行测试验收

因为逻辑都在前端,claude code很快完成并通过webapp-testing进行自动化浏览器测试和验收:

为了直观的感知其测试流程是否准确,笔者键入如下提示词:

完成功能开发后,输出你的自动化测试流程,包括但不限于:
1. 说明你的完整的测试前置处理流程
2. 输出你的测试思路,以及脚本编写思路和验收结果
3. 告诉我具体交互的操作流程和验收结果以及你的断言思路

整份报告以html展示,确保我直观了解本次自动化测试信息

对应思路如下,可以看到整体思路是准确的,过滤图片、保存图片、查询验收文章方面图片地址是否存在:

对应笔者也贴出其验收报告:

pg.goto(B+"/login"); pg.fill("input[type='password']", PWD)
# 用户名 = 第一个非 password 输入框
for el in pg.query_selector_all("input"):
if el.get_attribute("type")!="password": el.fill("sharkchili"); break
pg.click("button.el-button--primary")

pg.goto(B+f"/articles/{ART}/edit")
# 关键:等正文真正回填,避免扫到空内容(见 2.4 竞态)
for _ in range(40):
    v = pg.eval_on_selector("textarea","e=>e.value.length")
if v and v > 200: break
    pg.wait_for_timeout(300)

pg.click("button:has-text('发布文章')")
cells = pg.query_selector_all(".cover-cell")
assert len(cells) == 8                 # ② 仅七牛、数量正确
cells[1].click()
assert pg.query_selector(".cover-cell.active")   # 选中高亮
assert pg.query_selector(".cover-preview")       # 顶部预览

更进一步

当然,这也只是AI的一面之词,虽然随着模型的发展,AI的幻觉率少了很多,但是笔者对此还是一直持有怀疑的态度。对于此类问题,笔者一般都采用如下思路:

  1. 人工打开浏览器验证,按照个人验收脚本进行抽检
  2. 关掉无头模式

仔细查阅资料后,笔者发现playwright是可以关闭无头模式,对应配置如下:

b = p.chromium.launch(
    headless=False,   # 关无头:弹出真窗口,你能看见
    slow_mo=800,      # 每步放慢 800ms,看清它"点"的动作
)

本着自动化的事就让自动化的AI处理,于是笔者键入如下提示词:

我想直观的看到你的验收步骤,请将自动化测试脚本以关闭无头模式的方式运行,让我直观看到你的验收步骤。

可以看到,claude code很人性化的在网页顶部说明用意,并执行点击操作:

小结

本文通过一次完整的claude code工作复盘获取最佳实践。这是笔者深度使用AI后,与claude code沟通后了解到的工作细节,为能够更精准地理解并合理地使用,笔者从工作原理、基础实践到实际脚本验证多个角度,对webapp-testing做了系统的讲解与深入分析。

概括来说,webapp-testing的本质是用Playwright通过CDP协议驱动Chromium内核,把网页真打开、真点一遍,再断言结果对不对。原理层面,它靠真浏览器真渲染保证验收可信,动态页(SPA)务必先等networkidle再查DOM,否则查到的是空壳,实践层面,从环境安装、关无头肉眼感知到脚本断言验收,每一步都能自己动手验证。

而比工具本身更重要的,是使用AI的态度。AI给出的验收结论终究只是它的一面之词,笔者对此始终保持怀疑——关掉无头亲眼盯一遍、或按自己的脚本抽检,才是把AI产出落到实处的那一步。AI时代要善用每一次完整的工作闭环构建学习反馈,驱动自己更加高效地使用AI。

SharkChili · 禅与计算机程序设计的艺术

开源项目

  • mini-redis:笔者用 Go 从零手写的教学级 Redis,适合对着源码把缓存与网络底层一行行啃透,欢迎 Star 和交流 · https://github.com/shark-ctrl/mini-redis

关注公众号 写代码的SharkChili ,发送关键字 【加群】 添加笔者好友、进技术交流群。