基于Playwright与AI智能体的财政软件自动化测试实战

基于Playwright与AI智能体的财政软件自动化测试实战
1. 项目概述当AI智能体遇上财政软件测试最近在跟几个做财政软件测试的朋友聊天大家普遍都在吐槽一个事儿财政系统的测试简直是自动化测试领域的“硬骨头”。这类系统往往业务流程极其复杂涉及预算编制、国库支付、政府采购、资产管理等多个模块数据关联性强规则严谨到近乎苛刻。一个简单的支付流程背后可能串联着几十张表单和上百条校验规则。传统的UI自动化测试脚本维护成本高得吓人业务规则一变脚本就得大改测试人员疲于奔命。就在这个当口以Playwright为代表的新一代浏览器自动化工具和基于大语言模型的AI智能体技术开始碰撞出火花。我最近花了一个多月时间深入折腾了一套“Playwright Agent”的测试方案专门用来啃财政软件自动化测试这块硬骨头。简单来说它不再是写死脚本而是让一个“AI测试员”Agent去理解测试需求自己操作浏览器完成从登录、填报、审批到结果验证的全流程。这听起来有点科幻但实测下来对于财政软件这种高复杂度、高规范性的系统效果出奇地好。这篇文章我就把自己从零搭建、踩坑、优化的全过程以及背后的设计思路毫无保留地分享出来。无论你是正在被财政系统测试折磨的QA还是对AI自动化测试感兴趣的技术人相信都能找到可以直接“抄作业”的实战经验。2. 核心设计为什么是Playwright AI Agent在决定技术栈之前我们得先想清楚财政软件自动化测试的痛点到底是什么。我总结下来主要是三点业务流程长且多变、数据与规则耦合紧密、UI元素状态复杂。传统的Selenium或早期Playwright脚本是“录制-回放”或“脚本编写-执行”的范式本质是将人的操作路径固化。一旦业务流调整比如财政局要求增加一个中间审核环节或者某个表单字段的校验逻辑变了脚本就必须人工介入修改敏捷性无从谈起。而“Playwright Agent”的思路则完全不同。它的核心是将测试任务从“脚本执行”提升到“目标驱动”。我们不再告诉它“点击A按钮在B输入框填123”而是告诉它“完成一笔差旅费报销申请并确保最终状态为‘支付成功’”。这个“AI测试员”会自己分解任务先登录找到报销申请入口理解表单每个字段该填什么比如出差事由、金额、附件自动生成符合财务规则的测试数据完成填报、提交并跟踪后续的审批流最终验证结果。这里Playwright负责提供稳定、强大的浏览器操作能力而AI智能体通常是基于大语言模型负责理解、规划和决策。2.1 技术选型深度解析为什么选择Playwright而不是其他工具对于财政软件这类常需要兼容IE模式或老旧内核的系统Playwright对Chromium、Firefox、WebKit三大引擎的无缝支持是巨大优势。更重要的是它的自动等待机制和强大的选择器能极大缓解财政软件页面加载慢、动态元素多的痛苦。比如一个预算项目选择下拉框可能异步加载数据Playwright可以很优雅地等待其可用而不需要写一堆time.sleep。在AI智能体层面我并没有直接使用ChatGPT的Web界面而是通过其API或国内可用的等效大模型API来构建。核心是函数调用Function Calling能力。我将Playwright的常用操作如click,fill,select_option,get_text封装成一个个工具函数并赋予其清晰的描述。AI智能体在规划任务时会根据当前页面状态和目标决定调用哪个函数并生成正确的参数。例如AI看到页面有一个“报销金额”输入框它会调用fill函数并生成一个符合“金额为正数且不超过预算”规则的测试数据作为参数。2.2 架构设计图与数据流整个系统的运行流程可以概括为“感知-思考-行动”循环感知Agent通过Playwright获取当前页面的HTML快照、URL和关键元素状态。思考将当前状态和测试目标一同提交给大语言模型。LLM分析现状规划下一步最应该执行的操作例如“需要先登录”“当前在主页应点击‘报销管理’菜单”并生成对应的工具函数调用。行动系统执行LLM指定的Playwright函数操作浏览器。验证行动后再次“感知”新状态判断是否达成子目标或最终目标。循环直至测试任务完成或失败。这个架构的关键在于测试逻辑业务流不再固化在代码里而是存在于LLM对财政业务的理解中。当业务流程变更时我们只需要更新给LLM的提示词Prompt中的业务流程描述或者提供一两个新的操作示例Agent就能自适应新的流程极大地降低了维护成本。注意这个方案的成功高度依赖于给AI智能体提供清晰、准确的“上下文”。这包括系统的角色权限说明如“张三是预算科审核员”、关键业务规则如“政府采购项目必须上传招标文件”、以及操作函数的精确描述。准备这些“测试知识库”是前期最重要的投入。3. 实战搭建从零构建你的第一个财政测试Agent理论讲完了我们直接上手。这里我以一款典型的财政国库支付系统为例演示如何完成“指标录入-用款计划-支付申请”这个核心流程的自动化测试。3.1 环境准备与基础框架搭建首先你需要一个Python环境3.8。安装核心依赖pip install playwright openai # 或使用其他兼容OpenAI API的库如litellm playwright install chromium # 安装浏览器驱动这里我使用openai库作为LLM的调用客户端。如果你使用的是国内模型可以使用其提供的兼容OpenAI API的SDK原理完全一样。接下来创建两个核心文件tools.py封装Playwright操作和agent.py智能体主逻辑。tools.py- 将Playwright操作转化为Agent可用的工具from playwright.sync_api import Page import json class PlaywrightTools: def __init__(self, page: Page): self.page page def navigate(self, url: str) - str: 导航到指定URL。 self.page.goto(url) return f已导航至 {url} def get_page_content(self) - str: 获取当前页面的核心文本内容和交互元素状态用于Agent决策。 # 提取页面主要文本避免将整个HTML扔给LLM content self.page.inner_text(body) # 获取所有按钮、输入框等交互元素的标识和状态 elements self.page.evaluate(() { const items []; document.querySelectorAll(button, input, a, select).forEach(el { items.push({ tag: el.tagName, text: el.innerText || el.value || el.placeholder, id: el.id, name: el.name, type: el.type, disabled: el.disabled, visible: el.checkVisibility() }); }); return JSON.stringify(items); }) return f页面内容摘要{content[:500]}...\\n交互元素{elements} def click(self, element_description: str) - str: 根据描述点击页面元素。描述应尽量唯一如‘登录按钮’或‘文本为“提交”的按钮’。 # 这里简化处理实际应用中需要更复杂的元素定位逻辑 # 例如结合文本、CSS选择器进行定位 try: self.page.click(ftext{element_description}) return f成功点击{element_description} except Exception as e: return f点击失败{e} def fill_form(self, field_mapping: str) - str: 根据提供的字段映射填充表单。参数应为JSON字符串如 {用户名: zhangsan, 密码: 123456}。 try: data json.loads(field_mapping) for field_name, value in data.items(): # 更健壮的定位方式通过placeholder、邻近label文本等定位 self.page.fill(finput[placeholder*{field_name}], input[name*{field_name}], str(value)) return f表单填充成功{list(data.keys())} except Exception as e: return f表单填充失败{e} def select_dropdown(self, dropdown_description: str, option: str) - str: 选择下拉框选项。 try: self.page.select_option(fselect:has-text({dropdown_description}), labeloption) return f在下拉框‘{dropdown_description}’中成功选择‘{option}’ except Exception as e: return f选择失败{e} def get_element_text(self, element_description: str) - str: 获取特定元素的文本内容用于验证。 try: text self.page.inner_text(f:has-text({element_description})) return f元素‘{element_description}’的文本是{text} except Exception as e: return f获取文本失败{e}agent.py- 智能体的“大脑”import openai from playwright.sync_api import sync_playwright from tools import PlaywrightTools import json class TestingAgent: def __init__(self, api_key, base_urlhttps://api.openai.com/v1): self.client openai.OpenAI(api_keyapi_key, base_urlbase_url) self.playwright sync_playwright().start() self.browser self.playwright.chromium.launch(headlessFalse) # 调试时可设为False self.page self.browser.new_page() self.tools PlaywrightTools(self.page) # 定义工具列表用于提供给LLM self.available_tools [ { type: function, function: { name: navigate, description: 打开一个新的网页地址。, parameters: {type: object, properties: {url: {type: string}}} } }, # ... 将tools.py中所有方法都按此格式定义 ] # 系统提示词这是Agent的“测试章程” self.system_prompt 你是一个专业的财政软件自动化测试AI助手。你的目标是操作浏览器完成指定的测试任务。 当前测试的系统是**财政国库支付管理系统**。你拥有一个‘测试员’账号。 核心业务流程知识 1. 登录用户名为身份证号密码为预设。 2. 指标录入路径为【预算管理】-【指标录入】需要选择预算单位、功能分类、录入金额。 3. 支付申请路径为【支付管理】-【直接支付申请】需要关联指标、填写收款人信息、金额。 请根据‘当前页面状态’和‘当前测试目标’决定下一步操作。每次只执行一个最明确、最必要的操作。 操作后我会反馈给你新的页面状态。 self.messages [{role: system, content: self.system_prompt}] def run_task(self, task: str): 执行一个测试任务。 print(f开始执行任务{task}) self.messages.append({role: user, content: f测试目标{task}。当前页面状态{self.tools.get_page_content()}}) while True: response self.client.chat.completions.create( modelgpt-4, # 或使用其他支持函数调用的模型 messagesself.messages, toolsself.available_tools, tool_choiceauto ) message response.choices[0].message self.messages.append(message) # 检查LLM是否要求调用工具 if message.tool_calls: for tool_call in message.tool_calls: function_name tool_call.function.name function_args json.loads(tool_call.function.arguments) # 执行对应的Playwright工具函数 if hasattr(self.tools, function_name): func getattr(self.tools, function_name) result func(**function_args) print(f执行: {function_name}({function_args}) - {result}) # 将执行结果作为观察反馈给LLM self.messages.append({ role: tool, tool_call_id: tool_call.id, name: function_name, content: result f\\n新的页面状态{self.tools.get_page_content()} }) else: print(f未知工具{function_name}) else: # LLM认为任务已完成或无法继续 print(fAgent回复{message.content}) break def close(self): self.browser.close() self.playwright.stop() # 使用示例 if __name__ __main__: agent TestingAgent(api_keyyour-api-key) try: agent.run_task(登录系统并进入指标录入页面。) # 后续可以继续更复杂的任务如agent.run_task(为‘市教育局’录入一笔金额为50000元的‘商品和服务支出’指标。) finally: agent.close()这个基础框架已经具备了智能体测试的核心能力。你可以看到我们并没有写任何关于“点击登录按钮”、“输入用户名”的硬编码所有的操作逻辑都由LLM根据当前页面状态动态生成。3.2 财政业务场景的深度适配上面的基础框架能跑通但要对财政软件进行有效测试必须进行深度定制。财政软件测试的核心是数据和规则。1. 测试数据工厂的集成我们不能让AI随便填“测试数据123”必须生成符合财政业务规则的测试数据。我们需要建立一个轻量级的“测试数据工厂”class FinanceDataFactory: staticmethod def generate_budget_unit(): 生成预算单位名称从预设列表随机选取如‘市财政局办公室’、‘第一中学’。 units [市财政局办公室, 市教育局, 市卫健委, 第一中学, 人民医院] return random.choice(units) staticmethod def generate_economic_classification(): 生成政府经济分类如‘302-商品和服务支出’、‘310-资本性支出’。 classifications [302-商品和服务支出, 303-对个人和家庭的补助, 310-资本性支出] return random.choice(classifications) staticmethod def generate_payment_amount(limit100000): 生成支付金额确保为两位小数正数且在合理范围内。 return round(random.uniform(1, limit), 2)然后在Agent的system_prompt中增加“当你需要填写‘预算单位’、‘经济分类’、‘金额’等字段时请调用FinanceDataFactory的方法生成合规的测试数据并以JSON格式传递给fill_form工具。”2. 复杂表单与多步骤操作的封装财政软件一个页面可能有几十个字段。让AI逐个识别填充效率低且易错。更好的做法是将高频操作封装成更高级的工具。# 在tools.py中增加 def fill_complex_budget_form(self, form_data: str) - str: 填充复杂的指标录入表单。form_data是一个包含所有字段信息的JSON字符串。 data json.loads(form_data) # 假设表单布局固定使用更精确的选择器 self.page.fill(#budgetUnit, data[budget_unit]) # 预算单位输入框 self.page.click(#economicClassificationDropdown) self.page.click(ftext{data[economic_class]}) # 选择经济分类 self.page.fill(#amount, str(data[amount])) self.page.fill(#projectName, data.get(project_name, 自动化测试项目)) # ... 填充更多字段 return 复杂指标表单填充完成。 # 在available_tools中注册这个新工具这样LLM在遇到指标录入页面时可以直接调用fill_complex_budget_form并传入一个由FinanceDataFactory生成的、结构化的数据对象一次性完成整个表单的填充稳定性和效率都更高。4. 核心挑战与优化策略实录在实际将这套方案应用于多个财政项目后我遇到了几个典型问题并总结出了一套优化策略。4.1 挑战一页面状态感知不准与“发呆”问题问题描述Agent有时会“卡住”反复获取页面状态却无法做出有效决策。比如点击“提交”后页面在后台处理前端显示“处理中...”但Agent获取的页面文本可能变化不大导致它误以为操作未成功陷入循环。根因分析LLM基于静态的HTML文本快照做决策对前端动态状态如Loading、异步更新、弹窗不敏感。get_page_content方法只提取了文本丢失了关键的UI状态信息。解决方案增强“感知”能力将UI状态显式地告诉LLM。截图辅助在关键操作点击提交、打开新页面前后使用page.screenshot()保存截图并将截图路径或Base64编码摘要可调用视觉模型API简单描述作为上下文的一部分提供给LLM。提示词可改为“当前页面状态{文本摘要}。界面视觉提示有一个蓝色旋转的加载图标。”等待特定状态在工具函数中内置智能等待。例如在click函数中加入对后续页面变化的等待逻辑。def click_and_wait(self, element_description: str, wait_for_selector: str None) - str: 点击元素并可选地等待某个新元素出现代表操作成功。 self.page.click(ftext{element_description}) if wait_for_selector: try: self.page.wait_for_selector(wait_for_selector, statevisible, timeout10000) return f点击‘{element_description}’成功并已观察到‘{wait_for_selector}’元素。 except: return f点击完成但未在指定时间内看到预期元素‘{wait_for_selector}’。 return f已点击{element_description}自定义状态判断函数增加一个get_page_state工具专门判断页面处于哪种已知状态如“登录页”、“主页”、“表单填写页”、“提交成功页”、“错误弹窗页”。这可以通过判断页面中是否存在某些特征元素来实现。4.2 挑战二业务规则复杂导致的错误操作问题描述LLM可能不理解“用款计划金额不能超过指标可用余额”、“政府采购支付必须关联合同编号”等深层业务规则导致生成的操作序列在业务逻辑上无效。解决方案将业务规则“编码”进提示词和工具函数。在System Prompt中强化规则用清晰、结构化的语言列出所有关键业务约束。例如“规则1支付申请金额必须小于等于所选指标的‘可用额度’。规则2当支出类型为‘政府采购’时‘合同备案编号’字段为必填。”设计规则校验工具创建一个validate_operation工具在Agent准备执行关键操作如提交支付申请前主动检查数据是否符合业务规则。这个工具可以调用一个本地的规则校验器。def validate_payment_data(self, payment_data: str) - str: 验证支付申请数据是否符合财政规则。 data json.loads(payment_data) errors [] if data[amount] 0: errors.append(金额必须大于0。) if data[type] gov_procurement and not data.get(contract_no): errors.append(政府采购类型必须填写合同编号。) # ... 更多规则校验 if errors: return f数据校验失败{.join(errors)} else: return 数据校验通过。然后在Agent的决策流程中插入规则在调用fill_form或执行提交前先调用validate_operation。如果校验失败则将错误信息反馈给LLM让其重新规划或修正数据。4.3 挑战三执行效率与稳定性问题描述完全依赖LLM进行每一步的“思考-决策”对于长流程测试超过20步耗时较长且每次网络调用都有失败风险。优化策略采用“混合模式”和“断点续跑”。关键路径录制与回放对于极其稳定、不变的核心导航路径如“从登录到进入支付申请页面”可以使用Playwright的录制功能生成一段基础脚本。让Agent直接从某个确定的页面状态开始执行可变部分如填写不同的申请数据。这相当于为Agent设置了一个“快速传送点”。子任务封装将“完成一笔支付申请”这样的中等粒度任务封装成一个更大的工具execute_payment_application在这个工具内部用传统的、但参数化的Playwright脚本实现。这样LLM只需要在高层决定“现在要测试支付功能”然后调用这个大工具即可无需干预内部每一步点击。这平衡了灵活性和效率。状态保存与恢复将Browser Context序列化存储。当长时间测试任务意外中断时可以从断点处的页面状态和对话历史恢复让Agent继续执行避免从头开始。5. 效果评估与未来展望经过多个真实财政项目模块的测试这套Playwright Agent方案展现出了显著优势维护成本降低当业务流程微调时如增加一个审核节点通常只需更新system_prompt中的流程描述并提供一个新节点的操作示例。传统脚本可能需要修改多处定位器和逻辑。场景覆盖增强通过让LLM生成不同的测试数据组合可以轻松实现“边界值测试”、“异常流测试”。例如只需告诉Agent“请测试当金额为负数、为零、为超大数时的提交情况”它就能自主规划出多个测试用例并执行。回归测试效率提升将核心业务流程如指标下达、计划申报、支付执行编写成一组高层级的测试任务描述即可让Agent在每次构建后自动执行一遍全流程回归解放人力。当然它并非银弹。初期搭建和“调教”Agent设计提示词、封装工具需要投入对复杂异常场景如从未见过的报错弹窗的处理能力仍依赖LLM的泛化能力和我们提供的错误处理示例库。我个人认为AI在自动化测试领域的渗透会越来越深。下一步我计划探索两个方向一是让Agent具备自学习能力将执行过程中遇到的新页面、新元素自动更新到其知识库中二是实现多Agent协作模拟财政系统中不同角色预算员、审核员、支付员的交互完成端到端的业务流程测试。这听起来更像是一个“虚拟的财政办公室”了。无论如何工具始终为人服务。Playwright Agent不是要取代测试工程师而是成为一个强大的“副驾驶”帮我们处理那些重复、繁琐、基于固定规则的交互让我们能更专注于设计更刁钻的测试场景、探索更深层的业务逻辑缺陷。如果你也在为复杂系统的自动化测试头疼不妨从一个小模块开始尝试引入这个“AI测试员”它可能会给你带来意想不到的惊喜。