基于Qwen3-VL多模态大模型实现UI自动化测试脚本智能生成

发布时间:2026/6/30 19:07:20

基于Qwen3-VL多模态大模型实现UI自动化测试脚本智能生成 1. 项目概述当大模型“看见”你的软件界面最近在折腾自动化测试一个老生常谈的痛点又浮上水面UI自动化测试脚本的编写和维护成本太高了。每次UI元素一改定位器XPath、CSS Selector就失效测试工程师就得化身“考古学家”在代码里一点点比对、修复。这活儿既枯燥又容易出错严重拖慢了敏捷交付的节奏。直到我注意到了阿里通义千问团队开源的Qwen3-VL模型。这可不是一个普通的聊天模型它是一个“视觉-语言”多模态大模型简单说就是既能看懂图片又能理解文字指令。我就在想如果让它“看”一眼我们的软件界面截图然后直接告诉它“帮我生成点击登录按钮的测试脚本”这事儿是不是就成了顺着这个思路我基于社区里一个非常活跃的Qwen3-VL-WEBUI项目做了一次深入的探索和实践。这个WEBUI项目提供了一个图形化界面让我们可以方便地上传图片、输入指令与Qwen3-VL模型进行交互而无需关心复杂的模型部署和API调用。我的目标很明确验证这套技术方案能否真正实现从“UI识别”到“用例生成”的自动化流水线把测试工程师从繁琐的定位器编写中解放出来让他们更专注于测试设计和业务验证。简单来说这次实践就是给模型一张软件界面的截图让它理解界面上的元素按钮、输入框、列表等及其功能然后根据测试需求自动生成可执行的自动化测试代码比如基于Selenium或Playwright的Python脚本。这听起来像是测试领域的“魔法”但背后其实是多模态大模型和提示词工程Prompt Engineering的结合。接下来我就把这次从环境搭建到实际落地的完整过程、踩过的坑以及一些独家心得毫无保留地分享出来。2. 核心思路与技术选型解析2.1 为什么是Qwen3-VLWEBUI在开始动手之前我们需要理清为什么选择这个技术栈。市面上视觉相关的AI模型不少比如GPT-4V、Gemini Pro Vision以及一些开源的如LLaVA。选择Qwen3-VL-WEBUI组合主要基于以下几点考量1. 模型能力与成本平衡Qwen3-VL作为国产开源模型的佼佼者在多项中英文多模态评测中表现亮眼。对于UI识别这种相对结构化的视觉理解任务它的精度已经足够可用。最关键的是它完全开源我们可以本地部署避免了调用闭源商业API带来的高昂成本和数据隐私担忧。虽然GPT-4V可能在某些复杂场景下更聪明但考虑到测试脚本生成是一个需要反复调试、频繁请求的过程本地模型的“免费”和“可控”优势巨大。2. WEBUI带来的极致便利性Qwen3-VL-WEBUI这个项目本质上是一个为Qwen3-VL模型量身定制的图形化聊天前端。它基于Gradio或Streamlit等框架构建将模型推理、对话历史、图片上传等功能封装成了一个开箱即用的Web应用。对于测试工程师而言这意味着零代码交互不需要写一行Python代码去调用模型打开浏览器就能用。直观的视觉反馈可以上传截图看到模型的回复进行多轮对话来修正指令整个过程符合人的直觉。快速迭代提示词我们可以直接在UI的输入框里修改给模型的指令Prompt即时看到不同Prompt带来的输出变化这对于优化用例生成逻辑至关重要。3. 技术栈的亲和性整个方案基于Python生态。Qwen3-VL模型由PyTorch驱动WEBUI项目通常也使用Python编写。这对于测试团队来说学习成本较低因为现代自动化测试框架如pytest、Playwright也基本都是Python/Node.js生态的生成的脚本能无缝集成到现有的测试工程中。注意选择开源方案也意味着需要自己处理环境配置、资源GPU/显存和可能的模型微调。如果你的团队没有相应的工程能力或者追求极致的开箱即用和稳定性一些云服务商提供的视觉理解API也是备选但需要仔细评估其成本和对测试数据的隐私政策。2.2 整体工作流设计我们的目标不是做一个花架子而是要形成一个可重复、可集成的工作流。我设计的核心流程如下截图采集使用系统截图工具或自动化测试工具如Playwright的screenshot方法获取待测应用界面的高清截图。视觉理解与元素描述将截图上传至Qwen3-VL-WEBUI通过精心设计的Prompt让模型识别出界面中的关键交互元素并用自然语言或结构化数据如JSON描述出来。例如“左上角有一个深蓝色的‘登录’按钮中间有两个文本输入框上面的标签是‘用户名’下面是‘密码’下方有一个‘记住我’复选框。”测试用例生成基于元素描述再次向模型发出指令要求其针对特定场景生成测试代码。例如“请为这个登录界面生成一个Python脚本使用Playwright库测试用例为‘输入正确的用户名和密码点击登录验证跳转成功’。”代码后处理与集成模型生成的代码可能包含一些小错误或不符合团队规范。我们需要一个简单的后处理脚本或人工检查来修正这些问题然后将脚本集成到主流的测试框架如pytest中加入断言、数据驱动等逻辑。执行与验证运行生成的自动化脚本验证其是否能正确执行并完成测试目标。这个流程的核心在于第2步和第3步的Prompt工程。模型的表现好坏几乎完全取决于我们如何“提问”。接下来我们就进入实操环节看看如何一步步搭建起这个系统。3. 环境搭建与核心工具部署3.1 基础环境准备首先你需要一台拥有足够资源的机器。由于Qwen3-VL是大型模型强烈推荐使用带有NVIDIA GPU的服务器或本地电脑。CPU也能运行但速度会慢到让你怀疑人生完全无法用于交互式调试。操作系统Linux (Ubuntu 20.04/22.04) 或 Windows (WSL2) 是首选。macOS (M系列芯片) 也可行但需要配置Metal后端。Python版本建议3.8 - 3.10。使用conda或venv创建独立的虚拟环境是必须的避免包冲突。CUDA与cuDNN如果你使用NVIDIA GPU请根据你的显卡型号和PyTorch版本安装对应版本的CUDA工具包如11.7 11.8和cuDNN。这是GPU加速的基础。Git用于拉取代码。3.2 部署Qwen3-VL模型这里我们以使用Transformers库加载模型为例这是最通用和主流的方式。安装PyTorch前往 PyTorch官网 根据你的CUDA版本选择正确的安装命令。例如# 假设CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118安装Transformers及相关库pip install transformers accelerate sentencepiece pillowaccelerate库用于优化模型加载和推理sentencepiece是分词器所需pillow用于图像处理。下载模型Qwen3-VL模型在Hugging Face Model Hub上。你可以使用snapshot_download来下载或者直接用git lfs克隆。这里推荐用snapshot_download更稳定。from huggingface_hub import snapshot_download model_path snapshot_download(repo_idQwen/Qwen3-VL-7B-Instruct) # 以7B指令微调版为例模型有几个版本如2B 7B 72B对于UI识别任务Qwen3-VL-7B-Instruct在精度和资源消耗上是一个不错的平衡点。首次下载需要较长时间和足够的磁盘空间约15GB。编写一个简单的验证脚本确保模型能正确加载和进行单轮对话。from transformers import AutoModelForCausalLM, AutoTokenizer from PIL import Image import torch model_name ./models/Qwen3-VL-7B-Instruct # 你下载的模型本地路径 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.float16, # 使用半精度减少显存占用 device_mapauto, # 自动分配模型层到GPU/CPU trust_remote_codeTrue ).eval() # 准备一张测试图片和问题 image_path ./test_ui.png image Image.open(image_path).convert(RGB) question 描述这张图片里的所有可交互元素。 query tokenizer.from_list_format([ {image: image_path}, {text: question}, ]) inputs tokenizer(query, return_tensorspt) inputs inputs.to(model.device) with torch.no_grad(): pred model.generate(**inputs, max_new_tokens512) response tokenizer.decode(pred.cpu()[0], skip_special_tokensTrue) print(response)如果能成功输出对图片的描述说明模型部署成功。3.3 部署Qwen3-VL-WEBUI有了模型接下来让我们给它装上“眼睛”和“嘴巴”——WEBUI。社区有几个优秀的项目例如基于Gradio的qwen3-vl-webui。这里以其中一个典型项目为例。克隆WEBUI仓库git clone https://github.com/xxx/qwen3-vl-webui.git # 请替换为实际的仓库地址 cd qwen3-vl-webui安装WEBUI依赖pip install -r requirements.txt通常requirements.txt里会包含gradio,transformers,pillow等。配置模型路径你需要修改WEBUI的配置文件或启动参数指向你本地下载好的Qwen3-VL模型路径。具体方式因项目而异通常是在一个config.yaml文件或直接修改app.py里的model_name_or_path变量。启动WEBUI服务python app.py或者根据项目说明使用特定的启动命令。成功启动后终端会输出一个本地URL例如http://127.0.0.1:7860。访问与验证在浏览器中打开上述URL。你应该能看到一个简洁的聊天界面通常包含一个聊天历史区域。一个文本输入框。一个图片上传按钮。一个发送按钮。 尝试上传一张简单的UI截图比如一个计算器应用并输入“这是什么界面”如果模型能正确回答说明WEBUI部署成功。实操心得在部署过程中最大的坑往往是显存不足。7B的模型在FP16精度下需要大约14GB的显存。如果你的显卡显存不够比如只有8GB可以尝试以下方案使用量化模型寻找社区提供的GPTQ、AWQ或GGUF量化版本的Qwen3-VL可以大幅降低显存需求例如INT4量化后可能只需4-6GB。使用device_map和offloadtransformers的device_map”auto”会尝试将模型层均匀分配到可用的GPU和CPU内存中。对于显存紧张的机器可以结合accelerate进行更精细的CPU offload但这会显著降低推理速度。降级模型考虑使用更小的Qwen3-VL-2B模型但需要接受精度可能下降的现实。云服务如果本地资源实在有限可以考虑在云服务器如AutoDL、Lambda Labs上按需部署按小时计费对于短期实验成本可控。4. Prompt工程教会模型“看懂”UI并生成代码环境搭好了模型也能对话了但如果你直接扔一张图然后说“生成测试脚本”得到的结果很可能驴唇不对马嘴。关键在于Prompt提示词。我们需要通过精心设计的Prompt引导模型按照我们设定的步骤和格式进行思考。4.1 第一阶段Prompt结构化元素识别我们的第一步是让模型不是泛泛而谈而是以结构化的方式输出界面元素信息。这为后续生成代码提供了准确的“坐标”和“属性”。一个基础的元素识别Prompt示例你是一个专业的UI自动化测试助手。请仔细分析用户提供的这张软件界面截图。 你的任务是 1. 识别出图中所有可交互的UI元素例如按钮、文本输入框、复选框、单选框、下拉列表、链接、滑块等。 2. 对于每个识别出的元素请以JSON数组的格式提供以下信息 - element_type: 元素类型如button, text_input, checkbox。 - description: 对该元素的简短文字描述包括其上的文字或图标含义如“登录按钮”、“用户名输入框”。 - approximate_position: 元素在图片中的大致位置描述如“左上角”、“中央偏右”、“底部导航栏第二个图标”。这有助于在代码中通过文本定位。 - likely_identifier: 推测该元素在代码中最可能用于定位的属性值如按钮上的文字“登录”输入框旁的标签“用户名”。如果元素上有清晰文字优先使用文字。 请严格按照以下JSON格式输出不要有任何额外的解释或标记 [ { “element_type”: “...”, “description”: “...”, “approximate_position”: “...”, “likely_identifier”: “...” }, ... ]为什么这样设计角色设定开头明确模型角色使其进入特定语境。任务分解将“识别”这个复杂任务拆解为两个清晰的子步骤。结构化输出强制要求JSON格式便于我们后续用程序解析。likely_identifier字段是关键它直接关联到自动化脚本中的定位策略如Playwright的get_by_text(“登录”)。位置描述虽然无法提供像素级坐标但“左上角”、“中央”等描述在结合上下文定位如先定位某个区域时仍有参考价值。4.2 第二阶段Prompt基于场景的代码生成拿到结构化的元素列表后我们就可以针对具体测试场景生成代码了。这里需要指定测试框架和编程语言。一个针对登录场景的代码生成Prompt示例你是一个资深的Python自动化测试工程师。现在需要为一个Web登录页面编写测试脚本。 已知该页面的UI元素信息如下JSON格式 [ {“element_type”: “text_input”, “description”: “用户名输入框”, “likely_identifier”: “用户名”}, {“element_type”: “text_input”, “description”: “密码输入框”, “likely_identifier”: “密码”}, {“element_type”: “checkbox”, “description”: “记住我复选框”, “likely_identifier”: “记住我”}, {“element_type”: “button”, “description”: “登录按钮”, “likely_identifier”: “登录”} ] 测试场景验证用户使用正确的凭据可以成功登录。 请使用 Playwright for Python 测试框架编写一个完整的测试函数。要求如下 1. 函数名为 test_valid_login。 2. 使用 pytest 风格函数以 test_ 开头。 3. 使用 playwright.sync_api 的同步API。 4. 使用元素上最可能的文字标识likely_identifier进行定位优先使用 page.get_by_text() 或 page.get_by_label() 方法。 5. 在用户名输入框输入 “test_user”在密码输入框输入 “secure_password123”。 6. 点击登录按钮。 7. 添加断言验证登录成功后页面的跳转或某个成功登录后才出现的元素例如用户头像或“欢迎”字样。请根据常识推断一个合理的成功后的验证点。 8. 代码应包含必要的导入语句和完整的函数体。 9. 在代码中为关键步骤添加简要的注释。 请只输出最终的Python代码不要有任何额外的解释或标记。为什么这样设计提供上下文将上一阶段得到的JSON直接作为输入让模型知道它要操作的对象是什么。明确约束详细指定了框架Playwright、语言Python、风格pytest、API类型同步、定位策略优先按文本。这极大提高了生成代码的可用性和一致性。定义场景与数据明确了测试用例的具体步骤和测试数据。要求断言强调了测试的核心——验证并引导模型根据常识添加合理的断言。格式化输出要求“只输出代码”避免了模型输出冗余的自然语言描述方便我们直接复制粘贴。4.3 Prompt迭代与优化技巧在实际操作中很少能一次就写出完美的Prompt。你需要根据模型的输出进行迭代优化。少样本学习Few-Shot Learning如果模型对某种复杂元素如自定义图标按钮、动态加载列表识别或代码生成不理想可以在Prompt中提供一两个例子。例如在元素识别Prompt后附加“例如对于一个购物车图标按钮输出应为{“element_type”: “button”, “description”: “购物车图标按钮”, “approximate_position”: “右上角”, “likely_identifier”: “购物车”}”分步引导对于非常复杂的界面或操作流程不要试图让模型一步到位。可以先让它描述界面然后你根据描述再让它生成操作A的代码接着生成操作B的代码最后组合。纠正与反馈当模型输出错误时将错误的输出和你的纠正一起作为新的对话历史输入告诉模型“刚才哪里错了应该怎样”。多轮对话后模型在同一会话中会表现得更好。温度Temperature参数在WEBUI的高级设置中通常可以调整temperature默认0.7左右。对于需要确定性、结构化输出的任务如生成JSON和代码可以适当调低如0.2让模型的输出更集中、更可预测。对于需要创意的任务可以调高。5. 完整实践流程从截图到可执行脚本现在让我们串联起所有环节完成一个端到端的示例。假设我们要为一个简单的TODO List Web应用生成一个“添加新待办事项”的测试用例。5.1 步骤一获取待测界面截图使用任何截图工具如Snipaste、Playwright的page.screenshot()截取TODO应用的主界面。确保截图清晰包含“输入框”和“添加按钮”。5.2 步骤二在WEBUI中执行元素识别打开部署好的Qwen3-VL-WEBUI。上传TODO应用的截图。在文本框中输入我们精心设计的第一阶段Prompt结构化元素识别。点击发送。模型可能返回的JSON示例[ { “element_type”: “text_input”, “description”: “新增待办事项输入框”, “approximate_position”: “页面顶部中央” “likely_identifier”: “Add a new todo” }, { “element_type”: “button”, “description”: “添加事项按钮” “approximate_position”: “输入框右侧” “likely_identifier”: “Add” }, { “element_type”: “list”, “description”: “待办事项列表” “approximate_position”: “输入框下方” “likely_identifier”: null } ]5.3 步骤三生成测试脚本在WEBUI中开启一个新的对话轮次或继续当前对话。输入框中放入我们设计的第二阶段Prompt代码生成。注意要将上一步得到的JSON数组粘贴到Prompt中对应的位置。点击发送。模型可能生成的Python代码示例import pytest from playwright.sync_api import Page, expect def test_add_new_todo_item(page: Page): “”“测试添加新的待办事项。”“” # 假设页面已打开URL为应用首页 # page.goto(“http://localhost:3000“) # 定位新增待办事项输入框并输入文本 input_box page.get_by_placeholder(“Add a new todo”) # 使用placeholder定位这是根据likely_identifier和常见模式推断的 input_box.fill(“Learn Qwen3-VL for UI testing”) # 定位并点击添加按钮 add_button page.get_by_text(“Add”) add_button.click() # 断言新添加的待办事项出现在列表中 # 假设列表中的每个事项由一个具有特定文本的列表项li或div表示 # 这里我们断言包含我们输入文本的元素是可见的 new_todo_item page.get_by_text(“Learn Qwen3-VL for UI testing”) expect(new_todo_item).to_be_visible()5.4 步骤四代码后处理与集成模型生成的代码已经非常接近可用了但通常需要一些手动微调修正定位器模型可能使用了get_by_placeholder但实际元素可能是get_by_label或get_by_role。你需要根据实际应用的HTML结构使用浏览器开发者工具检查并修正定位方式。这是目前AI无法完全替代的一步因为模型“看”不到HTML源码。补充上下文模型生成的函数通常不包含打开浏览器、导航到URL、关闭浏览器等Fixture。你需要将其嵌入到你的pytest测试类或Fixture中。添加等待与稳定性处理AI生成的代码通常比较“理想化”缺少对网络延迟、元素加载动态性的处理。你需要添加适当的等待例如page.wait_for_selector()或 Playwright 的自动等待机制。数据驱动将测试数据如”Learn Qwen3-VL for UI testing”提取到外部文件或参数化装饰器中使脚本更易于维护。优化后的集成脚本示例# conftest.py 或测试文件顶部 import pytest from playwright.sync_api import Page, expect pytest.fixture(scope“function”) def todo_page(page: Page): “”“打开TODO应用首页。”“” page.goto(“http://localhost:3000“) yield page # 测试后清理可选 # 测试用例文件 class TestTodoApp: def test_add_new_todo_item(self, todo_page: Page): “”“测试添加新的待办事项。”“” test_todo_text “Learn Qwen3-VL for UI testing” # 使用更稳健的定位先找输入框的label然后定位到对应的input # 假设HTML结构为label for”new-todo”Add a new todo/labelinput id”new-todo” / input_box todo_page.get_by_label(“Add a new todo”) input_box.fill(test_todo_text) add_button todo_page.get_by_role(“button”, name“Add”) # 使用role定位可能更准确 add_button.click() # 添加显式等待确保新项目已添加到DOM todo_page.wait_for_selector(f“text{test_todo_text}”) new_todo_item todo_page.get_by_text(test_todo_text) expect(new_todo_item).to_be_visible()经过以上四步一个由AI辅助生成的、基本可用的UI自动化测试脚本就诞生了。虽然需要一些人工后处理但其核心逻辑和代码骨架已经由模型完成节省了大量编写基础代码的时间。6. 常见问题、局限性与应对策略在实际使用中你肯定会遇到各种问题。下面是我踩过的一些坑以及总结的应对策略。6.1 模型识别不准确或“幻觉”问题模型可能将背景图案误认为按钮或者对相似元素如一排图标描述混乱。更严重的是产生“幻觉”即生成界面上根本不存在的元素描述。对策提供更清晰的截图确保截图分辨率高、光线均匀、只包含目标界面避免无关的桌面或浏览器边框干扰。细化Prompt在识别Prompt中增加约束如“只识别主要的、用户可交互的元素”“忽略纯装饰性的图片和背景”。分区域识别对于复杂界面可以分别截取不同功能区域的截图让模型分而治之。人工校验与修正必须将模型输出的元素列表与实际界面进行人工比对和修正。这是保证后续步骤正确的基石。6.2 生成的代码定位器策略不佳问题模型倾向于使用get_by_text()但文本可能动态变化、不唯一或存在国际化问题。它也可能选择脆弱的XPath。对策在Prompt中明确最佳实践如“优先使用get_by_role(),get_by_label(),get_by_test_id()等语义化定位方式其次考虑get_by_text()避免使用XPath。”后处理中统一替换将模型生成的get_by_text(“登录”)批量替换为更稳健的get_by_role(“button”, name“登录”)如果HTML结构支持。引入测试属性推动开发团队为关键交互元素添加稳定的测试ID如>

相关新闻