<!-- title: 官方网页测试件首拆：侦察再动手 -->

# 官方网页测试件首拆：侦察再动手

## 概述

本期是本栏目第二轮单件深拆，对象是 Anthropic 官方 example-skills 插件里的 `webapp-testing`——专门让 Claude Code 替你测试本地 Web 应用的技能。本文材料取自本机安装的 anthropic-agent-skills 插件缓存中该技能的 SKILL.md 正文原文，逐段引用、逐段讲解。核心发现：这个技能真正值钱的不是“会写 Playwright 代码”，而是三条上下文工程纪律——脚本当黑盒不读源码、先侦察后动手、等 `networkidle` 再碰 DOM。它把 LLM 测网页时最常见的三种翻车方式，提前写死在了文档里。

## 一、它是什么，装完长什么样

`webapp-testing` 是 Anthropic 官方技能仓库 anthropics/skills 中 example-skills 目录下的一个技能，定位只有一句话：**测试本地 Web 应用时，写原生 Python Playwright 脚本**。

整个技能的文件结构非常克制：

```
webapp-testing/
├── SKILL.md              # 主文档，约百行
├── scripts/
│   └── with_server.py    # 服务生命周期管理器（支持多服务器）
└── examples/
    ├── element_discovery.py       # 发现页面上的按钮、链接、输入框
    ├── static_html_automation.py  # 用 file:// URL 测本地静态 HTML
    └── console_logging.py         # 自动化过程中捕获控制台日志
```

没有 requirements.txt，没有测试框架封装，没有断言库。SKILL.md 开头就把家底盘出来：

> **Helper Scripts Available**: `scripts/with_server.py` - Manages server lifecycle (supports multiple servers)

一个脚本，三个示例，一页正文。对比市面上动辄塞进十几万 token 的“全能测试框架”型技能，这个官方件的第一个设计决策就是做减法。

安装方式两种，命令如下：

```bash
# 方式一：Claude Code 内走官方插件市场
/plugin marketplace add anthropics/skills
/plugin install example-skills@anthropic-agent-skills

# 方式二：手动安装
git clone https://github.com/anthropics/skills
cp -r skills/example-skills/webapp-testing ~/.claude/skills/

# 前置依赖（Playwright 环境需自备）
pip install playwright
playwright install chromium
```

具体安装入口以仓库 README 为准。装完之后，当你对 Claude Code 说“帮我测一下这个页面能不能正常提交表单”这类任务时，技能就会被触发。

## 二、逐段拆解：九段正文，每段都在堵一个翻车点

### 第 1 段：一句话使命，零废话

正文第一段全部内容就是开头那句"To test local web applications, write native Python Playwright scripts."。没有背景介绍，没有技术选型论述。这是官方件的标准开头写法——第一段只回答“这个技能存在是为了干什么”，把上下文窗口留给后面真正可执行的指令。本栏目此前拆官方 pdf、docx 件时提过“三层渐进披露”，这个件把第一层压到了极限：一句话。

### 第 2 段：黑盒脚本纪律——全文最值钱的一段

紧跟工具清单，出现了整份文档里语气最重的一条规则：

> **Always run scripts with `--help` first** to see usage. DO NOT read the source until you try running the script first and find that a customized solution is abslutely necessary. These scripts can be very large and thus pollute your context window. They exist to be called directly as black-box scripts rather than ingested into your context window.

三个层次：先跑 `--help`；实在不行才读源码；理由是"脚本很大，会污染你的上下文窗口，它们生来就是被直接调用的黑盒，不是被吞进上下文里的”。

这段话值得每个 Skill 作者抄一遍。多数自制技能的通病是让模型把整个仓库读一遍再干活，结果一次任务烧掉几万 token 在读代码上。官方在这里明确把“读源码”定义为最后手段，并且给出了为什么——这是很少见的天真话术，直接把成本模型讲给模型听。顺带一提，原文里 "abslutely" 是个拼写错误，这种未经润色的痕迹反而说明这是工程师手写的操作纪律，不是营销文案。

### 第 3 段：决策树前置——把分支判断变成照表执行

