基于MCP协议与AI大模型的智能Web自动化测试框架实践

基于MCP协议与AI大模型的智能Web自动化测试框架实践

1. 项目概述:当AI指令遇见浏览器自动化

最近在折腾自动化测试时,我一直在想一个问题:为什么写测试脚本的门槛还是这么高?一个测试工程师或者产品经理,明明能用一句话描述清楚测试场景——“登录后,在商品列表页点击第一个商品,加入购物车,然后去结算页看看总价对不对”,但要把这句话变成可执行的Playwright或Selenium代码,中间却隔着一道需要编程技能的鸿沟。

直到我开始把“AI智能体”和“Playwright”这两个看似不相关的玩意儿,通过一个叫MCP的协议给串了起来,事情就变得有意思了。这个项目的核心,就是想验证一个想法:能不能让用户直接用人类语言告诉系统要测什么,然后系统自己理解、规划并执行对应的浏览器自动化操作?这不仅仅是“用AI生成代码”,而是构建一个能理解意图、动态决策并执行任务的“智能测试执行体”。

简单来说,我搭建了一个框架,你告诉它“帮我测试一下用户从登录到下单的流程”,它就能自己打开浏览器,模拟用户操作,完成测试并生成报告。背后的引擎是AI大模型(比如GPT-4、Claude-3),它负责理解你的自然语言指令;而Playwright作为顶尖的浏览器自动化工具,是框架强健的“手和脚”;连接两者的“神经系统”,就是MCP协议。

这个实践对于测试团队、低代码平台开发者,乃至任何想提升复杂业务流程自动化水平的人,都有参考价值。它降低了自动化测试的创作门槛,让业务验证变得更敏捷。接下来,我就把这套框架的设计思路、核心实现、踩过的坑以及未来的想象空间,拆开了揉碎了和大家聊聊。

2. 核心架构与MCP协议的关键作用

2.1 为什么是“AI + Playwright + MCP”这个组合?

在决定技术栈时,我评估过几个方向。最初想用传统的“自然语言处理+规则引擎”来解析指令,但很快发现,测试场景千变万化,规则根本写不完,维护成本爆炸。而当前的大语言模型在理解复杂意图、进行多步推理和规划方面表现惊人,正好弥补了这个缺口。

Playwright的选择几乎没有悬念。相比Selenium,它更现代,支持多浏览器(Chromium, Firefox, WebKit)且API设计优雅,自动等待、网络拦截、移动端模拟等特性对复杂测试场景非常友好。它的强大,为AI智能体提供了稳定可靠的执行环境。

最关键的粘合剂是MCP(Model Context Protocol)。你可以把它理解为一套“AI智能体与应用工具之间的标准对话接口”。它由Anthropic提出,目的是让大模型能安全、结构化地调用外部工具和资源。在这个框架里,MCP Server封装了Playwright的所有能力(如打开页面、点击、输入、截图等),并将其以“工具”的形式暴露给AI模型。AI模型通过MCP Client调用这些工具,就像在说:“请帮我点击这个按钮”,而无需关心底层是Playwright的哪行代码。

这个组合的优势在于:

  1. 解耦与标准化:AI模型和自动化执行器通过MCP协议通信,彼此独立。你可以更换背后的AI模型(从GPT换到Claude),也可以更换执行器(理论上可以换成Selenium),只要它们遵循MCP协议。
  2. 动态规划与容错:AI模型可以根据页面实时状态(通过MCP获取的截图、HTML元素信息)动态调整下一步操作,处理一些意料之外的弹窗或页面变化,这是静态脚本无法做到的。
  3. 意图直达操作:用户无需将需求翻译成“代码”,只需描述“目标”,剩下的规划、定位、执行由系统完成。

2.2 框架整体设计思路

整个框架的运行流程,可以看作一个“感知-思考-行动”的循环:

自然语言指令 -> AI智能体(规划与决策) -> MCP协议 -> Playwright工具集 -> 浏览器操作 -> 结果反馈 -> 下一轮决策

