{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "AI 测研社",
  "home_page_url": "https://ceyanshe.com/",
  "feed_url": "https://ceyanshe.com/feed.json",
  "description": "AI 测研社专注测试与质量场景的 AI 工作流实践，通过真实项目研究需求分析、测试执行、多源数据校验、失败定位和报告生成的智能化。",
  "icon": "https://ceyanshe.com/logo.svg",
  "items": [
    {
      "title": "关于我",
      "url": "https://ceyanshe.com/about.html",
      "id": "https://ceyanshe.com/about.html",
      "summary": "关于我 我是一名从软件测试出发，持续实践 AI 工程化和自动化工作流的技术从业者。 这个网站用于公开记录真实项目、操作过程、问题排查和阶段性成果，希望帮助更多传统测试工程师理解并使用 AI。 关注方向 🧪 AI 测试与智能断言 🔧 Claude Code、Codex、MCP、Skills 实战 🔗 AI 自动化工作流 📊 数据质量与校验 📝 ...",
      "content_html": "\n<p>我是一名从软件测试出发，持续实践 AI 工程化和自动化工作流的技术从业者。</p>\n<p>这个网站用于公开记录真实项目、操作过程、问题排查和阶段性成果，希望帮助更多传统测试工程师理解并使用 AI。</p>\n<h2>关注方向</h2>\n<ul>\n<li>🧪 AI 测试与智能断言</li>\n<li>🔧 Claude Code、Codex、MCP、Skills 实战</li>\n<li>🔗 AI 自动化工作流</li>\n<li>📊 数据质量与校验</li>\n<li>📝 技术写作与知识沉淀</li>\n</ul>\n<h2>内容原则</h2>\n<ol>\n<li><strong>真实项目</strong>：所有内容尽量来自真实测试场景</li>\n<li><strong>真实结果</strong>：展示实际运行结果，包括失败和踩坑过程</li>\n<li><strong>真实限制</strong>：明确标注当前能力边界，不夸大 AI 效果</li>\n<li><strong>可重复执行</strong>：代码和配置可以在读者自己的环境中运行</li>\n</ol>\n",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "AI 工作流",
      "url": "https://ceyanshe.com/ai-workflow-basics.html",
      "id": "https://ceyanshe.com/ai-workflow-basics.html",
      "summary": "AI 工作流 AI 工作流栏目负责介绍实现 AI 工作流需要掌握的通用知识——从理解什么是 AI 工作流，到掌握 Agent、MCP、Skills 和提示词工程。 AI 工作流不是单次对话，也不是只生成一段代码，而是能够被重复执行、验证结果并保留记录的完整流程。 AI 工作流入门 推荐文章 理解 AI 测试的核心概念、工具生态与学习路线，迈出从传统测试...",
      "content_html": "\n<p>AI 工作流栏目负责介绍实现 AI 工作流需要掌握的通用知识——从理解什么是 AI 工作流，到掌握 Agent、MCP、Skills 和提示词工程。</p>\n<p><strong>AI 工作流不是单次对话，也不是只生成一段代码</strong>，而是能够被重复执行、验证结果并保留记录的完整流程。</p>\n",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "学习交流",
      "url": "https://ceyanshe.com/community.html",
      "id": "https://ceyanshe.com/community.html",
      "summary": "加入 AI 测研社学习交流 交流 AI 测试、Claude Code、Codex、MCP、Skills 与自动化工作流实战。 交流方式 我们目前通过以下方式交流： 💬 在博客文章下方留言讨论 📧 邮件交流：TODO（联系方式待补充） 🌐 关注博客更新 加入原则 欢迎分享真实项目和踩坑经验 鼓励提出具体问题和改进建议 不欢迎纯粹的广告和引流行为 目...",
      "content_html": "\n<p>交流 AI 测试、Claude Code、Codex、MCP、Skills 与自动化工作流实战。</p>\n",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "企业落地",
      "url": "https://ceyanshe.com/enterprise.html",
      "id": "https://ceyanshe.com/enterprise.html",
      "summary": "企业落地研究 AI 测研社关注的是 AI 工作流在企业测试场景中的实际落地，不是演示性的单次操作。 当前内容以案例研究、方案设计和原型验证为主，后续将通过真实项目逐步沉淀可复用的工作流模板和实施方法。 企业测试场景 企业中常见的测试流程问题： 测试用例编写和更新成本高，需求变更后人工维护效率低 自动化脚本开发和维护困难，框架升级和页面变化导致大量返工 ...",
      "content_html": "\n<p>AI 测研社关注的是 AI 工作流在企业测试场景中的实际落地，不是演示性的单次操作。</p>\n<p><strong>当前内容以案例研究、方案设计和原型验证为主</strong>，后续将通过真实项目逐步沉淀可复用的工作流模板和实施方法。</p>\n",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "关于 AI 测研社",
      "url": "https://ceyanshe.com/intro.html",
      "id": "https://ceyanshe.com/intro.html",
      "summary": "关于 AI 测研社 以测求真，以研促用 AI 测研社是一个专注于 AI 测试工程化的技术实践平台。 &quot;测&quot;代表软件测试与真实测评，&quot;研&quot;代表技术研究与方法沉淀。我们不只介绍工具，更通过真实项目验证 Claude Code、Codex、MCP、Skills 和智能体在软件测试中的实际价值。 品牌价值观 以测求真：通...",
      "content_html": "\n<h2>以测求真，以研促用</h2>\n<p><strong>AI 测研社</strong>是一个专注于 AI 测试工程化的技术实践平台。</p>\n<p>&quot;测&quot;代表软件测试与真实测评，&quot;研&quot;代表技术研究与方法沉淀。我们不只介绍工具，更通过真实项目验证 Claude Code、Codex、MCP、Skills 和智能体在软件测试中的实际价值。</p>\n<h3>品牌价值观</h3>\n<ol>\n<li><strong>以测求真</strong>：通过真实测试验证工具效果</li>\n<li><strong>以研求深</strong>：研究原理并沉淀可复用方法</li>\n<li><strong>实战优先</strong>：所有内容尽量来自真实项目</li>\n<li><strong>持续进化</strong>：记录传统测试向 AI 测试转型的过程</li>\n</ol>\n<h3>关注领域</h3>\n<ul>\n<li>🧪 <strong>测试框架</strong>：Playwright、Cypress、Selenium</li>\n<li>🤖 <strong>AI 工具</strong>：Claude Code、OpenAI Codex CLI、Cursor</li>\n<li>🔌 <strong>MCP 开发</strong>：自定义 MCP Server 与 Skills</li>\n<li>🏗️ <strong>Agent 构建</strong>：AI Testing Agent 设计与实现</li>\n<li>📊 <strong>CI/CD</strong>：GitHub Actions、Jenkins</li>\n</ul>\n",
      "image": "https://ceyanshe.com/assets/images/cover3.jpg",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "Claude Code + Playwright MCP 安装与验证",
      "url": "https://ceyanshe.com/ai-testing/claude-code-playwright-mcp-setup.html",
      "id": "https://ceyanshe.com/ai-testing/claude-code-playwright-mcp-setup.html",
      "summary": "Claude Code + Playwright MCP 安装与验证 前言 上一篇文章我们聊了 ，这篇就动手实践——安装 Claude Code CLI 并配置 Playwright MCP Server。 完成本文后，你将能用自然语言驱动 Playwright 完成 Web 自动化测试。 环境准备 系统要求 Node.js 18+ （推荐 20 LT...",
      "content_html": "\n<h2>前言</h2>\n<p>上一篇文章我们聊了 <a href=\"/ai-testing/guide/why-traditional-testers-learn-ai-testing.html\" target=\"_blank\">为什么要学 AI 测试</a>，这篇就动手实践——<strong>安装 Claude Code CLI 并配置 Playwright MCP Server</strong>。</p>\n<p>完成本文后，你将能用自然语言驱动 Playwright 完成 Web 自动化测试。</p>\n<h2>环境准备</h2>\n<h3>系统要求</h3>\n<ul>\n<li>Node.js 18+ （推荐 20 LTS）</li>\n<li>npm 或 pnpm</li>\n<li>Git</li>\n<li>VS Code（可选，但强烈推荐用于编辑配置文件）</li>\n</ul>\n<h3>检查环境</h3>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">node</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --version</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 应输出 v18.x 或 v20.x</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npm</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --version</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 应输出 9.x 或 10.x</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>第一步：安装 Playwright MCP Server</h2>\n<p>Playwright MCP Server 是微软官方提供的 MCP 服务器，让 AI 模型能直接控制浏览器。</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 全局安装 Playwright MCP Server</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npm</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> -g</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> @anthropic/mcp-server-playwright</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 安装 Playwright 浏览器</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npx</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> playwright</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> chromium</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>验证安装</h3>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npx</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> @anthropic/mcp-server-playwright</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --version</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>如果输出版本号，说明安装成功。</p>\n<h2>第二步：配置 Claude Code</h2>\n<h3>创建配置文件</h3>\n<p>在用户目录下创建 <code>.claude.json</code> 配置文件：</p>\n<div class=\"language-json line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"json\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-json\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  \"mcpServers\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    \"playwright\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"command\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"npx\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"args\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"-y\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"@anthropic/mcp-server-playwright\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"env\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><div class=\"hint-container tip\">\n<p class=\"hint-container-title\">配置文件位置</p>\n<ul>\n<li><strong>Windows</strong>: <code>%USERPROFILE%\\.claude.json</code></li>\n<li><strong>macOS/Linux</strong>: <code>~/.claude.json</code></li>\n</ul>\n</div>\n<h3>验证 MCP 连接</h3>\n<p>启动 Claude Code 后，检查 MCP 工具是否已加载：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">claude</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>在交互界面中输入 <code>/mcp</code>，应该能看到 <code>playwright</code> 服务器及它提供的工具列表：</p>\n<ul>\n<li><code>browser_navigate</code> - 导航到 URL</li>\n<li><code>browser_click</code> - 点击元素</li>\n<li><code>browser_type</code> - 输入文本</li>\n<li><code>browser_screenshot</code> - 截图</li>\n<li><code>browser_evaluate</code> - 执行 JavaScript</li>\n</ul>\n<h2>第三步：第一个 AI 驱动的测试</h2>\n<h3>测试目标</h3>\n<p>用自然语言让 Claude Code + Playwright 完成以下操作：</p>\n<ol>\n<li>打开百度首页</li>\n<li>搜索 &quot;AI 测试&quot;</li>\n<li>验证搜索结果不为空</li>\n<li>截图保存</li>\n</ol>\n<h3>执行</h3>\n<p>在 Claude Code 中输入：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>请使用 Playwright 完成以下测试：</span></span>\n<span class=\"line\"><span>1. 导航到 https://www.baidu.com</span></span>\n<span class=\"line\"><span>2. 在搜索框输入 \"AI 测试\"</span></span>\n<span class=\"line\"><span>3. 点击搜索按钮</span></span>\n<span class=\"line\"><span>4. 等待结果加载</span></span>\n<span class=\"line\"><span>5. 截图保存为 baidu-search-result.png</span></span>\n<span class=\"line\"><span>6. 告诉我搜索结果的标题列表</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>预期结果</h3>\n<p>Claude Code 会自动：</p>\n<ol>\n<li>启动浏览器</li>\n<li>执行每个步骤</li>\n<li>截图并保存</li>\n<li>返回搜索结果文本</li>\n</ol>\n<h2>进阶：编写 MCP 测试配置</h2>\n<p>将浏览器测试封装到项目的 MCP 配置中：</p>\n<div class=\"language-json line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"json\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-json\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// .mcp.json（项目根目录）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  \"mcpServers\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    \"playwright\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"command\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"npx\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"args\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"-y\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"@anthropic/mcp-server-playwright\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"env\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">        \"PLAYWRIGHT_BROWSERS_PATH\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"0\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>常见问题</h2>\n<h3>Q: <code>npx playwright install</code> 报错？</h3>\n<p>确保网络环境正常，或使用国内镜像：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">set</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright/</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npx</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> playwright</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> chromium</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>Q: Claude Code 连不上 MCP Server？</h3>\n<p>检查 <code>.claude.json</code> 路径是否正确，以及 MCP Server 是否成功安装：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npx</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> @anthropic/mcp-server-playwright</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --help</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><h3>Q: 浏览器启动失败？</h3>\n<p>可能是缺少系统依赖。Linux 用户请运行：</p>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npx</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> playwright</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install-deps</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> chromium</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><h2>小结</h2>\n<p>完成本文的操作后，你已经：</p>\n<ul>\n<li>✅ 安装了 Playwright MCP Server</li>\n<li>✅ 配置了 Claude Code 的 MCP 连接</li>\n<li>✅ 用自然语言完成了第一个 AI 驱动的浏览器测试</li>\n<li>✅ 了解了常见问题的解决方法</li>\n</ul>\n<p><strong>下一步：</strong> 尝试用 Claude Code + Playwright 测试你自己的项目，体验 AI 测试的实际效率提升。</p>\n",
      "date_published": "2026-07-16T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "AI 开发工具"
      ]
    },
    {
      "title": "测试实战",
      "url": "https://ceyanshe.com/ai-testing/test-practice.html",
      "id": "https://ceyanshe.com/ai-testing/test-practice.html",
      "summary": "测试实战 测试实战栏目按照真实测试场景分类，展示 AI 工作流在具体测试领域中的应用。 每一个场景都围绕可运行、可校验、可重复的目标展开，不限于某一种工具。 UI 自动化工作流 推荐文章 用自然语言描述测试任务，让 Claude Code 通过 Playwright MCP 操作真实浏览器，完成页面识别、登录、数据提取和可重复执行的测试脚本。 接口测试...",
      "content_html": "\n<p>测试实战栏目按照真实测试场景分类，展示 AI 工作流在具体测试领域中的应用。</p>\n<p>每一个场景都围绕<strong>可运行、可校验、可重复</strong>的目标展开，不限于某一种工具。</p>\n",
      "date_published": "2026-07-27T10:58:20.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": []
    },
    {
      "title": "AI 测试博客从创建到上线操作手册",
      "url": "https://ceyanshe.com/notes/how-to-build-ai-testing-blog.html",
      "id": "https://ceyanshe.com/notes/how-to-build-ai-testing-blog.html",
      "summary": "AI 测试博客从创建到上线操作手册 [!summary] 最终成果 使用 VuePress 2 + VuePress Theme Hope 创建中文 AI 测试博客，将源码保存到 GitHub，并通过 Cloudflare Pages 免费部署。 当前网站：https://ai-test-blog.pages.dev 一、整体流程 各平台的作用： 二、...",
      "content_html": "\n<blockquote>\n<p>[!summary] 最终成果<br>\n使用 <strong>VuePress 2 + VuePress Theme Hope</strong> 创建中文 AI 测试博客，将源码保存到 GitHub，并通过 Cloudflare Pages 免费部署。</p>\n<p>当前网站：<a href=\"https://ai-test-blog.pages.dev\" target=\"_blank\" rel=\"noopener noreferrer\">https://ai-test-blog.pages.dev</a></p>\n</blockquote>\n<h2>一、整体流程</h2>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>本地创建 VuePress 博客</span></span>\n<span class=\"line\"><span>→ 使用 Claude Code 修改内容和配置</span></span>\n<span class=\"line\"><span>→ 本地预览并执行生产构建</span></span>\n<span class=\"line\"><span>→ Git 提交并推送到 GitHub</span></span>\n<span class=\"line\"><span>→ Cloudflare Pages 自动部署</span></span>\n<span class=\"line\"><span>→ 获得 pages.dev 公开访问地址</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>各平台的作用：</p>\n<p>| 工具 | 作用 |<br>\n|</p>\n",
      "date_published": "2026-07-22T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "测试成长"
      ]
    },
    {
      "title": "Obsidian 使用腾讯云 COS 搭建图床：安装、配置与图片管理",
      "url": "https://ceyanshe.com/notes/obsidian-cos-image-hosting-setup.html",
      "id": "https://ceyanshe.com/notes/obsidian-cos-image-hosting-setup.html",
      "summary": "使用 Tencent COS for Imgur 插件，将 Obsidian 中粘贴或拖入的图片自动上传到腾讯云 COS，并完成 CORS、存储路径和访问权限配置。",
      "content_html": "\n<p>写 Obsidian 笔记时，直接粘贴截图虽然方便，但图片会不断堆积在本地仓库中。时间一长，不仅仓库越来越大，Git 同步、跨设备访问和文章发布也会变得麻烦。</p>\n<p><a href=\"https://github.com/bobostudio/obsidian-imgur-plugin\" target=\"_blank\" rel=\"noopener noreferrer\">Tencent COS for Imgur</a> 是一款由 bobostudio 开发的 Obsidian 插件。它可以把粘贴或拖入笔记的图片自动上传到腾讯云 COS，并将本地图片引用替换为云端链接。</p>\n<figure><img src=\"https://github.com/bobostudio/obsidian-imgur-plugin/raw/master/images/banner2.png\" alt=\"Tencent COS for Imgur 插件\" tabindex=\"0\" loading=\"lazy\"><figcaption>Tencent COS for Imgur 插件</figcaption></figure>\n<p>本文从零完成一次配置，并在最后验证图片能否正常上传。</p>\n<h2>一、它能解决什么问题</h2>\n<p>配置完成后，在 Obsidian 中复制粘贴或拖入图片，插件会自动完成：</p>\n<ol>\n<li>将图片上传到腾讯云 COS；</li>\n<li>生成图片的云端访问地址；</li>\n<li>把地址插入当前 Markdown 笔记；</li>\n<li>在图片管理面板中统一查看和删除图片。</li>\n</ol>\n<p>插件还支持：</p>\n<ul>\n<li>PNG、JPG、JPEG、GIF、SVG、WebP 等图片格式；</li>\n<li>PDF、音视频、Office 文档、ZIP 等多格式文件；</li>\n<li>自定义 COS 存储路径；</li>\n<li>本地笔记和在线笔记备份；</li>\n<li>图片链接有效期设置；</li>\n<li>拖拽调整本地或在线图片的显示大小；</li>\n<li>将笔记中的外链图片同步到 COS。</li>\n</ul>\n<blockquote>\n<p>[!tip]<br>\n如果笔记需要发布为博客，使用自己的 COS 比依赖第三方公共图床更可控；如果笔记含有私人截图，则要谨慎选择存储桶权限。</p>\n</blockquote>\n<h2>二、开始前需要准备什么</h2>\n<p>你需要准备：</p>\n<ul>\n<li>一个腾讯云账号；</li>\n<li>已开通的<a href=\"https://console.cloud.tencent.com/cos\" target=\"_blank\" rel=\"noopener noreferrer\">对象存储 COS</a>；</li>\n<li>一个 COS 存储桶；</li>\n<li>腾讯云 API 的 <code>SecretId</code> 和 <code>SecretKey</code>；</li>\n<li>桌面端或移动端 Obsidian。</li>\n</ul>\n<p>整个配置过程可以概括为：</p>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>创建 COS 存储桶</span></span>\n<span class=\"line\"><span>      ↓</span></span>\n<span class=\"line\"><span>获取 SecretId / SecretKey</span></span>\n<span class=\"line\"><span>      ↓</span></span>\n<span class=\"line\"><span>配置存储桶 CORS</span></span>\n<span class=\"line\"><span>      ↓</span></span>\n<span class=\"line\"><span>安装并配置 Obsidian 插件</span></span>\n<span class=\"line\"><span>      ↓</span></span>\n<span class=\"line\"><span>测试连接并粘贴图片</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>三、创建 COS 存储桶</h2>\n<p>进入<a href=\"https://console.cloud.tencent.com/cos\" target=\"_blank\" rel=\"noopener noreferrer\">腾讯云 COS 控制台</a>，创建一个存储桶。创建时重点记住下面两个参数：</p>\n<p>| 参数 | 示例 | 说明 |<br>\n|</p>\n",
      "image": "https://github.com/bobostudio/obsidian-imgur-plugin/raw/master/images/banner2.png",
      "date_published": "2026-07-24T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "测试成长"
      ]
    },
    {
      "title": "从本地写作到自动上线：VuePress 博客自动部署完整记录",
      "url": "https://ceyanshe.com/notes/vuepress-github-actions-blog-deployment-guide.html",
      "id": "https://ceyanshe.com/notes/vuepress-github-actions-blog-deployment-guide.html",
      "summary": "从本地写作到自动上线：VuePress 博客自动部署完整记录 本文记录「AI 测研社」博客从本地写文章，到 GitHub Actions 自动构建并部署至云服务器的完整过程。 完成配置以后，日常更新博客只需要： 一、最终实现效果 自动化链路跑通后，不再需要手动执行以下工作： 手动上传文章到服务器。 手动执行 VuePress 构建。 手动复制 dist...",
      "content_html": "\n<p>本文记录「AI 测研社」博客从本地写文章，到 GitHub Actions 自动构建并部署至云服务器的完整过程。</p>\n<p>完成配置以后，日常更新博客只需要：</p>\n<div class=\"language-text line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"text\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-text\"><span class=\"line\"><span>本地写文章 → Git 提交并推送 → GitHub Actions 构建 → 自动部署 → 网站更新</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><h2>一、最终实现效果</h2>\n<div class=\"language-mermaid line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"mermaid\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-mermaid\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">flowchart LR</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    A[\"本地 PyCharm&#x3C;br/>编写 Markdown\"] --> B[\"Git 提交\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    B --> C[\"推送到 GitHub&#x3C;br/>main 分支\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    C --> D[\"GitHub Actions&#x3C;br/>安装依赖并构建\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    D --> E[\"SSH + rsync&#x3C;br/>上传静态文件\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    E --> F[\"1Panel / OpenResty&#x3C;br/>提供网站访问\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    F --> G[\"ceyanshe.com&#x3C;br/>展示最新内容\"]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>自动化链路跑通后，不再需要手动执行以下工作：</p>\n<ul>\n<li>手动上传文章到服务器。</li>\n<li>手动执行 VuePress 构建。</li>\n<li>手动复制 <code>dist</code> 文件。</li>\n<li>每次更新都登录 1Panel。</li>\n</ul>\n<h2>二、整体环境</h2>\n<p>| 项目 | 当前使用方案 |<br>\n|</p>\n",
      "date_published": "2026-07-24T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "测试成长"
      ]
    },
    {
      "title": "我用 VuePress、GitHub Actions 和阿里云搭建了 AI 测研社",
      "url": "https://ceyanshe.com/notes/%E6%88%91%E7%94%A8VuePress-GitHub-Actions%E5%92%8C%E9%98%BF%E9%87%8C%E4%BA%91%E6%90%AD%E5%BB%BA%E4%BA%86AI%E6%B5%8B%E7%A0%94%E7%A4%BE.html",
      "id": "https://ceyanshe.com/notes/%E6%88%91%E7%94%A8VuePress-GitHub-Actions%E5%92%8C%E9%98%BF%E9%87%8C%E4%BA%91%E6%90%AD%E5%BB%BA%E4%BA%86AI%E6%B5%8B%E7%A0%94%E7%A4%BE.html",
      "summary": "从本地 Markdown 写作、GitHub Actions 自动构建，到阿里云服务器自动发布，完整复盘 AI 测研社的建站与持续部署过程。",
      "content_html": "\n<blockquote>\n<p>本文记录我从 WordPress 转向 VuePress，并使用 GitHub Actions 将网站自动部署到阿里云服务器的完整过程。最终实现的效果是：本地修改 Markdown，推送到 GitHub，网站自动构建并发布，全程不需要手动上传文件。</p>\n</blockquote>\n<h2>一、为什么要搭建 AI 测研社</h2>\n<p>我希望建立一个长期更新的个人技术网站，用来记录和分享以下内容：</p>\n<ul>\n<li>AI 测试工程化</li>\n<li>Claude Code、Codex、MCP 和 Skills 实战</li>\n<li>n8n AI 自动化工作流</li>\n<li>PPT 与视频自动化</li>\n<li>测试工程师的成长与转型</li>\n</ul>\n<p>网站不只是一个博客，也是我后续沉淀项目案例、建立个人品牌和验证商业化方向的基础。</p>\n<p>我最初尝试过 WordPress。WordPress 的后台编辑和插件生态很方便，但对于以 Markdown、代码和技术文档为主的网站，我更希望获得以下能力：</p>\n<ul>\n<li>文章直接以 Markdown 文件保存</li>\n<li>可以使用 Git 管理所有修改记录</li>\n<li>页面是静态文件，服务器压力更小</li>\n<li>本地可以使用 Obsidian、Typora、VS Code 或 Claude Code 写作</li>\n<li>推送代码后能够自动构建和部署</li>\n</ul>\n<p>因此，我最终选择了：</p>\n<blockquote>\n<p>VuePress + GitHub + GitHub Actions + 阿里云 + 1Panel/OpenResty</p>\n</blockquote>\n<h2>二、最终技术架构</h2>\n<p>整个发布流程如下：</p>\n<div class=\"language-mermaid line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"mermaid\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-mermaid\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">flowchart LR</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    A[\"本地 Markdown\"] --> B[\"GitHub 仓库\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    B --> C[\"GitHub Actions 构建\"]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    C --> D[\"阿里云静态网站\"]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>各部分的作用如下：</p>\n<p>| 组件 | 作用 |<br>\n|</p>\n",
      "image": "https://ceyanshe.com/assets/images/vuepress-github-actions-aliyun-cover.png",
      "date_published": "2026-07-26T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "建站实战",
        "AI 开发工具"
      ]
    },
    {
      "title": "我用 Claude Code + Playwright MCP 跑通了第一次真实 UI 测试",
      "url": "https://ceyanshe.com/ai-testing/guide/first-real-ui-test-with-claude-code-playwright-mcp.html",
      "id": "https://ceyanshe.com/ai-testing/guide/first-real-ui-test-with-claude-code-playwright-mcp.html",
      "summary": "我用 Claude Code + Playwright MCP 跑通了第一次真实 UI 测试 以前编写 UI 自动化测试，通常需要先分析页面、寻找元素、编写定位器，再组织测试流程。 这一次，我尝试把测试任务直接交给 Claude Code，让它通过 Playwright MCP 操作真实浏览器，完成页面识别、登录和商品信息获取。 本文记录完整实践过程，...",
      "content_html": "\n<p>以前编写 UI 自动化测试，通常需要先分析页面、寻找元素、编写定位器，再组织测试流程。</p>\n<p>这一次，我尝试把测试任务直接交给 Claude Code，让它通过 Playwright MCP 操作真实浏览器，完成页面识别、登录和商品信息获取。</p>\n<p>本文记录完整实践过程，包括：</p>\n<ul>\n<li>如何配置并验证 Playwright MCP</li>\n<li>如何把测试需求描述给 Claude Code</li>\n<li>Claude Code 如何识别页面元素</li>\n<li>如何完成 SauceDemo 登录测试</li>\n<li>如何将一次 AI 操作沉淀成可重复执行的自动化脚本</li>\n<li>实践过程中遇到的问题</li>\n</ul>\n<h2>一、这次要完成什么任务</h2>\n<p>测试网站使用公开的自动化练习网站：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>https://www.saucedemo.com/</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><p>本次目标是验证下面这条业务链路：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>打开登录页</span></span>\n<span class=\"line\"><span>→ 输入用户名和密码</span></span>\n<span class=\"line\"><span>→ 点击登录</span></span>\n<span class=\"line\"><span>→ 进入商品列表</span></span>\n<span class=\"line\"><span>→ 验证页面加载成功</span></span>\n<span class=\"line\"><span>→ 获取商品名称和价格</span></span>\n<span class=\"line\"><span>→ 输出测试结果</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>测试账号：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>用户名：standard_user</span></span>\n<span class=\"line\"><span>密码：不要在文章或截图中公开展示</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><p>注意：SauceDemo 是公开演示网站，但真实项目中的账号、密码、Token 等敏感数据都应该使用环境变量保存，不能直接写进代码或提交到 GitHub。</p>\n<h2>二、我的实践环境</h2>\n<p>本次使用的主要工具：</p>\n<p>| 工具                     | 作用                                   |<br>\n|</p>\n",
      "date_published": "2026-07-22T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "传统测试工程师为什么要学习 AI 测试",
      "url": "https://ceyanshe.com/ai-testing/guide/why-traditional-testers-learn-ai-testing.html",
      "id": "https://ceyanshe.com/ai-testing/guide/why-traditional-testers-learn-ai-testing.html",
      "summary": "传统测试工程师为什么要学习 AI 测试 前言 如果你是一名传统软件测试工程师，每天的工作是写测试用例、执行回归测试、维护自动化脚本——你可能会问：AI 测试跟我有什么关系？ 答案是：关系很大，而且比你想象的更紧迫。 这篇文章将从一个传统测试工程师的视角，聊聊为什么现在就应该开始学习 AI 测试。 测试行业的现状 传统测试的痛点 重复劳动占比高：大量的回...",
      "content_html": "\n<h2>前言</h2>\n<p>如果你是一名传统软件测试工程师，每天的工作是写测试用例、执行回归测试、维护自动化脚本——你可能会问：<strong>AI 测试跟我有什么关系？</strong></p>\n<p>答案是：<strong>关系很大，而且比你想象的更紧迫。</strong></p>\n<p>这篇文章将从一个传统测试工程师的视角，聊聊为什么现在就应该开始学习 AI 测试。</p>\n<h2>测试行业的现状</h2>\n<h3>传统测试的痛点</h3>\n<ol>\n<li><strong>重复劳动占比高</strong>：大量的回归测试、冒烟测试仍然依赖手工执行</li>\n<li><strong>用例维护成本高</strong>：需求变更后，测试用例和自动化脚本的更新往往滞后</li>\n<li><strong>覆盖度难以保证</strong>：靠人工分析很难做到全面覆盖，边界 case 容易被遗漏</li>\n<li><strong>效率瓶颈明显</strong>：测试执行速度受限于人力和环境资源</li>\n</ol>\n<h3>AI 带来的变革</h3>\n<p>AI 正在从以下几个方面改变测试：</p>\n<p>| 领域 | 传统方式 | AI 增强方式 |<br>\n|</p>\n",
      "date_published": "2026-07-15T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "使用 AI 分析测试失败原因",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/ai-failure-analysis.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/ai-failure-analysis.html",
      "summary": "使用 AI 分析测试失败原因 将测试失败日志、截图和差异数据交给大模型，辅助定位失败根因并给出修复建议。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项...",
      "content_html": "\n<p>将测试失败日志、截图和差异数据交给大模型，辅助定位失败根因并给出修复建议。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "自动采集测试结果与截图",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/collect-test-results-and-screenshots.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/collect-test-results-and-screenshots.html",
      "summary": "自动采集测试结果与截图 在测试执行过程中自动采集接口响应、页面截图、日志和断言结果。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过程整理，...",
      "content_html": "\n<p>在测试执行过程中自动采集接口响应、页面截图、日志和断言结果。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "从 0 到 1 创建 AI Testing Agent",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/creating-ai-testing-agent-from-scratch.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/creating-ai-testing-agent-from-scratch.html",
      "summary": "从 0 到 1 创建 AI Testing Agent 前言 前面两篇文章我们分别讨论了： 现在，是时候更进一步了——创建一个能独立完成测试任务的 AI Testing Agent。 什么是 AI Testing Agent？ AI Testing Agent 是一个能够： 🧠 理解测试需求——解析自然语言描述的测试场景 🔧 自主选择工具——决定使...",
      "content_html": "\n<h2>前言</h2>\n<p>前面两篇文章我们分别讨论了：</p>\n<ul>\n<li><a href=\"/ai-testing/guide/why-traditional-testers-learn-ai-testing.html\" target=\"_blank\">为什么要学 AI 测试</a></li>\n<li><a href=\"/ai-tools/claude-code/claude-code-playwright-mcp-setup.html\" target=\"_blank\">Claude Code + Playwright MCP 安装与验证</a></li>\n</ul>\n<p>现在，是时候更进一步了——<strong>创建一个能独立完成测试任务的 AI Testing Agent。</strong></p>\n<h2>什么是 AI Testing Agent？</h2>\n<p>AI Testing Agent 是一个能够：</p>\n<ol>\n<li>🧠 <strong>理解测试需求</strong>——解析自然语言描述的测试场景</li>\n<li>🔧 <strong>自主选择工具</strong>——决定使用哪个测试框架、哪个浏览器</li>\n<li>📝 <strong>生成测试代码</strong>——编写并执行测试脚本</li>\n<li>📊 <strong>分析测试结果</strong>——判断通过/失败，给出修复建议</li>\n<li>🔄 <strong>迭代优化</strong>——根据反馈不断改进测试策略</li>\n</ol>\n<p>简单来说，它是一个<strong>能独立思考和行动的测试工程师数字分身。</strong></p>\n<h2>Agent 架构设计</h2>\n<h3>整体架构</h3>\n<div class=\"language-mermaid line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"mermaid\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-mermaid\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">graph TB</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    User[用户输入测试需求] --> Orchestrator[Agent 编排器]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Orchestrator --> Planner[测试计划器]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Orchestrator --> Executor[测试执行器]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Orchestrator --> Analyzer[结果分析器]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Planner --> ToolRegistry[工具注册中心]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Executor --> ToolRegistry</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Analyzer --> ToolRegistry</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ToolRegistry --> PlaywrightMCP[Playwright MCP]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ToolRegistry --> APITool[API 测试工具]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ToolRegistry --> AssertTool[断言工具]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    ToolRegistry --> ReportTool[报告工具]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    </span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Analyzer --> Report[测试报告]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>核心组件</h3>\n<h4>1. Agent 编排器（Orchestrator）</h4>\n<p>负责接收用户指令，协调各组件工作：</p>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>用户输入 → 解析意图 → 制定计划 → 分配任务 → 汇总结果</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div></div></div><h4>2. 测试计划器（Planner）</h4>\n<p>根据需求生成测试策略和用例清单：</p>\n<ul>\n<li>分析测试范围</li>\n<li>确定测试类型（功能/性能/安全）</li>\n<li>生成测试用例概要</li>\n</ul>\n<h4>3. 测试执行器（Executor）</h4>\n<p>调用具体的 MCP 工具执行测试：</p>\n<ul>\n<li>浏览器操作（通过 Playwright MCP）</li>\n<li>API 调用</li>\n<li>断言验证</li>\n<li>截图/录屏</li>\n</ul>\n<h4>4. 结果分析器（Analyzer）</h4>\n<p>对测试结果进行分析：</p>\n<ul>\n<li>判断通过/失败</li>\n<li>分析失败原因</li>\n<li>生成修复建议</li>\n<li>输出测试报告</li>\n</ul>\n<h2>实战：构建第一个 Agent</h2>\n<h3>项目结构</h3>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>ai-testing-agent/</span></span>\n<span class=\"line\"><span>├── src/</span></span>\n<span class=\"line\"><span>│   ├── agent/</span></span>\n<span class=\"line\"><span>│   │   ├── orchestrator.ts    # 编排器</span></span>\n<span class=\"line\"><span>│   │   ├── planner.ts         # 计划器</span></span>\n<span class=\"line\"><span>│   │   ├── executor.ts        # 执行器</span></span>\n<span class=\"line\"><span>│   │   └── analyzer.ts        # 分析器</span></span>\n<span class=\"line\"><span>│   ├── tools/</span></span>\n<span class=\"line\"><span>│   │   ├── registry.ts        # 工具注册</span></span>\n<span class=\"line\"><span>│   │   ├── playwright.ts      # Playwright 工具</span></span>\n<span class=\"line\"><span>│   │   ├── api.ts             # API 工具</span></span>\n<span class=\"line\"><span>│   │   └── assert.ts         # 断言工具</span></span>\n<span class=\"line\"><span>│   ├── prompts/</span></span>\n<span class=\"line\"><span>│   │   ├── planner.md         # 计划器 Prompt</span></span>\n<span class=\"line\"><span>│   │   ├── executor.md        # 执行器 Prompt</span></span>\n<span class=\"line\"><span>│   │   └── analyzer.md        # 分析器 Prompt</span></span>\n<span class=\"line\"><span>│   └── index.ts               # 入口</span></span>\n<span class=\"line\"><span>├── tests/</span></span>\n<span class=\"line\"><span>│   └── agent.test.ts</span></span>\n<span class=\"line\"><span>├── package.json</span></span>\n<span class=\"line\"><span>└── tsconfig.json</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>Step 1: 工具注册中心</h3>\n<div class=\"language-typescript line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"typescript\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-typescript\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// src/tools/registry.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  name</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  description</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  execute</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">params</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Record</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">any</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">>) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">=></span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Promise</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ToolResult</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">>;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ToolRegistry</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> tools</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Map</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">Tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">> </span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">=</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Map</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  register</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">tool</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> void</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">set</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  getToolNames</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[] {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> Array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">keys</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">());</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">  getToolDescription</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">()</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> Array</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">from</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">values</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">())</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      .</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">map</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">t</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> =></span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> `- </span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">${</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">: </span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">${</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">t</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">description</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      .</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">join</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">\\n</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  async</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> execute</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">name</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">params</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Record</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">any</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">>)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Promise</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">ToolResult</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    const</span><span style=\"--shiki-light:#986801;--shiki-dark:#E5C07B\"> tool</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">tools</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">get</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    if</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> (</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\">!</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">) </span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">throw</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Error</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`Tool \"</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">${</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\" not found`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> tool</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">execute</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">params</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>Step 2: 编排器实现</h3>\n<div class=\"language-typescript line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"typescript\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-typescript\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// src/agent/orchestrator.ts</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TaskRequest</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  description</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;       </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 测试需求描述</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  target</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;            </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 测试目标 URL</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  browser</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> string</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;          </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 浏览器类型</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  timeout</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#C678DD\">?</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> number</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;          </span><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">// 超时时间</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">interface</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TaskResult</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  success</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#E5C07B\"> boolean</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  testCases</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TestCase</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[];</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  executionResults</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> ExecutionResult</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">[];</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">  report</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TestReport</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">class</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Orchestrator</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> planner</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Planner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> executor</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Executor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  private</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\"> analyzer</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Analyzer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  constructor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">() {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">planner</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Planner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">executor</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Executor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">    this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">analyzer</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> new</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> Analyzer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">();</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">  async</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\"> executeTask</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic\">request</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> TaskRequest</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">)</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\"> Promise</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">&#x3C;</span><span style=\"--shiki-light:#C18401;--shiki-dark:#E5C07B\">TaskResult</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">    console</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">log</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`🚀 开始执行测试任务: </span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">${</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">request</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">description</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // 1. 制定测试计划</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">    console</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">log</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'📋 阶段 1/3: 制定测试计划...'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    const</span><span style=\"--shiki-light:#986801;--shiki-dark:#E5C07B\"> plan</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> await</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">planner</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">createPlan</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // 2. 执行测试用例</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">    console</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">log</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">`🔄 阶段 2/3: 执行 </span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">${</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">plan</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">testCases</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">length</span><span style=\"--shiki-light:#CA1243;--shiki-dark:#C678DD\">}</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> 个测试用例...`</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    const</span><span style=\"--shiki-light:#986801;--shiki-dark:#E5C07B\"> executionResults</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> await</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">executor</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">execute</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">plan</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">testCases</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">    // 3. 分析结果并生成报告</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">    console</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">log</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">'📊 阶段 3/3: 分析结果并生成报告...'</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    const</span><span style=\"--shiki-light:#986801;--shiki-dark:#E5C07B\"> report</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> =</span><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\"> await</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\"> this</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E5C07B\">analyzer</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">analyze</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">(</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">executionResults</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A626A4;--shiki-dark:#C678DD\">    return</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      success</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> report</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">passed</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> ===</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> report</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">total</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      testCases</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#ABB2BF\">:</span><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\"> plan</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">.</span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">testCases</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">      executionResults</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E06C75\">      report</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    };</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>Step 3: 测试计划器 Prompt</h3>\n<div class=\"language-markdown line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"markdown\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-markdown\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\">&#x3C;!-- src/prompts/planner.md --></span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">你是一个测试计划专家 Agent。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">## 任务</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">根据用户提供的测试需求，制定详细的测试计划。</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">## 输入</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 需求描述：{{description}}</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">-</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 测试目标：{{target}}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">## 输出要求</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">1.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 列出所有需要测试的场景（至少 5 个）</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">2.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 为每个场景编写测试步骤</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">3.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 指定每个场景的预期结果</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#E5C07B\">4.</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\"> 标注优先级（P0/P1/P2）</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">## 输出格式</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">```json</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">{</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  \"testCases\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: [</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    {</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"id\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"TC-001\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"title\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"...\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"priority\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"P0\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">,</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"steps\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"...\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">, </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"...\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">],</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">      \"expectedResult\"</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">\"...\"</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    }</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">  ]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span></span></span>\n<span class=\"line\"><span>### Step 4: 执行器</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>```typescript</span></span>\n<span class=\"line\"><span>// src/agent/executor.ts</span></span>\n<span class=\"line\"><span>class Executor {</span></span>\n<span class=\"line\"><span>  async execute(testCases: TestCase[]): Promise&#x3C;ExecutionResult[]> {</span></span>\n<span class=\"line\"><span>    const results: ExecutionResult[] = [];</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>    for (const tc of testCases) {</span></span>\n<span class=\"line\"><span>      console.log(`  ⚡ 执行: ${tc.title}`);</span></span>\n<span class=\"line\"><span>      </span></span>\n<span class=\"line\"><span>      try {</span></span>\n<span class=\"line\"><span>        const startTime = Date.now();</span></span>\n<span class=\"line\"><span>        </span></span>\n<span class=\"line\"><span>        // 逐步骤执行</span></span>\n<span class=\"line\"><span>        for (const step of tc.steps) {</span></span>\n<span class=\"line\"><span>          await this.executeStep(step);</span></span>\n<span class=\"line\"><span>        }</span></span>\n<span class=\"line\"><span>        </span></span>\n<span class=\"line\"><span>        const duration = Date.now() - startTime;</span></span>\n<span class=\"line\"><span>        </span></span>\n<span class=\"line\"><span>        results.push({</span></span>\n<span class=\"line\"><span>          testCaseId: tc.id,</span></span>\n<span class=\"line\"><span>          status: 'passed',</span></span>\n<span class=\"line\"><span>          duration,</span></span>\n<span class=\"line\"><span>          screenshots: [],</span></span>\n<span class=\"line\"><span>        });</span></span>\n<span class=\"line\"><span>        </span></span>\n<span class=\"line\"><span>        console.log(`  ✅ 通过: ${tc.title} (${duration}ms)`);</span></span>\n<span class=\"line\"><span>      } catch (error) {</span></span>\n<span class=\"line\"><span>        results.push({</span></span>\n<span class=\"line\"><span>          testCaseId: tc.id,</span></span>\n<span class=\"line\"><span>          status: 'failed',</span></span>\n<span class=\"line\"><span>          error: (error as Error).message,</span></span>\n<span class=\"line\"><span>          screenshots: [],</span></span>\n<span class=\"line\"><span>        });</span></span>\n<span class=\"line\"><span>        </span></span>\n<span class=\"line\"><span>        console.log(`  ❌ 失败: ${tc.title}`);</span></span>\n<span class=\"line\"><span>      }</span></span>\n<span class=\"line\"><span>    }</span></span>\n<span class=\"line\"><span>    </span></span>\n<span class=\"line\"><span>    return results;</span></span>\n<span class=\"line\"><span>  }</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>运行你的第一个 Agent</h2>\n<div class=\"language-bash line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"bash\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-bash\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 安装依赖</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npm</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> install</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 编译</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npm</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> run</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> build</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># 运行 Agent</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#4078F2;--shiki-dark:#61AFEF\">npm</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> start</span><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\"> --</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> \\</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">  --description</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"测试百度搜索功能\"</span><span style=\"--shiki-light:#0184BC;--shiki-dark:#56B6C2\"> \\</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">  --target</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\"> \"https://www.baidu.com\"</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>预期输出</h3>\n<div class=\"language- line-numbers-mode\" data-highlighter=\"shiki\" data-ext style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-\"><span class=\"line\"><span>🚀 开始执行测试任务: 测试百度搜索功能</span></span>\n<span class=\"line\"><span>📋 阶段 1/3: 制定测试计划...</span></span>\n<span class=\"line\"><span>  生成了 8 个测试用例</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>🔄 阶段 2/3: 执行 8 个测试用例...</span></span>\n<span class=\"line\"><span>  ⚡ 执行: TC-001 打开百度首页</span></span>\n<span class=\"line\"><span>  ✅ 通过: TC-001 (1234ms)</span></span>\n<span class=\"line\"><span>  ⚡ 执行: TC-002 搜索关键词</span></span>\n<span class=\"line\"><span>  ✅ 通过: TC-002 (2345ms)</span></span>\n<span class=\"line\"><span>  ...</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>📊 阶段 3/3: 分析结果并生成报告...</span></span>\n<span class=\"line\"><span>  总计: 8 | 通过: 7 | 失败: 1 | 通过率: 87.5%</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>进阶方向</h2>\n<p>掌握了基础 Agent 后，可以往以下方向演进：</p>\n<h3>1. 多 Agent 协作</h3>\n<div class=\"language-mermaid line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"mermaid\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-mermaid\"><span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">graph LR</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Manager[管理 Agent] --> WebAgent[Web 测试 Agent]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Manager --> APIAgent[API 测试 Agent]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Manager --> PerfAgent[性能测试 Agent]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">    Manager --> SecAgent[安全测试 Agent]</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h3>2. 持续学习</h3>\n<ul>\n<li>记录每次测试结果到知识库</li>\n<li>从失败中学习常见错误模式</li>\n<li>自动优化测试策略</li>\n</ul>\n<h3>3. CI/CD 集成</h3>\n<div class=\"language-yaml line-numbers-mode\" data-highlighter=\"shiki\" data-ext=\"yaml\" style=\"--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34\"><pre class=\"shiki shiki-themes one-light one-dark-pro vp-code\"><code class=\"language-yaml\"><span class=\"line\"><span style=\"--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic\"># .github/workflows/ai-test.yml</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">name</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">AI Testing Agent</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#986801;--shiki-dark:#D19A66\">on</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: [</span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">pull_request</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">]</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">jobs</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">  ai-test</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    runs-on</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">ubuntu-latest</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">    steps</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">:</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">uses</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">actions/checkout@v4</span></span>\n<span class=\"line\"><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">      - </span><span style=\"--shiki-light:#E45649;--shiki-dark:#E06C75\">run</span><span style=\"--shiki-light:#383A42;--shiki-dark:#ABB2BF\">: </span><span style=\"--shiki-light:#50A14F;--shiki-dark:#98C379\">npm start -- --mode ci --target ${{ github.event.pull_request.html_url }}</span></span></code></pre>\n<div class=\"line-numbers\" aria-hidden=\"true\" style=\"counter-reset:line-number 0\"><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div><div class=\"line-number\"></div></div></div><h2>小结</h2>\n<p>本文我们从架构设计到代码实现，完整走了一遍 AI Testing Agent 的创建过程。核心要点：</p>\n<ol>\n<li><strong>Agent = 编排器 + 计划器 + 执行器 + 分析器</strong></li>\n<li><strong>MCP 工具是 Agent 的手和脚</strong>——工具越丰富，Agent 能力越强</li>\n<li><strong>从简单开始，逐步迭代</strong>——先让 Agent 跑通一个场景，再扩展</li>\n<li><strong>Prompt 质量决定 Agent 上限</strong>——花时间打磨每个组件的 Prompt</li>\n</ol>\n",
      "date_published": "2026-07-20T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "自动生成接口测试脚本",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/generate-api-test-scripts.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/generate-api-test-scripts.html",
      "summary": "自动生成接口测试脚本 基于结构化测试用例，使用 AI 自动生成 Pytest 接口测试代码。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过...",
      "content_html": "\n<p>基于结构化测试用例，使用 AI 自动生成 Pytest 接口测试代码。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "自动生成 Playwright UI 测试",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/generate-playwright-ui-tests.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/generate-playwright-ui-tests.html",
      "summary": "自动生成 Playwright UI 测试 基于测试用例自动生成 Playwright 浏览器自动化脚本，覆盖页面操作和数据采集。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下...",
      "content_html": "\n<p>基于测试用例自动生成 Playwright 浏览器自动化脚本，覆盖页面操作和数据采集。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "使用 AI 生成结构化测试用例",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/generate-structured-test-cases.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/generate-structured-test-cases.html",
      "summary": "使用 AI 生成结构化测试用例 将测试策略和需求文档转换为结构化、可执行的测试用例清单。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过程整...",
      "content_html": "\n<p>将测试策略和需求文档转换为结构化、可执行的测试用例清单。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    },
    {
      "title": "自动生成综合测试报告",
      "url": "https://ceyanshe.com/ai-testing/testing-agent/generate-test-report.html",
      "id": "https://ceyanshe.com/ai-testing/testing-agent/generate-test-report.html",
      "summary": "自动生成综合测试报告 汇总测试执行结果、失败分析、差异明细，自动生成 Markdown、JSON 或 Allure 格式的测试报告。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、...",
      "content_html": "\n<p>汇总测试执行结果、失败分析、差异明细，自动生成 Markdown、JSON 或 Allure 格式的测试报告。</p>\n<blockquote>\n<p>本文正在根据项目实际开发过程整理，后续持续补充。</p>\n</blockquote>\n<h2>一、为什么要做</h2>\n<h2>二、最终实现效果</h2>\n<h2>三、环境和技术栈</h2>\n<h2>四、实现思路</h2>\n<h2>五、项目目录</h2>\n<h2>六、操作步骤</h2>\n<h2>七、关键代码</h2>\n<h2>八、测试与验证</h2>\n<h2>九、遇到的问题及解决方法</h2>\n<h2>十、最终总结</h2>\n<h2>十一、下一阶段计划</h2>\n",
      "date_published": "2026-07-27T00:00:00.000Z",
      "date_modified": "2026-07-27T10:58:20.000Z",
      "authors": [
        {
          "name": "AI测研社"
        }
      ],
      "tags": [
        "AI 测试"
      ]
    }
  ]
}