```
User task → Is it static HTML?
    ├─ Yes → Read HTML file directly to identify selectors
    │         ├─ Success → Write Playwright script using selectors
    │         └─ Fails/Incomplete → Treat as dynamic (below)
    │
    └─ No (dynamic webapp) → Is the server already running?
        ├─ No → Run: python scripts/with_server.py --help
        │        Then use the helper + write simplified Playwright script
        │
        └─ Yes → Reconnaissance-then-action: ...
```

SKILL.md 用 ASCII 字符画了一棵决策树，第一刀切“静态还是动态”，第二刀切“服务器起了没有”。两个问题的答案组合出三条路径：静态 HTML 直接读文件找选择器；动态且服务没起就走 with_server.py 托管；动态且服务已起就走“侦察后动手”。

这是把“模型自由发挥空间”收敛成“查表执行”的典型手法。LLM 测网页时最大的不确定性不是代码写不写得出来，而是面对任务时先做什么。决策树把这个顺序写死了。

### 第 4 段：with_server.py 用法——服务器问题的统一解

动态应用测试的老大难是服务生命周期：起服务、等端口就绪、跑测试、杀进程。这个技能用一个辅助脚本统一解决：

```bash
# 单服务
python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py

# 前后端双服务
python scripts/with_server.py \
  --server "cd backend && python server.py" --port 3000 \
  --server "cd frontend && npm run dev" --port 5173 \
  -- python your_automation.py
```

注意设计上的关键一刀，原文写得很清楚：自动化脚本里**只写 Playwright 逻辑，服务器由辅助脚本自动管理**。职责分离之后，模型每次生成的自动化脚本都短一截，出错面也随之缩小。

示例代码里还有两行行内注释，是全文的第二处重语气：

```python
browser = p.chromium.launch(headless=True) # Always launch chromium in headless mode
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle') # CRITICAL: Wait for JS to execute
```

"Always"和"CRITICAL"没有写在散文里，而是写成了代码注释。这是很聪明的双重编码：模型抄这段代码模板时，规则跟着代码一起被抄走；就算模型跳过散文直接看代码，约束也还在。

### 第 5 段：侦察后动手——本技能的灵魂模式

> **Reconnaissance-Then-Action Pattern**: 1. Inspect rendered DOM → 2. Identify selectors from inspection results → 3. Execute actions using discovered selectors

顺序是死的：先看渲染后的真实 DOM（截图 + 抓 content + `page.locator('button').all()`），从侦察结果里挑选择器，最后才执行动作。禁止凭猜测写选择器一步到位。

这一条直击 LLM 自动化测试的最大翻车点：模型很爱“想象”页面结构，直接写出 `page.click('#submit-btn')` 这种看起来合理但页面上根本不存在的选择器，然后陷入“猜选择器—报错—再猜”的死循环。先侦察后动手，等于强制模型用真实页面状态替换想象。

### 第 6 段：Common Pitfall——一正一反各一句话

> ❌ **Don't** inspect the DOM before waiting for `networkidle` on dynamic apps
> ✅ **Do** wait for `page.wait_for_load_state('networkidle')` before inspection

单端动态应用（SPA）的页面在 JS 跑完前是一具空壳，过早抓 DOM 只会得到空列表。技能把这个坑提炼成一对正反例，两行解决。反例对照（❌/✅）是提示词工程里性价比极高的格式：模型对“不要做什么”比对“要做什么”更敏感，成对给出则两头都堵住了。

### 第 7-9 段：Best Practices 与 Reference Files

Best Practices 五条：脚本当黑盒、用 `sync_playwright()` 同步接口、用完关浏览器、选择器优先 `text=`/`role=`/CSS/ID、按需加 `wait_for_selector()`。最后 Reference Files 把三个示例文件的用途一句话讲清，形成正文之外的第二层参考。整个文档首尾呼应：开头说脚本有哪两个，结尾说示例有哪三个，中间没有任何冗余。

## 三、两次调用之间的分工：一张图看懂

```mermaid
flowchart TD
    U["用户下达测试任务"] --> M["模型读 SKILL.md"]
    M --> H["先跑 --help 探测脚本用法"]
    H --> W["with_server.py 托管服务"]
    M --> P["模型只写 Playwright 逻辑"]
    W --> R["服务就绪后自动运行脚本"]
    P --> R
    R --> O["页面结果回传给模型"]
    O --> J{"测试通过吗"}
    J -->|通过| K["汇报测试结论"]
    J -->|失败| M
```