我把它分成了三个核心层:

  1. 交互与规划层:这是框架的“大脑”。接收用户的自然语言指令(如“测试登录功能”),利用大语言模型进行任务分解和步骤规划。例如,模型会规划出:打开登录页 -> 定位用户名输入框 -> 输入测试账号 -> 定位密码输入框 -> 输入密码 -> 定位登录按钮 -> 点击 -> 验证跳转结果。这一层通过MCP Client与下层通信。

  2. 能力抽象层:这是框架的“神经系统”,由MCP Server构成。它定义了AI可以调用的所有“工具”。我为Playwright的核心操作创建了一系列MCP工具,例如:

    • navigate_to(url): 导航到指定URL。
    • click(selector): 点击某个CSS选择器对应的元素。
    • fill(selector, text): 在输入框内填入文本。
    • get_page_content(): 获取当前页面的文本内容或结构化信息。
    • take_screenshot(): 对当前页面截图。
    • evaluate(selector, property): 获取元素的特定属性(如是否可见、文本内容)。

    每个工具都有清晰的输入输出描述,AI模型能准确理解何时以及如何使用它们。

  3. 执行与反馈层:这是框架的“手脚”,即Playwright运行时。它忠实地执行MCP Server传来的指令,操作真实的浏览器。同时,它将执行结果(成功/失败、页面截图、元素状态)通过MCP Server反馈给AI智能体,供其进行下一轮决策。

这种分层设计使得每一层都可以独立优化和扩展。比如,可以在规划层接入更强大的模型来提升复杂任务规划能力,也可以在能力层增加数据库查询、API调用等非浏览器操作工具。

3. 核心模块实现与关键技术细节

3.1 MCP Server的构建:封装Playwright能力

构建一个稳定、易用的MCP Server是整个项目的基石。我选择用Python来实现,因为它对Playwright和FastAPI(用于构建MCP Server的HTTP接口)都有很好的支持。

首先,需要定义工具(Tools)。MCP协议中,一个工具需要包含名称、描述、输入参数模式(JSON Schema)和实际的执行函数。

# 示例:定义点击工具 from mcp import Tool click_tool = Tool( name="click_element", description="点击页面上指定的元素。", input_schema={ "type": "object", "properties": { "selector": { "type": "string", "description": "用于定位元素的CSS选择器,例如 '#submit-btn' 或 'text=登录'" } }, "required": ["selector"] }, handler=async_click_handler # 实际的执行函数 ) async def async_click_handler(selector: str): """实际的点击操作处理函数""" page = get_current_page() # 获取当前Playwright页面对象 try: # Playwright内置了智能等待,这里直接点击 await page.click(selector) return {"success": True, "message": f"成功点击元素: {selector}"} except Exception as e: # 捕获异常并返回结构化错误,AI可以根据错误信息调整策略 return {"success": False, "message": f"点击失败: {str(e)}", "suggestion": "请检查选择器是否正确,或元素是否可见。"}

这里有几个关键点:

  • 选择器策略:为了让AI能更准确地定位元素,除了CSS选择器,我还封装了基于文本(text=)、XPath和角色(role=)的定位方式,并在工具描述中清晰说明。实践中发现,结合文本和角色定位,AI的命中率更高。
  • 错误处理与反馈:执行函数的返回值必须结构化。成功时返回成功标志和结果;失败时,不仅要返回失败,还要尽可能提供可读的错误信息和修复建议(如“元素未找到,建议使用更精确的选择器”)。这为AI的自我修正提供了依据。
  • 状态管理:Playwright的BrowserContextPage对象需要在整个会话中保持。我使用了一个会话管理器来关联MCP会话与Playwright实例,确保每个用户的测试流都在独立的浏览器上下文中进行,互不干扰。

注意:在定义工具描述时,要尽可能详细和准确。AI模型完全依赖这些描述来理解工具功能。模糊的描述会导致模型错误调用。例如,“获取页面内容”这个描述就太宽泛,更好的描述是“获取当前页面主体部分的可见文本内容,用于理解页面状态”。

3.2 AI智能体(规划器)的提示工程与任务分解

AI智能体是这个框架的“指挥官”。它的核心是一个精心设计的系统提示词(System Prompt),用来设定其角色、能力和行为规范。

