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