而整个技能对上下文的分层管理，是它区别于民间件的核心结构：

```mermaid
flowchart TD
    A["第一层 SKILL.md 正文"] --> B["第二层 examples 三个示例"]
    B --> C["第三层 with_server.py 源码"]
    C --> D["禁区 默认不读"]
    A --> E["模型常驻上下文 约百行"]
    B --> F["按需查阅某个文件"]
    C --> G["仅定制时才读"]
```

三层各管一摊：正文常驻、示例按需、源码禁区。这就是本栏目拆官方 pdf 件时说过的“渐进披露”，在测试场景下的具体落地。

## 四、评测表

| 维度 | 权重 | 评分 | 简评 |
|------|------|------|------|
| 功能完整度 | 25% | ★★★★☆ | 静态/动态/多服务全覆盖，但只管行为不管像素，无性能与移动端 |
| 设计质量 | 25% | ★★★★★ | 决策树、黑盒纪律、注释军规、反例对照，教科书级上下文工程 |
| 实战效果 | 20% | ★★★★☆ | 侦察再动手直击 LLM 测网页最大翻车点；效果依赖本机 Playwright 环境装好 |
| 上手难度 | 15% | ★★★★☆ | 概念零门槛，但需自备 Python + Playwright + Chromium 环境 |
| 社区活跃度 | 15% | ★★★★☆ | 官方 example-skills 插件渠道分发，随官方仓库更新，属长期维护件 |

横向参照同门：docx/pdf 件的强项是文档格式的边界处理，pptx 系的强项是模板化产出，而 webapp-testing 的强项是**把失败模式前置写死**——五件官方件里，它的正文最短，但每句话的“防翻车密度”最高。

## 五、适用与不适用

**适合交给它**：本地开发中的功能回归（表单提交、登录流程、增删改查走通）、前后端双服务联调冒烟、改完前端之后“页面还能不能用”的快速验证、CI 前的本地预演。

**不要指望它**：像素级视觉还原走查（它只管行为不管审美）、线上生产环境监控（定位是 local web applications）、性能压测（Playwright 不是压测工具）、移动端真机测试。另外它假设你本地能装 Playwright，环境装不好，技能写得再好也白搭。

## 六、给 Skill 作者的五个可抄模式

1. **黑盒脚本纪律**：辅助脚本配 `--help`，正文明写“先跑 help、禁读源码”，并讲出理由（上下文污染）。一次任务省下的 token 是真实的钱。
2. **决策树前置**：把任务分叉写成 ASCII 决策树放在正文前部，模型照表执行，不再自由发挥顺序。
3. **注释即军规**：把 "Always"“CRITICAL” 级别的约束写进示例代码的行内注释，让规则随代码模板一起被复制。
4. **反例对照**：❌/✅ 成对出现，一条坑两行讲完。
5. **三层披露**：正文常驻 → 示例按需 → 源码禁区，每个文件在正文里都有一句话定位。

## 七、设计件价值排名

把 webapp-testing 拆成五个设计件，按“抄走后对自己技能的提升幅度”排名：

| 排名 | 设计件 | 为什么值钱 |
|------|--------|-----------|
| 1 | 黑盒脚本纪律 | 所有带脚本的技能都适用，直接省上下文成本 |
| 2 | 侦察再动手 | 任何“先看再改”类任务（测网页、改代码、爬数据）通用 |
| 3 | 决策树前置 | 任务有分叉就能用，把自由度换成确定性 |
| 4 | 注释即军规 | 有示例代码的技能都该抄 |
| 5 | ❌✅对照 | 短小，适合所有已知高频翻车点 |

## 参考来源

1. [anthropics/skills — Anthropic 官方技能仓库](https://github.com/anthropics/skills) — webapp-testing 所在的 example-skills 插件来源仓库
2. [webapp-testing/SKILL.md（example-skills 路径下）](https://github.com/anthropics/skills/blob/main/example-skills/webapp-testing/SKILL.md) — 本文逐段引用的正文的规范存放位置，本文材料同时取自本机 anthropic-agent-skills 插件缓存中同名文件
3. [Playwright for Python 官方文档](https://playwright.dev/python/) — 技能所依赖的 sync API、networkidle、locator 概念出处

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