system_prompt = """ 你是一个专业的Web自动化测试助手。你的目标是根据用户的自然语言指令,通过调用一系列可用的工具来完成端到端的测试流程。 ## 你的能力 你可以通过调用工具来:导航到网页、与页面元素交互(点击、输入、选择)、获取页面信息、断言验证。 ## 你的工作流程 1. **理解指令**:仔细分析用户的测试需求。 2. **制定计划**:将复杂任务分解为一系列具体的、可执行的步骤。每一步都应该对应一个工具调用。 3. **执行与观察**:按顺序调用工具。每次调用后,仔细分析工具返回的结果(成功/失败、页面内容、截图描述)。 4. **动态调整**:如果某一步失败,根据错误信息分析原因,并调整你的计划(例如,更换选择器,或先执行其他前置操作)。 5. **验证与报告**:在关键步骤后,主动验证结果是否符合预期(例如,登录后页面是否跳转),并在任务结束时总结测试结果。 ## 重要原则 - **安全第一**:不要执行任何可能破坏数据或系统的危险操作。 - **精准定位**:优先使用`text=`或具有唯一性的`id`选择器。如果元素难以定位,可以先调用`get_page_content`了解页面结构。 - **逐步推进**:一次只执行一个明确的操作,确认成功后再进行下一步。 - **处理异常**:遇到弹窗、加载慢等情况时,根据工具返回的错误信息,尝试等待或使用其他策略。 """

在实际运行中,用户指令和对话历史会作为用户提示(User Prompt)发送给模型。模型根据系统提示的规范,输出一个结构化的响应,指明下一步要调用的工具及其参数。框架解析这个响应,通过MCP Client调用对应的Server工具。

任务分解的挑战与技巧:对于“测试购物流程”这样的复杂指令,模型需要将其分解为几十个步骤。我发现,在提示词中要求模型“先输出一个高层级的计划大纲”,然后再逐步细化执行,比让它直接输出所有步骤更稳定,也更容易在中间步骤失败时进行回溯和调整。

3.3 闭环执行与自修正机制

一个只会按固定剧本执行的AI不是好测试员。真正的价值在于它能根据实时反馈进行动态调整。这就是“执行-观察-决策”的闭环。

框架的工作流如下:

  1. AI输出行动指令(调用工具A)。
  2. 框架通过MCP执行工具A。
  3. 框架将工具A的执行结果(成功/失败+详细信息)作为新的上下文,连同原始指令再次发送给AI。
  4. AI分析结果:如果成功,则规划下一步(工具B);如果失败,则分析原因(是选择器问题?还是页面未加载?),并可能输出一个修正动作(比如先调用get_page_content重新侦察,或换一个选择器重试)。

