<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://ceyanshe.com/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <atom:link href="https://ceyanshe.com/rss.xml" rel="self" type="application/rss+xml"/>
    <title>AI 测研社</title>
    <link>https://ceyanshe.com/</link>
    <description>AI 测研社专注测试与质量场景的 AI 工作流实践，通过真实项目研究需求分析、测试执行、多源数据校验、失败定位和报告生成的智能化。</description>
    <language>zh-CN</language>
    <pubDate>Mon, 27 Jul 2026 10:58:58 GMT</pubDate>
    <lastBuildDate>Mon, 27 Jul 2026 10:58:58 GMT</lastBuildDate>
    <generator>@vuepress/plugin-feed</generator>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <image>
      <title>AI 测研社</title>
      <url>https://ceyanshe.com/logo.svg</url>
      <link>https://ceyanshe.com/</link>
    </image>
    <category>AI 开发工具</category>
    <category>测试成长</category>
    <category>建站实战</category>
    <category>AI 测试</category>
    <item>
      <title>关于我</title>
      <link>https://ceyanshe.com/about.html</link>
      <guid>https://ceyanshe.com/about.html</guid>
      <source url="https://ceyanshe.com/rss.xml">关于我</source>
      <description>关于我 我是一名从软件测试出发，持续实践 AI 工程化和自动化工作流的技术从业者。 这个网站用于公开记录真实项目、操作过程、问题排查和阶段性成果，希望帮助更多传统测试工程师理解并使用 AI。 关注方向 🧪 AI 测试与智能断言 🔧 Claude Code、Codex、MCP、Skills 实战 🔗 AI 自动化工作流 📊 数据质量与校验 📝 ...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>AI 工作流</title>
      <link>https://ceyanshe.com/ai-workflow-basics.html</link>
      <guid>https://ceyanshe.com/ai-workflow-basics.html</guid>
      <source url="https://ceyanshe.com/rss.xml">AI 工作流</source>
      <description>AI 工作流 AI 工作流栏目负责介绍实现 AI 工作流需要掌握的通用知识——从理解什么是 AI 工作流，到掌握 Agent、MCP、Skills 和提示词工程。 AI 工作流不是单次对话，也不是只生成一段代码，而是能够被重复执行、验证结果并保留记录的完整流程。 AI 工作流入门 推荐文章 理解 AI 测试的核心概念、工具生态与学习路线，迈出从传统测试...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![CDATA[
<p>AI 工作流栏目负责介绍实现 AI 工作流需要掌握的通用知识——从理解什么是 AI 工作流，到掌握 Agent、MCP、Skills 和提示词工程。</p>
<p><strong>AI 工作流不是单次对话，也不是只生成一段代码</strong>，而是能够被重复执行、验证结果并保留记录的完整流程。</p>
]]></content:encoded>
    </item>
    <item>
      <title>学习交流</title>
      <link>https://ceyanshe.com/community.html</link>
      <guid>https://ceyanshe.com/community.html</guid>
      <source url="https://ceyanshe.com/rss.xml">学习交流</source>
      <description>加入 AI 测研社学习交流 交流 AI 测试、Claude Code、Codex、MCP、Skills 与自动化工作流实战。 交流方式 我们目前通过以下方式交流： 💬 在博客文章下方留言讨论 📧 邮件交流：TODO（联系方式待补充） 🌐 关注博客更新 加入原则 欢迎分享真实项目和踩坑经验 鼓励提出具体问题和改进建议 不欢迎纯粹的广告和引流行为 目...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![CDATA[
<p>交流 AI 测试、Claude Code、Codex、MCP、Skills 与自动化工作流实战。</p>
]]></content:encoded>
    </item>
    <item>
      <title>企业落地</title>
      <link>https://ceyanshe.com/enterprise.html</link>
      <guid>https://ceyanshe.com/enterprise.html</guid>
      <source url="https://ceyanshe.com/rss.xml">企业落地</source>
      <description>企业落地研究 AI 测研社关注的是 AI 工作流在企业测试场景中的实际落地，不是演示性的单次操作。 当前内容以案例研究、方案设计和原型验证为主，后续将通过真实项目逐步沉淀可复用的工作流模板和实施方法。 企业测试场景 企业中常见的测试流程问题： 测试用例编写和更新成本高，需求变更后人工维护效率低 自动化脚本开发和维护困难，框架升级和页面变化导致大量返工 ...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![CDATA[
<p>AI 测研社关注的是 AI 工作流在企业测试场景中的实际落地，不是演示性的单次操作。</p>
<p><strong>当前内容以案例研究、方案设计和原型验证为主</strong>，后续将通过真实项目逐步沉淀可复用的工作流模板和实施方法。</p>
]]></content:encoded>
    </item>
    <item>
      <title>关于 AI 测研社</title>
      <link>https://ceyanshe.com/intro.html</link>
      <guid>https://ceyanshe.com/intro.html</guid>
      <source url="https://ceyanshe.com/rss.xml">关于 AI 测研社</source>
      <description>关于 AI 测研社 以测求真，以研促用 AI 测研社是一个专注于 AI 测试工程化的技术实践平台。 &amp;quot;测&amp;quot;代表软件测试与真实测评，&amp;quot;研&amp;quot;代表技术研究与方法沉淀。我们不只介绍工具，更通过真实项目验证 Claude Code、Codex、MCP、Skills 和智能体在软件测试中的实际价值。 品牌价值观 以测求真：通...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![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:encoded>
      <enclosure url="https://ceyanshe.com/assets/images/cover3.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Claude Code + Playwright MCP 安装与验证</title>
      <link>https://ceyanshe.com/ai-testing/claude-code-playwright-mcp-setup.html</link>
      <guid>https://ceyanshe.com/ai-testing/claude-code-playwright-mcp-setup.html</guid>
      <source url="https://ceyanshe.com/rss.xml">Claude Code + Playwright MCP 安装与验证</source>
      <description>Claude Code + Playwright MCP 安装与验证 前言 上一篇文章我们聊了 ，这篇就动手实践——安装 Claude Code CLI 并配置 Playwright MCP Server。 完成本文后，你将能用自然语言驱动 Playwright 完成 Web 自动化测试。 环境准备 系统要求 Node.js 18+ （推荐 20 LT...</description>
      <category>AI 开发工具</category>
      <pubDate>Thu, 16 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>测试实战</title>
      <link>https://ceyanshe.com/ai-testing/test-practice.html</link>
      <guid>https://ceyanshe.com/ai-testing/test-practice.html</guid>
      <source url="https://ceyanshe.com/rss.xml">测试实战</source>
      <description>测试实战 测试实战栏目按照真实测试场景分类，展示 AI 工作流在具体测试领域中的应用。 每一个场景都围绕可运行、可校验、可重复的目标展开，不限于某一种工具。 UI 自动化工作流 推荐文章 用自然语言描述测试任务，让 Claude Code 通过 Playwright MCP 操作真实浏览器，完成页面识别、登录、数据提取和可重复执行的测试脚本。 接口测试...</description>
      <pubDate>Mon, 27 Jul 2026 10:58:20 GMT</pubDate>
      <content:encoded><![CDATA[
<p>测试实战栏目按照真实测试场景分类，展示 AI 工作流在具体测试领域中的应用。</p>
<p>每一个场景都围绕<strong>可运行、可校验、可重复</strong>的目标展开，不限于某一种工具。</p>
]]></content:encoded>
    </item>
    <item>
      <title>AI 测试博客从创建到上线操作手册</title>
      <link>https://ceyanshe.com/notes/how-to-build-ai-testing-blog.html</link>
      <guid>https://ceyanshe.com/notes/how-to-build-ai-testing-blog.html</guid>
      <source url="https://ceyanshe.com/rss.xml">AI 测试博客从创建到上线操作手册</source>
      <description>AI 测试博客从创建到上线操作手册 [!summary] 最终成果 使用 VuePress 2 + VuePress Theme Hope 创建中文 AI 测试博客，将源码保存到 GitHub，并通过 Cloudflare Pages 免费部署。 当前网站：https://ai-test-blog.pages.dev 一、整体流程 各平台的作用： 二、...</description>
      <category>测试成长</category>
      <pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>Obsidian 使用腾讯云 COS 搭建图床：安装、配置与图片管理</title>
      <link>https://ceyanshe.com/notes/obsidian-cos-image-hosting-setup.html</link>
      <guid>https://ceyanshe.com/notes/obsidian-cos-image-hosting-setup.html</guid>
      <source url="https://ceyanshe.com/rss.xml">Obsidian 使用腾讯云 COS 搭建图床：安装、配置与图片管理</source>
      <description>使用 Tencent COS for Imgur 插件，将 Obsidian 中粘贴或拖入的图片自动上传到腾讯云 COS，并完成 CORS、存储路径和访问权限配置。</description>
      <category>测试成长</category>
      <pubDate>Fri, 24 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
      <enclosure url="https://github.com/bobostudio/obsidian-imgur-plugin/raw/master/images/banner2.png" type="image/png"/>
    </item>
    <item>
      <title>从本地写作到自动上线：VuePress 博客自动部署完整记录</title>
      <link>https://ceyanshe.com/notes/vuepress-github-actions-blog-deployment-guide.html</link>
      <guid>https://ceyanshe.com/notes/vuepress-github-actions-blog-deployment-guide.html</guid>
      <source url="https://ceyanshe.com/rss.xml">从本地写作到自动上线：VuePress 博客自动部署完整记录</source>
      <description>从本地写作到自动上线：VuePress 博客自动部署完整记录 本文记录「AI 测研社」博客从本地写文章，到 GitHub Actions 自动构建并部署至云服务器的完整过程。 完成配置以后，日常更新博客只需要： 一、最终实现效果 自动化链路跑通后，不再需要手动执行以下工作： 手动上传文章到服务器。 手动执行 VuePress 构建。 手动复制 dist...</description>
      <category>测试成长</category>
      <pubDate>Fri, 24 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>我用 VuePress、GitHub Actions 和阿里云搭建了 AI 测研社</title>
      <link>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</link>
      <guid>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</guid>
      <source url="https://ceyanshe.com/rss.xml">我用 VuePress、GitHub Actions 和阿里云搭建了 AI 测研社</source>
      <description>从本地 Markdown 写作、GitHub Actions 自动构建，到阿里云服务器自动发布，完整复盘 AI 测研社的建站与持续部署过程。</description>
      <category>建站实战</category>
      <category>AI 开发工具</category>
      <pubDate>Sun, 26 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
      <enclosure url="https://ceyanshe.com/assets/images/vuepress-github-actions-aliyun-cover.png" type="image/png"/>
    </item>
    <item>
      <title>我用 Claude Code + Playwright MCP 跑通了第一次真实 UI 测试</title>
      <link>https://ceyanshe.com/ai-testing/guide/first-real-ui-test-with-claude-code-playwright-mcp.html</link>
      <guid>https://ceyanshe.com/ai-testing/guide/first-real-ui-test-with-claude-code-playwright-mcp.html</guid>
      <source url="https://ceyanshe.com/rss.xml">我用 Claude Code + Playwright MCP 跑通了第一次真实 UI 测试</source>
      <description>我用 Claude Code + Playwright MCP 跑通了第一次真实 UI 测试 以前编写 UI 自动化测试，通常需要先分析页面、寻找元素、编写定位器，再组织测试流程。 这一次，我尝试把测试任务直接交给 Claude Code，让它通过 Playwright MCP 操作真实浏览器，完成页面识别、登录和商品信息获取。 本文记录完整实践过程，...</description>
      <category>AI 测试</category>
      <pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>传统测试工程师为什么要学习 AI 测试</title>
      <link>https://ceyanshe.com/ai-testing/guide/why-traditional-testers-learn-ai-testing.html</link>
      <guid>https://ceyanshe.com/ai-testing/guide/why-traditional-testers-learn-ai-testing.html</guid>
      <source url="https://ceyanshe.com/rss.xml">传统测试工程师为什么要学习 AI 测试</source>
      <description>传统测试工程师为什么要学习 AI 测试 前言 如果你是一名传统软件测试工程师，每天的工作是写测试用例、执行回归测试、维护自动化脚本——你可能会问：AI 测试跟我有什么关系？ 答案是：关系很大，而且比你想象的更紧迫。 这篇文章将从一个传统测试工程师的视角，聊聊为什么现在就应该开始学习 AI 测试。 测试行业的现状 传统测试的痛点 重复劳动占比高：大量的回...</description>
      <category>AI 测试</category>
      <pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>使用 AI 分析测试失败原因</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/ai-failure-analysis.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/ai-failure-analysis.html</guid>
      <source url="https://ceyanshe.com/rss.xml">使用 AI 分析测试失败原因</source>
      <description>使用 AI 分析测试失败原因 将测试失败日志、截图和差异数据交给大模型，辅助定位失败根因并给出修复建议。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>自动采集测试结果与截图</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/collect-test-results-and-screenshots.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/collect-test-results-and-screenshots.html</guid>
      <source url="https://ceyanshe.com/rss.xml">自动采集测试结果与截图</source>
      <description>自动采集测试结果与截图 在测试执行过程中自动采集接口响应、页面截图、日志和断言结果。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过程整理，...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>从 0 到 1 创建 AI Testing Agent</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/creating-ai-testing-agent-from-scratch.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/creating-ai-testing-agent-from-scratch.html</guid>
      <source url="https://ceyanshe.com/rss.xml">从 0 到 1 创建 AI Testing Agent</source>
      <description>从 0 到 1 创建 AI Testing Agent 前言 前面两篇文章我们分别讨论了： 现在，是时候更进一步了——创建一个能独立完成测试任务的 AI Testing Agent。 什么是 AI Testing Agent？ AI Testing Agent 是一个能够： 🧠 理解测试需求——解析自然语言描述的测试场景 🔧 自主选择工具——决定使...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>自动生成接口测试脚本</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/generate-api-test-scripts.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/generate-api-test-scripts.html</guid>
      <source url="https://ceyanshe.com/rss.xml">自动生成接口测试脚本</source>
      <description>自动生成接口测试脚本 基于结构化测试用例，使用 AI 自动生成 Pytest 接口测试代码。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>自动生成 Playwright UI 测试</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/generate-playwright-ui-tests.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/generate-playwright-ui-tests.html</guid>
      <source url="https://ceyanshe.com/rss.xml">自动生成 Playwright UI 测试</source>
      <description>自动生成 Playwright UI 测试 基于测试用例自动生成 Playwright 浏览器自动化脚本，覆盖页面操作和数据采集。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>使用 AI 生成结构化测试用例</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/generate-structured-test-cases.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/generate-structured-test-cases.html</guid>
      <source url="https://ceyanshe.com/rss.xml">使用 AI 生成结构化测试用例</source>
      <description>使用 AI 生成结构化测试用例 将测试策略和需求文档转换为结构化、可执行的测试用例清单。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、下一阶段计划 本文正在根据项目实际开发过程整...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
    <item>
      <title>自动生成综合测试报告</title>
      <link>https://ceyanshe.com/ai-testing/testing-agent/generate-test-report.html</link>
      <guid>https://ceyanshe.com/ai-testing/testing-agent/generate-test-report.html</guid>
      <source url="https://ceyanshe.com/rss.xml">自动生成综合测试报告</source>
      <description>自动生成综合测试报告 汇总测试执行结果、失败分析、差异明细，自动生成 Markdown、JSON 或 Allure 格式的测试报告。 本文正在根据项目实际开发过程整理，后续持续补充。 一、为什么要做 二、最终实现效果 三、环境和技术栈 四、实现思路 五、项目目录 六、操作步骤 七、关键代码 八、测试与验证 九、遇到的问题及解决方法 十、最终总结 十一、...</description>
      <category>AI 测试</category>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <content:encoded><![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:encoded>
    </item>
  </channel>
</rss>