ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OCR+LLM自动生成测试用例:从需求文档到结构化用例的完整实践

OCR+LLM自动生成测试用例:从需求文档到结构化用例的完整实践 1. 方案背景与整体设计思路从手动写用例到OCRLLM自动生成做测试的都知道需求文档到测试用例这一步往往比执行用例本身还费头发。不管是新接手的项目还是迭代频繁的老系统产品经理丢过来一份几十页的PRD里面还夹杂着一堆截图、流程图、表格写到用例的时候整个人都是麻的。我试过用传统的需求管理工具做关联追溯也试过让实习生先人工把文档结构化再写用例效率始终上不去。真正让我下定决心搞这套OCRLLM自动生成用例方案的是一次两周迭代里连续三天熬夜补用例的惨痛经历——纯手工从PDF里抠需求点再一条一条翻译成用例步骤基本等于人肉OCR加人肉LLM。1.1 为什么选OCRLLM这个组合先说结论OCR解决的是文档内容进不来的问题LLM解决的是内容看不懂的问题两个缺一不可。很多团队一开始的误区是只上LLM认为大模型直接读文档就行。但实际业务场景里需求文档的形态远没有想象中干净。产品经理习惯把原型截图直接贴进PRD业务方给的需求可能是拍照发过来的白板草图国资或金融类项目里甚至有大量扫描版的历史需求说明。这些内容在LLM眼里根本不可读必须先过OCR这一关把图像变成文字。反过来说只上OCR也不行。传统的OCR引擎哪怕识别率做到99%输出的也只是一堆没有结构的文本流。需求文档里的用户点击登录按钮输入账号密码和未登录状态下访问购物车跳转登录页到底谁是谁的前置条件、哪些是异常分支机器是分不清的。这个语义理解的部分恰恰是LLM最擅长的。所以OCR负责把非结构化图像转成文本LLM负责把非结构化文本转成结构化用例各自解决擅长的问题才算把方案闭环。1.2 方案整体架构与数据流向整个链路我给分成五个环节后续落地的每个细节都围绕这条主链路展开需求文档采集接收PDF、Word、图片、扫描件等多种格式统一转成图像或文本中间态。OCR识别与版面还原识别文字内容、标题层级、表格结构尽量还原文档原有的阅读顺序。文本结构化重组把OCR结果拼装成Markdown等带格式的文本让LLM能理解层级关系。LLM需求解析与用例生成按Prompt模板提取需求点、业务规则生成覆盖正常和异常路径的测试用例。结果校验与导出用JSON Schema校验LLM输出不合格的自动重试或人工修正最终导出为Excel/XMind/测试管理平台可导入的格式。这套架构里最关键的设计决策是文本结构化重组这一层。很多人以为OCR识别完直接丢给LLM就行实际跑过之后就知道没有版面结构的信息LLM经常把需求描述和操作步骤混在一起生成的用例牛头不对马嘴。所以我把这一步单独拎出来用OCR的版面分析结果重建Markdown结构成本不高但效果提升非常明显。提示这套方案不是要完全替代测试工程师而是把看文档、翻截图、抠需求点这种体力活自动化掉工程师只需要做最后的用例评审和补充时间投入能减少70%以上。2. 核心细节解析与实操要点OCR识别层怎么做才靠谱这套方案里OCR其实是最容易翻车的一环因为需求文档的质量参差不齐。我最早拿Tesseract跑中文扫描件识别率惨不忍睹后来换到PaddleOCR才算是稳定下来。这里把踩过的坑和验证过有效的做法整理一下。2.1 图像预处理必须做不能省很多OCR教程会告诉你图像预处理能提升识别率但没告诉你的是在需求文档这个场景里预处理不是锦上添花是生死攸关。我遇到过的最典型情况是业务方用手机拍的白板草图整个图像是歪的文字还有阴影遮挡。这种情况下直接跑OCR出来的文字全是乱的。后来我加了几步预处理流程透视矫正用OpenCV检测文档边缘把倾斜的拍摄图像拉正。白板拍摄经常是斜着拍的这一步不做后续一切都白搭。灰度与二值化去掉背景干扰让文字区域更突出。PaddleOCR内置的预处理做得不错但对光照不均的图像我会先用自适应阈值做一次二值化。降噪与去模糊对扫描件里的噪点做中值滤波对模糊图像做一次锐化。这步还有个容易被忽略的细节分辨率。扫描件分辨率低于200dpi时小字号文字识别率会明显下降最好在预处理阶段就统一把图像放大到合适的尺寸再做识别。2.2 版面分析与表格还原决定LLM能不能看懂第二次翻车是在表格识别上。需求文档里最常见的是权限矩阵表、字段说明表、接口参数表这类表格信息密度极高但也是OCR最容易出错的地方。PaddleOCR内置了版面分析模块能区分文字、标题、表格、图片等区域。但默认模型对复杂表格的支持一般尤其是合并单元格、跨行表头、无边框表格这些情况输出会乱掉。我的做法是用PaddleOCR的版面分析结果做区域分类把表格区域单独切出来。表格区域用专门的表格结构识别模型PaddleOCR里叫TableRec处理输出HTML格式的表格结构。再把HTML表格转成Markdown喂给LLM时它才能理解这个字段属于哪个模块、什么类型、是否必填这些关系。还有一个细节是阅读顺序。OCR识别文字是按检测框输出的并不保证从左到右、从上到下的阅读顺序。如果直接把检测框按坐标排序遇到双栏排版或者图文混排的文档就会乱掉。PaddleOCR的PP-Structure模型在这方面做了优化能按阅读顺序输出我实测下来对大部分PRD文档有效。2.3 OCR引擎选型PaddleOCR为主双引擎兜底选型方面我前后对比过Tesseract、EasyOCR、PaddleOCR和几个商用云OCR。Tesseract对中文的支持太弱EasyOCR速度偏慢商用云OCR效果好但涉及文档外发合规问题很多企业不敢用。最后定的是PaddleOCR原因有三个中文识别效果好对印刷体和清晰手写体都能处理。内置版面分析、表格识别、关键信息抽取一套SDK全搞定。可本地化部署文档不出内网安全合规上没压力。不过PaddleOCR也不是万能的。遇到历史扫描件里的生僻字、异体字或者手写批注叠在印刷体上的情况我还会加一个备用引擎比如本地部署的RapidOCR做交叉验证两个引擎结果不一致时取置信度高的那个。注意OCR识别的目标不是追求100%的文字正确率而是保证关键信息不丢。测试用例生成关注的是功能点和业务规则偶尔个别错别字不影响但数字、金额、状态值这类关键字段错了就会直接导致用例无效所以对这类字段要做二次校验。3. 核心细节解析与实操要点LLM生成层怎么调教才稳定OCR这关过了之后真正的重头戏是LLM怎么把需求文本变成像样的测试用例。这里面的坑比OCR还多尤其是生成结果不稳定这个问题几乎每个用LLM做结构化输出的团队都会遇到。3.1 Prompt设计把需求文档翻译成用例生成指令先说一个最容易犯的错直接甩一段需求文本给LLM说请生成测试用例。这样出来的结果通常泛泛而谈全是套话没有业务深度。我试过几次之后把Prompt设计换成了三段式结构角色与任务定义明确告诉LLM它是资深测试工程师任务是分析需求文档并输出覆盖正常、异常、边界场景的用例。需求上下文把OCR预处理后的Markdown文本完整贴进去并附上文档结构说明。生成规则与输出格式列出用例编号规则、字段定义、覆盖要求、输出为JSON的Schema。其中生成规则是核心。我会在Prompt里明确要求LLM遵循这些约束每个功能需求点至少要有一条正向用例和一条反向用例。涉及数值输入的字段必须补充边界值用例最小值、最大值、临界值、超界值。涉及权限的模块必须覆盖有权限和无权限两种场景。用例步骤要可执行预期结果要可验证不能出现系统正常这种模糊描述。还有一个很好用的技巧在Prompt里加一段Few-shot示例给LLM看一个需求文本和对应用例的样例。不需要多两三条就够。LLM会照着示例的风格和深度来生成输出质量会明显提升。3.2 结构化输出JSON Schema是LLM生成的稳定器用LLM生成用例最大的问题不是生成不了而是生成的格式不稳定。有时候步骤和预期结果混在一个字段里有时候用例标题写成了散文有时候直接输出一段Markdown而不是JSON。我折腾过几轮之后发现单纯在Prompt里写请以JSON格式输出是不够的必须在Prompt里附上完整的JSON Schema定义并且要求LLM严格按Schema输出。Schema长这样{ type: object, properties: { requirements: { type: array, items: { type: object, properties: { requirement_id: { type: string }, requirement_desc: { type: string }, test_cases: { type: array, items: { type: object, properties: { case_id: { type: string }, case_title: { type: string }, precondition: { type: string }, steps: { type: array, items: { type: string } }, expected_result: { type: string }, priority: { enum: [P0, P1, P2, P3] }, test_type: { enum: [功能, 边界, 异常, 权限, 兼容] } }, required: [case_id, case_title, steps, expected_result] } } }, required: [requirement_id, requirement_desc, test_cases] } } } }实测下来给出Schema之后LLM输出的JSON解析成功率从不到60%提升到90%以上。剩下的失败情况再用下面的重试机制兜底。有些LLM服务商提供了JSON Mode或者Function Calling能力比如OpenAI的response_format{type: json_object}或者各家的结构化输出接口能进一步把成功率推到98%以上。如果企业用的是私有化部署模型没有原生JSON Mode那就用Schema约束重试的组合拳效果也够用。3.3 上下文管理与重试机制需求文档动辄几十上百页但LLM的上下文窗口是有限的。一次性全塞进去要么超长被截断要么模型记不住前面的内容生成结果质量下降。我的做法是分段处理按章节拆分需求文档每个章节单独生成用例。每个章节的标题和概述作为上下文前缀确保LLM知道自己当前在处理哪个模块。最后汇总所有章节的用例做一遍去重和编号重排。重试机制也值得说。LLM输出不稳定是常态我设计了三级容错第一级JSON解析失败时自动把报错信息和原始输出回传给LLM要求它修正成合法JSON最多重试两次。第二级JSON解析成功但校验不通过比如缺少必填字段用校验错误信息引导LLM补充。第三级连续三次失败就不再重试把该章节标记为待人工处理写入日志由测试人员手动补充。提示重试时的Prompt设计很讲究要把错误信息原样贴回去并加上请修正上面的输出只返回修正后的JSON不要任何多余说明。这样LLM才能聚焦在修正上而不是又生成一遍完整内容。4. 落地实操从需求文档到测试用例的完整流水线前面讲了不少理论这节直接上能跑的东西。我把整个流水线用Python实现了一遍这里分享核心代码、Prompt模板和一个工业级的执行流程。这套代码我是在一台普通工作站上跑的CPU模式下处理一份20页的PRD大概需要3到5分钟GPU环境可以压缩到1分钟以内。4.1 环境准备与依赖安装用到的核心依赖只有三个PaddleOCR负责文字识别OpenAI SDK负责调用大模型框架通用换成国内模型同样适用只是接口地址和模型名不同OpenPyXL负责Excel导出。pip install paddleocr paddlepaddle openai openpyxl有个小坑提示PaddleOCR的paddlepaddle包体积很大首次安装建议指定CPU版本避免把CUDA全家桶也装进来。4.2 核心代码实现OCR识别LLM生成先看OCR识别部分。我封装了一个函数输入图片路径输出Markdown格式的结构化文本from paddleocr import PaddleOCR import numpy as np ocr PaddleOCR( use_textline_orientationTrue, langch, show_logFalse ) def image_to_markdown(image_path): try: result ocr.predict( image_path, use_ocrTrue, use_layoutTrue, use_tableTrue, use_pieFalse ) except Exception as e: print(f[OCR Error] {image_path}: {e}) return md_lines [] for res in result[0][res]: block_label res[rec_block] if rec_block in res else text text res.get(rec_text, ) if rec_text in res else if table in res: table_html res[table][html] md_lines.append(html_table_to_markdown(table_html)) elif block_label title: md_lines.append(f## {text}) elif block_label text: md_lines.append(text) elif text.strip(): md_lines.append(text) return \n.join(md_lines)这段代码精髓在于use_layoutTrue和use_tableTrue这两个参数。开启之后PaddleOCR会输出文档结构信息我能按标题、正文、表格分块处理而不是把所有文字挤成一团。LLM生成部分我用的是OpenAI格式的接口调用把前面说的三段式Prompt封装成一个函数from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlyour-llm-endpoint ) def generate_test_cases(markdown_text, schema, modelgpt-4o): sys_prompt 你是一位资深测试工程师专门负责从需求文档中提取功能需求并设计高质量的测试用例。 你的输出必须严格遵循给定的JSON Schema只输出JSON不输出任何解释。 user_prompt f下面是需求文档内容 {markdown_text} 请提取文档中的功能需求点并为每个需求点生成测试用例。要求 1. 每个功能需求点至少一条正向用例和一条反向用例 2. 数值型字段必须包含边界值用例 3. 涉及权限的操作必须覆盖有权限和无权限场景 4. 用例步骤必须具体可执行预期结果必须明确可验证 5. 严格按以下JSON Schema输出{json.dumps(schema, ensure_asciiFalse)} response client.chat.completions.create( modelmodel, response_format{type: json_object}, messages[ {role: system, content: sys_prompt}, {role: user, content: user_prompt} ], temperature0.2 ) return response.choices[0].message.contenttemperature0.2这个参数是我反复调出来的。太高容易编造需求太低用例格式虽然稳定但措辞会变得很机械。0.2到0.3之间是个比较平衡的区间。4.3 Prompt模板与用例质量校验纯靠Prompt写用例质量不能完全保证。我在流水线里加了一个质量校验节点用一套规则自动检查用例是否达标覆盖率检查需求文档里出现的功能关键词登录、注册、查询、导出、权限等是否在用例标题或步骤中有对应。边界值检查数值型输入字段是否包含最小值、最大值、超界值用例。反向用例检查每个需求点是否至少有一条预期结果为失败/拦截/提示的用例。重复检查不同需求点之间不能出现完全相同的用例标题。校验不通过时有两种处理方式如果只是个别用例缺失让LLM针对缺失项补生成如果问题较多整段打回重生成。实测下来带上质量校验后最终交给人工评审的用例质量明显提升。4.4 导出与测试管理平台对接生成结果统一转成二维表结构然后导出。我习惯导出两种格式Excel方便测试组内评审和归档每行一条用例。XMind用python-xmind库生成思维导图适合做需求覆盖度评审一图看清每个模块有多少用例。如果公司的测试管理平台禅道、TestRail、Jira等有OpenAPI也可以直接对接导入。Excel导出的Excel列我固定为模块、用例编号、用例标题、前置条件、操作步骤换行分隔、预期结果、优先级、用例类型。5. 踩坑实录与排查技巧这些问题我替你先试过了方案落地过程中我基本把能踩的坑都踩了一遍。这里挑几个典型问题附带定位思路和解决方法希望能帮你少走弯路。5.1 OCR翻车现场问题一表格识别后行列错乱。有一次处理需求文档里的权限矩阵表识别结果把管理员列和普通用户列的内容搞反了导致生成的用例断言全错。排查发现是表格结构模型对无边框表格的泛化能力不足。后来我在表格导出后加了一个表头逻辑校验逻辑如果检测到行首单元格是常规权限角色词管理员、用户、访客等则把该行强制作为列头处理。问题二多栏排版识别顺序错乱。双栏文档会被OCR按左栏读完再读右栏的规则拼接但遇到图文混排时这个规则会失效。建议开启PaddleOCR的阅读顺序排序参数或者在预处理阶段把双栏文档按栏切割成两张图分别识别再手动拼回。问题三扫描件背景噪点太多。解决办法是二值化加中值滤波。OpenCV里几行代码的事import cv2 img cv2.imread(scan.png, cv2.IMREAD_GRAYSCALE) img cv2.medianBlur(img, 3) # 去掉椒盐噪声 _, img cv2.threshold(img, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 自适应二值化5.2 LLM输出不听话怎么办问题一输出JSON带Markdown代码块。部分模型即使要求只输出JSON还是会包一层json代码块。解决方法是在解析时先做一次去代码块处理text response.choices[0].message.content.strip() if text.startswith(): text text.strip() text text.removeprefix(json\n)问题二生成的用例只有正向场景。这个问题在早期版本特别明显LLM只会写正常流程能走通的用例异常、边界、权限相关的基本不生成。用至少一条反向用例之类的硬性规则约束了生成后才好转。Prompt里明确写这类规则比等LLM自觉可靠得多。问题三需求文档过长LLM生成越来越敷衍。上下文太长会导致模型把前面的内容丢掉后半段生成的用例明显变浅。这个问题的本质是上下文管理的缺陷分段处理是最有效的解法。把文档按章节切好后每个章节单独生成再汇总去重。5.3 常见问题速查表问题现象根因解决方案OCR识别后文字乱序未开启版面阅读顺序开启PaddleOCR的版面分析功能表格行列错乱无边框表格或合并单元格识别失败表格区域单独走表格结构模型识别后做表头逻辑校验LLM输出的JSON解析失败缺少Schema约束或模型较弱在Prompt中提供完整JSON Schema开启JSON Mode用例全是正向场景Prompt缺少反向用例规则明确要求异常、边界、权限场景覆盖用Few-shot示例引导用例重复或漏项长文档一次性处理按章节分段生成汇总后做去重和覆盖率检查数值字段用例错误OCR识别出错或LLM理解偏差对数字、金额类关键字段做OCR二次校验生成后人工抽检5.4 一份可复制的落地路线图如果你正打算在团队里推行这套方案我建议按下面的节奏来不要一上来就追求全自动化第一阶段1周跑通OCR识别链路先做到需求文档转结构化文本人工核对识别质量。第二阶段1-2周跑通LLM生成链路先用3到5份真实需求文档做验证人和LLM各写一份用例对比覆盖率和质量。第三阶段2周加上质量校验和重试机制沉淀Prompt模板和Schema。第四阶段持续收集人工评审时标记的无效用例和缺陷用例定期用这些数据微调Prompt或做少量模型微调让生成质量持续提升。我个人在实际操作中的最大体会是这套方案真正提升的不是用例生成这一步而是把整个测试设计的思考过程被迫前置了。因为要让LLM生成好用例你首先得把需求文档梳理清楚、把规则边界定义明白这个梳理过程本身就是测试设计的一部分。所以哪怕最终生成结果只有70%能用剩下的30%靠人工补整体效率也远高于从零开始写。最后再分享一个小技巧Prompt里加一条如果需求文档中存在歧义或不完整的内容请在用例的备注字段中标注待确认。这一条能帮测试工程师提前发现需求缺陷而且往往是最有价值的产出——毕竟测试用例写得再好需求本身就是错的那用例质量再高也没用。
返回列表