例如,AI指令click(“#loginBtn”)可能因为元素加载慢而失败,返回“TimeoutError”。AI收到这个错误后,可能会先执行一个wait_for_selector(“#loginBtn”),然后再重试点击。

为了实现这一点,需要在每次调用AI时,都将完整的“对话历史”(包括之前所有的工具调用和结果)作为上下文传入。这能让AI保持对任务整体进展的记忆。

4. 实战演练:从零构建一个登录流程测试

理论说了这么多,我们动手跑一个最简单的例子:测试一个网站的登录功能。假设我们的网站登录页很简单,有用户名输入框(#username)、密码输入框(#password)和登录按钮(#submit)。

步骤1:启动框架首先,启动MCP Server(加载了所有Playwright工具),并启动AI客户端(连接了LLM API,如OpenAI或Anthropic)。

步骤2:发送指令用户发出指令:“请帮我测试登录功能,使用账号‘test@example.com’和密码‘123456’,登录成功后应该跳转到‘/dashboard’页面。”

步骤3:AI规划与执行(模拟对话)

  • AI思考:“用户要测试登录。我需要:1. 打开登录页;2. 输入账号;3. 输入密码;4. 点击登录;5. 验证跳转。”
  • AI行动:调用工具navigate_to(“https://example.com/login”)。Server执行,返回成功。
  • AI行动:调用工具fill(“#username”, “test@example.com”)。成功。
  • AI行动:调用工具fill(“#password”, “123456”)。成功。
  • AI行动:调用工具click(“#submit”)。成功。
  • AI验证:调用工具get_page_content()。获取到当前页面URL和关键文本。
  • AI分析:发现当前URL包含“/dashboard”,且页面有“欢迎回来”字样。判断登录成功。
  • AI报告:输出最终结论:“登录流程测试通过。成功导航至登录页,输入凭证并点击登录,系统按预期跳转至仪表盘页面。”

在这个过程中,如果#submit按钮因为动画延迟没有立即出现,Playwright的click操作可能会等待一段时间(可配置),这本身就具备一定的容错性。如果等待后仍失败,AI会收到错误,并可能尝试其他策略,比如先用get_page_content看看页面上有没有其他可点击的“登录”文本。

步骤4:结果可视化框架可以将整个执行过程记录下来,包括AI的每一步决策、调用的工具、返回的结果,以及Playwright自动截取的每一步的屏幕截图。最终生成一份图文并茂的可视化测试报告,清晰地展示了测试路径和状态。

5. 深入挑战:定位策略、稳定性与复杂场景

5.1 元素定位:AI的“眼睛”如何更准?

这是实践中最常遇到的问题。AI不是人眼,它通过选择器来“看”页面。不稳定的选择器会导致测试脆弱。

我采用的混合定位策略:

  1. 优先语义化选择器:在工具描述中,引导AI优先使用text=”登录”[aria-label=”搜索框”]这类与用户感知一致的属性。这比div:nth-child(3) > button稳定得多。
  2. 提供侦察工具:除了get_page_content(返回文本),我还增加了get_interactive_elements工具,它可以返回页面上所有可点击、可输入元素的列表及其可能的定位方式(id, text, role等),供AI决策参考。
  3. 视觉辅助定位(进阶):对于极度动态或前端框架生成的页面,纯DOM定位可能失效。我探索了结合计算机视觉的方法:当AI无法通过选择器定位时,调用take_screenshot工具,然后将截图和“请找到登录按钮”的描述一起发送给一个具备视觉能力的多模态模型(如GPT-4V),由它返回按钮在屏幕上的坐标,再通过Playwright的坐标点击功能操作。这套流程较慢,但作为兜底方案非常有效。

5.2 提升测试稳定性的实践

  1. 强制等待与智能等待:在Playwright工具封装层,为所有交互操作(click, fill)设置合理的默认超时时间(如30秒)。同时,鼓励AI在关键页面跳转后,主动调用wait_for_urlwait_for_selector工具进行确认,而不是立即执行下一步。
  2. 状态快照与回滚:对于多步骤流程测试(如结账),在关键节点(如登录成功、加入购物车后)调用page.context().storage_state()保存浏览器上下文状态(如cookies, localStorage)。如果后续步骤失败,可以从某个快照点快速恢复测试,而不必从头开始。
  3. 容错与重试逻辑:在框架层面,可以为某些可预见的错误(如网络错误、元素临时不可见)设计自动重试机制。当MCP Server返回这类错误时,框架可以自动重试2-3次,再将最终结果返回给AI。

5.3 复杂场景的应对:条件分支与数据驱动

真实的测试场景充满“如果...那么...”。

  • 场景:“如果商品库存为0,则显示‘缺货’按钮,否则显示‘加入购物车’按钮。”
  • 传统脚本:需要写if-else判断,硬编码选择器。
  • AI驱动框架:只需告诉AI:“请检查商品库存状态,并根据状态尝试进行相应的操作。” AI会先调用工具获取页面文本,解析出库存信息,然后动态决定下一步是点击“缺货”按钮还是“加入购物车”按钮。这要求AI具备一定的文本理解和逻辑判断能力。

对于数据驱动测试(用多组数据测试同一流程),框架可以轻松扩展。用户指令可以变为:“用下面三组账号密码测试登录:[(user1, pass1), (user2, pass2), (user3, pass3)]”。AI会理解这是一个循环任务,为每组数据规划并执行一遍登录流程。

6. 常见问题、优化方向与心得

6.1 实操中遇到的典型问题与排查

问题现象可能原因排查与解决思路
AI反复调用同一失败工具,陷入循环1. 工具错误信息不清晰,AI无法理解。
2. AI的决策逻辑有缺陷,缺乏回退策略。
1.优化工具反馈:在错误信息中明确给出可操作的“建议”,如“选择器‘.btn’匹配到5个元素,请使用更唯一的选择器”。
2.增强系统提示:在提示词中加入“当某步骤连续失败N次后,应暂停并描述当前页面状态,请求人工干预或尝试完全不同的路径”。
测试执行速度慢1. AI模型响应慢(特别是GPT-4)。
2. 每一步都等待AI决策,串行延迟高。
3. 频繁截图或获取页面内容,I/O开销大。
1.模型选型:对简单任务使用更快的模型(如Claude Haiku, GPT-3.5-Turbo)。
2.批量规划:对于已知的、线性的固定流程,可以提示AI一次性规划出多个步骤,然后批量执行,减少交互轮数。
3.缓存策略:对页面结构信息进行短期缓存,避免重复调用get_page_content
定位元素在Headless模式下失败,但在有头模式下成功1. Headless模式下的渲染、加载行为或有细微差异。
2. 某些元素依赖复杂的用户交互(如hover)才出现。
1.调试模式:在开发阶段使用有头模式(headless=False),并配合slow_mo参数减慢操作以便观察。
2.模拟交互:对于需要hover的元素,在点击前先调用hover工具。
3.环境一致性:确保测试环境的浏览器版本、视口大小与有头模式一致。
AI生成的步骤逻辑正确,但选择器总是不对AI对网页DOM结构不熟悉,倾向于生成过于通用或错误的选择器。1.提供范例:在系统提示词中加入几个正确使用选择器的例子。
2.工具增强:提供get_element_suggestions(description)工具,AI可以用自然语言描述元素(如“主要的提交按钮”),该工具通过一些启发式算法返回最可能的选择器列表。

6.2 成本、效率与适用场景权衡

成本考量:最大的成本来自AI模型的API调用(Token消耗)。一次复杂的测试流程可能涉及几十轮AI对话。优化方向包括:使用更便宜的模型处理简单步骤;对常见任务(如登录)制作“模板”或“技能”,让AI直接调用预定义的步骤序列,减少自由发挥。

效率对比:对于重复性高、路径固定的回归测试,传统编写脚本的方式效率更高、执行更快、成本为零。但对于探索性测试、快速验证新功能、或为复杂业务流编写初始测试用例,本框架的优势巨大。它能让产品、运营等非技术角色直接参与测试设计,极大缩短从需求到可执行测试的路径。

我的核心心得是:不要试图用这个框架完全取代所有传统自动化测试。它的定位应该是“增强”和“提效”。最适合的场景是:

  • 快速生成测试脚本草稿:让AI跑一遍流程,生成可维护和优化的Playwright代码。
  • 处理不确定的、动态的UI流程
  • 作为低代码/无代码测试平台的核心引擎

6.3 未来可能的扩展方向

  1. 多模态深度集成:更紧密地结合视觉模型,让AI能真正“看到”屏幕,处理验证码、图表验证等非文本交互。
  2. 自我优化与学习:框架可以记录成功的测试路径和使用的选择器,构建一个“选择器知识库”。当再次测试同一页面时,AI可以优先从知识库中选用历史成功的定位方式,提高稳定性和速度。
  3. 与测试管理平台集成:将AI测试体作为CI/CD流水线中的一个智能节点,接收来自Jira、TestRail等系统的测试用例描述,自动执行并将结果回传。
  4. 技能(Skill)市场:将验证过的、复杂的测试流程(如“OAuth第三方登录”、“支付宝支付”)封装成可复用的“技能”。用户只需说“执行支付宝支付技能”,AI就能调用这个预定义的、优化过的流程包。

构建这个框架的过程,更像是在教一个聪明的实习生如何做测试。你需要清晰地定义规则(MCP工具),耐心地指导方法(系统提示),并允许它从错误中学习(闭环反馈)。它目前还无法完全替代经验丰富的测试开发工程师,但在降低自动化门槛、激发新的测试形态上,已经展现出令人兴奋的潜力。最大的收获不是做出了一个多炫酷的工具,而是通过这次实践,真切地感受到“智能体”与“传统自动化”结合后,那种让机器更懂人意的可能性。