☰
DeepSeekAPI智能用例生成实战:自动化测试完整方案
2026/10/21 8:41:46 网站建设 项目流程

简介:面向软件测试工程师与自动化测试开发者的23页PDF文档,系统讲解如何借助DeepSeek API构建智能用例生成方案。文档从自动化测试框架的定义与常见类型讲起,依次介绍DeepSeek API的基本概念、技术特点、应用场景和密钥获取方式,然后围绕需求理解、用例生成、用例评估三个阶段,详细拆解需求预处理、语义提取、模板匹配、规则推理、API辅助生成以及覆盖率计算等核心步骤,并配有完整代码示例与分步解释,便于读者在真实项目里复现调用流程。整体目录结构完整,涵盖环境搭建、需求文档处理、模板定义、性能评估、电商登录与在线教育课程管理等案例,也对需求理解准确性、数据隐私和成本限制等挑战做了分析。资源包为单个PDF文件,大小约1.83MB,已有187人学习,适合需要将大模型能力落地到自动化测试中的中高级测试人员参考。

1. 智能用例生成不是玄学:DeepSeekAPI 在自动化测试里的真实位置

手工维护用例的瓶颈迟早会来,尤其是需求文档堆到几十页时,靠人肉拆解功能点再一条条补边界值,很容易漏场景。这套基于 DeepSeekAPI 的智能用例生成方案,思路是把需求文档喂给大模型,先生成一批基础用例,再结合模板与覆盖率指标做筛选和补充。它不是要完全取代测试工程师,而是把人从重复劳动里解放出来。适合正在做自动化测试平台搭建、想引入 AI 辅助的测试开发或 QA 团队,也适合对用例生成流程好奇的从业者。下面从框架选型讲起,落地到代码和避坑。

2. 自动化测试框架选型:从线性到数据驱动,智能用例生成绕不开模板

2.1 三类常见框架的代码形态与适用边界

在聊智能用例生成之前,得先把底层框架摸清楚。文档里把自动化测试框架分成三类,这个划分在落地时很有参考价值。

线性框架是最直白的写法,把测试步骤按顺序堆起来。以 Selenium 为例,基本就是“创建驱动→打开页面→输入关键词→点击→关闭”。

from selenium import webdriver driver = webdriver.Chrome() driver.get("https://example.com/login") search_box = driver.find_element_by_id("kw") search_box.send_keys("自动化测试") search_button = driver.find_element_by_id("su") search_button.click() driver.quit()

这段代码能跑,但复用性很差。一旦登录按钮的 ID 变了,或者需要换个浏览器,就得全文搜索去改。我一般只在冒烟测试或者一次性脚本里用线性框架,正式测试工程里不会这么写。

模块化框架把公共操作抽成函数,后续用例看起来会清爽很多。

from selenium import webdriver def open_browser(url): driver = webdriver.Chrome() driver.get(url) return driver def search_keyword(driver, keyword): search_box = driver.find_element_by_id("kw") search_box.send_keys(keyword) search_button = driver.find_element_by_id("su") search_button.click() driver = open_browser("https://example.com/login") search_keyword(driver, "自动化测试") driver.quit()

这里的关键是职责划分:打开浏览器是一个独立动作,搜索又是另一个动作。后续如果有新的测试场景,直接复用open_browser和search_keyword就行。模块化的缺点是设计成本会上去,如果模块划分得不好,函数之间互相传参,耦合度反而比线性框架更高。

数据驱动框架是这几类里最接近工程化标准的。它把测试数据抽到外部文件,脚本只负责执行逻辑。

import csv from selenium import webdriver def search_keyword(driver, keyword): search_box = driver.find_element_by_id("kw") search_box.send_keys(keyword) search_button = driver.find_element_by_id("su") search_button.click() with open('test_data.csv', 'r', encoding='utf-8') as file: reader = csv.reader(file) next(reader) # 跳过表头 for row in reader: keyword = row[0] driver = webdriver.Chrome() driver.get("https://example.com/login") search_keyword(driver, keyword) driver.quit()

数据驱动的好处是,新增一条测试数据只需要在 CSV 里加一行,不需要改代码。坏处是 CSV 文件多了以后,管理成本会转移给数据维护的人。这三种框架在文档里讲得很清楚,顺序安排也合理,但真正让智能用例生成落地的,不是框架本身,而是模板机制。

2.2 为什么智能用例生成绕不开模板

很多人以为“智能”就是把需求文本直接丢给 DeepSeekAPI,然后等它吐出一堆用例。实际操作下来会发现,大模型生成的结果虽然语言通顺,但结构不稳定。它会偶尔漏掉步骤、把预期结果写得模棱两可,甚至自行脑补需求里没有的功能。

所以在这套方案里,模板匹配是第一道防线。先根据需求中的关键信息,从预先定义好的模板库里匹配出基础用例,比如“正常登录”“用户名错误”“密码错误”这些。这一步不依赖大模型,结果完全可控。然后再把基础用例和需求文本一起作为输入,交给 DeepSeekAPI 做补充生成,让它往更多边界场景上发散。

这个设计很务实。模板负责兜底,大模型负责扩容。如果一开始就全交给大模型,代码评审的时候你根本没法判断它生成的用例到底对不对;有了模板做骨架,至少能保证每条生成结果都有基本的结构。

模板库本身也值得设计。文档里给出的登录模板是这样的:

login_templates = [ { "test_case_name": "正常登录测试", "test_steps": [ "打开登录页面", "在用户名输入框输入合法的用户名", "在密码输入框输入合法的密码", "点击登录按钮" ], "expected_result": "成功登录系统,跳转到主页" }, { "test_case_name": "异常登录(用户名错误)测试", "test_steps": [ "打开登录页面", "在用户名输入框输入错误的用户名", "在密码输入框输入合法的密码", "点击登录按钮" ], "expected_result": "系统提示用户名错误,登录失败" } ]

我一般会把模板按业务模块分文件存,比如login_templates.json、order_templates.json,再用 Python 的字典按模块名加载。这样模板库大了之后,维护时不需要改主流程代码。

2.3 从需求到用例的完整处理链路

整套方案的处理链路可以拆成六步:需求文档读取、文本预处理、关键信息提取、模板匹配、DeepSeekAPI 辅助生成、用例评估与优化。

读取环节需要处理编码问题,尤其是 Windows 环境下经常遇到 GBK 和 UTF-8 打架。预处理环节负责清掉特殊字符、多余空格,再做分词和词性标注。关键信息提取是承上启下的一步,这里用命名实体识别找出“用户”“登录页面”“用户名”这类实体,才能决定用例模板往哪个方向匹配。

模板匹配之后会得到一组初步用例,质量基本够用,但覆盖不一定完整。比如需求里写了“用户输入的年龄必须在 18 到 60 岁之间”,模板里如果只有正常输入,就漏掉了边界值 17、18、60、61。这时 DeepSeekAPI 的辅助生成就派上用场了,把需求文本和初步用例一起发过去,让它补充边界值、异常场景、网络异常这些内容。

最后一步是质量评估。文档里提到了覆盖率、可读性、独立性三个指标。覆盖率可以用需求跟踪矩阵来量化,可读性靠人工评审,独立性要检查用例之间有没有互相依赖。这套链路看起来长,但每一步都不是虚的,后面我会把每个环节的代码和参数摊开讲。

3. 基于 DeepSeekAPI 的智能用例生成实现:从需求文本到用例落地的完整链路

3.1 环境准备:Python、依赖库、API 密钥

实现这套方案的环境要求不高,Python 3.8 以上就行。我习惯用虚拟环境隔离依赖,避免把系统 Python 搞乱。

pip install requests jieba transformers

requests负责调用 DeepSeekAPI,jieba处理中文分词,transformers用来做命名实体识别。transformers是个重家伙,第一次安装会下载不少依赖,如果只是做实体识别,也可以换成轻量级的调用方式,比如直接请求一个预置的 NER 服务。但文档里用的是 Hugging Face 的 pipeline,所以先把transformers装上是稳妥的。

API 密钥需要去 DeepSeek 开放平台注册后申请。拿到密钥之后,不要硬编码在脚本里。我一般放到环境变量或者项目根目录的.env文件,然后通过os.getenv("DEEPSEEK_API_KEY")读取。硬编码密钥最大的风险是代码一旦提交到仓库,密钥就泄露了。

3.2 需求文档读取与文本预处理

需求文档通常以.txt或.md格式保存,读取时要注意编码。下面这个函数是文档里的标准写法:

def read_requirement_file(file_path): try: with open(file_path, 'r', encoding='utf-8') as file: requirement_text = file.read() return requirement_text except FileNotFoundError: print(f"文件 {file_path} 未找到。") return None

读完之后先别急着分词,要把噪声清掉。需求文档里经常有表格符号、无序列表的横杠、多余空格,这些都会干扰后面的实体识别。预处理的代码可以这样写:

import re import jieba import jieba.posseg as pseg def preprocess_text(text): # 去除特殊符号和多余空格 text = re.sub(r'[^\w\s]', '', text) text = re.sub(r'\s+', ' ', text).strip() # 中文分词 words = jieba.lcut(text) # 词性标注 pos_tagged = [(word, flag) for word, flag in pseg.cut(text)] return pos_tagged

这里有个容易忽略的参数:re.sub(r'[^\w\s]', '', text)会把所有非单词非空格的字符删掉,包括中文句号、逗号、括号。如果需求文本里有“用户点击【确认】按钮”,删除特殊符号后变成“用户点击确认按钮”,语义没变,但括号里的限定词丢了。所以真正做预处理时,我会多留一个步骤,把【】替换成空格而不是直接删除。文档里这个版本偏简化,适合格式干净的需求文档。

分词用的jieba.lcut返回的是 list,可以用它做后续的模板关键词匹配。pseg.cut返回的是带词性的 pair,比如("用户", "n"),这些词性标签在后文构建输入给 API 的提示词时可以直接拼进去。

3.3 关键信息提取

关键信息提取的目标是找出需求文本里的实体,比如用户、系统、页面、数据字段。文档里用了transformers加载 BERT 模型做 NER,对英文需求效果比较好,中文需求建议换成中文预训练模型。

from transformers import AutoTokenizer, AutoModelForTokenClassification import torch tokenizer = AutoTokenizer.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english") model = AutoModelForTokenClassification.from_pretrained("dbmdz/bert-large-cased-finetuned-conll03-english") def extract_entities(text): inputs = tokenizer(text, return_tensors="pt") outputs = model(**inputs) predictions = torch.argmax(outputs.logits, dim=2) tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0]) entities = [] for token, prediction in zip(tokens, predictions[0]): entity_label = model.config.id2label[prediction.item()] if entity_label != 'O': # O 表示非实体 entities.append((token, entity_label)) return entities

这个示例的模型是针对英文 CoNLL-03 数据集微调的,直接拿中文文本喂进去,识别出来的结果没有参考价值。文档在这里没有展开中文模型怎么选,实际项目中我一般会换bert-base-chinese或者用pkuseg做实体抽取,后用规则去匹配。规则匹配的准确率在小样本场景下反而更高。

实体识别的结果也不一定直接用于模板匹配。我更习惯把实体列表变成字符串,塞进后面 API 请求的input_text里。比如定义entities_str = ",".join([f"{token}/{label}" for token, label in entities]),这样大模型能看到需求里到底出现了哪些实体,生成用例时不会跑偏。

3.4 测试用例模板定义与存储

模板是这套方案的骨架,定义时不需要覆盖所有功能,只要能覆盖高频公共操作就行。文档里的登录模板设计得中规中矩,实际落地时我会加上字段类型、边界值预填这几类模板。

login_templates = [ { "test_case_name": "正常登录测试", "test_steps": [ "打开登录页面", "在用户名输入框输入合法的用户名", "在密码输入框输入合法的密码", "点击登录按钮" ], "expected_result": "成功登录系统,跳转到主页" }, { "test_case_name": "异常登录(用户名错误)测试", "test_steps": [ "打开登录页面", "在用户名输入框输入错误的用户名", "在密码输入框输入合法的密码", "点击登录按钮" ], "expected_result": "系统提示用户名错误,登录失败" } ]

模板存储我建议用 JSON 文件而不是 Python 字典硬编码。原因很简单,JSON 能直接被其他系统读取,也方便前端做可视化维护。加载逻辑是这样:

import json def load_templates(template_file): with open(template_file, 'r', encoding='utf-8') as f: templates = json.load(f) return templates

参数方面,test_case_name是用例标题,test_steps是步骤列表,expected_result是预期结果。这三个字段缺一不可,因为后续调用 DeepSeekAPI 时,要把这三个字段都作为参考范例拼进提示词里。如果模板里没有expected_result,大模型生成的用例很可能只有步骤没有断言,这样的用例在自动化框架里根本没法执行。

3.5 调用 DeepSeekAPI 生成用例

调用 DeepSeekAPI 是整个链路里技术含量最低但最容易出问题的一步。文档给出的请求方式是基于 HTTP 的requests.post,下面这段代码基本可以照抄:

import requests api_key = "your_api_key" url = "https://api.deepseek.com/generate" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } payload = { "input_text": "需求:用户可以在登录页面输入用户名和密码进行登录。初步测试用例:正常登录测试...", "max_length": 500, "temperature": 0.7 } response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: result = response.json() generated_test_cases = result["generated_text"] print(generated_test_cases) else: print(f"请求失败,状态码: {response.status_code},错误信息: {response.text}")

max_length决定生成的最大 token 数。测试用例一般都比较长,如果需求复杂,500 token 可能不够。我一般先设成 1000,等生成结果截断了再调。temperature控制输出的随机性,文档里用了 0.7,这个值适合发散式生成。如果你希望结果更保守、更贴近模板,可以降到 0.3;如果希望生成更多边界场景,可以提到 0.9。

有一点要注意,input_text不是一段简单的需求描述。我通常会把需求文本、实体列表、已有模板三部分拼在一起,用分隔符隔开,让模型明确知道“基于这些信息生成用例”。否则大模型可能会忽略已有的模板,完全按自己的理解写。

3.6 用例评估与优化

生成的用例直接进自动化框架风险很高,得先评估。文档里提到的覆盖率、可读性、独立性三个指标,实操时有个简单的办法:把生成结果转成 Markdown 表格,列出用例名称、对应需求编号、步骤数、预期结果,然后逐条人工过一遍。

覆盖率统计我一般用关键词映射:把需求文档里的功能描述拆成若干个关键词,再检查生成的用例文本里是否包含这些关键词。比如需求里有“登录”“用户名”“密码”“错误提示”,用例里如果四个词都出现了,算覆盖一条需求。

优化策略里有三个动作比较常用。

补充用例发生在需求条目没有被任何用例覆盖到的情况下,原因是原始需求文本表述太偏门,模板没匹配到,API 也没理解。此时可以把需求文本单独发一次请求,强行让模型生成一条聚焦用例。

修改用例针对的是可读性差或者断言不清晰的结果。比如模型生成“检查页面是否正确”,这句话没法用,需要改成“检查页面标题是否为『系统主页』”。

合并用例针对的是大量重复的场景。有时候模型会生成四五条“用户名错误”的用例,只是错误写法不同,这种就要合并成一条带测试数据的用例,把多个错误值放在同一行的测试数据里。

第 3 章到这里基本把实现链路讲完了,但真正让这套方案跑顺的不是链路本身,而是对细节的调优。下一章我把完整代码摊开,你会发现每个环节都有一些“血泪经验”。

4. 关键代码拆解:一套能直接跑的智能用例生成脚本

4.1 完整可运行脚本

把前面几节的函数串起来,就是一个能直接跑的版本。这里我稍微调整了文档里的代码,把transformers那部分换成了规则匹配,降低运行成本,也更容易在普通机器上跑。

import os import re import json import requests import jieba import jieba.posseg as pseg DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") API_URL = "https://api.deepseek.com/generate" def read_requirement_file(file_path): try: with open(file_path, "r", encoding="utf-8") as f: return f.read() except FileNotFoundError: print(f"文件 {file_path} 未找到。") return None def remove_noise(text): text = re.sub(r"[^\w\s]", "", text) text = re.sub(r"\s+", " ", text).strip() return text def preprocess_text(text): text = remove_noise(text) words = jieba.lcut(text) pos_tagged = [(word, flag) for word, flag in pseg.cut(text)] return pos_tagged def extract_keywords(pos_tagged): keywords = [] for word, flag in pos_tagged: if flag.startswith("n") or flag.startswith("v"): keywords.append(word) return list(set(keywords)) def load_templates(template_file): with open(template_file, "r", encoding="utf-8") as f: return json.load(f) def match_templates(keywords, templates): matched = [] for template in templates: step_text = " ".join(template["test_steps"]) for kw in keywords: if kw in step_text or kw in template["test_case_name"]: matched.append(template) break return matched def call_deepseek_api(input_text, max_length=1000, temperature=0.7): headers = { "Authorization": f"Bearer {DEEPSEEK_API_KEY}", "Content-Type": "application/json" } payload = { "input_text": input_text, "max_length": max_length, "temperature": temperature } response = requests.post(API_URL, headers=headers, json=payload) if response.status_code == 200: return response.json().get("generated_text", "") else: print(f"API 请求失败: {response.status_code}") return "" def generate_test_cases(requirement_text, templates): pos_tagged = preprocess_text(requirement_text) keywords = extract_keywords(pos_tagged) matched = match_templates(keywords, templates) base_text = json.dumps(matched, ensure_ascii=False) if matched else "无匹配模板" input_text = f"需求文本:{requirement_text}\n关键信息:{keywords}\n基础模板:{base_text}\n请生成更多测试用例。" return call_deepseek_api(input_text) if __name__ == "__main__": requirement = read_requirement_file("requirement.txt") if requirement: templates = load_templates("templates.json") result = generate_test_cases(requirement, templates) print(result)

这段脚本把核心流程收敛成了几个高内聚函数。remove_noise负责清噪声,preprocess_text做分词和词性标注,extract_keywords提取名词和动词作为模板匹配的关键词,match_templates负责从模板库里筛出可能相关的模板,call_deepseek_api负责调用 DeepSeekAPI,generate_test_cases作为业务入口把它们串起来。

4.2 代码逻辑逐段拆解

先看extract_keywords。这里用词性筛选,只保留名词和动词开头的词。原因是中文需求文本里,功能描述主要集中在名词和动词上,比如“用户”“登录”“输入”“密码”。形容词和副词对模板匹配帮助不大,还会增加噪声。

match_templates的实现比较粗糙,用的是子串匹配。比如需求关键词里有“登录”,模板的步骤文本里也有“登录”,就认为这个模板被命中。这个逻辑在简单场景下够用,但要注意一个翻车点:如果模板步骤是“打开订单列表”,需求关键词是“订单列表”,能匹配成功;但如果是“查看订单”,就很难匹配到。所以实际项目里,我一般在模板里额外加一个keywords字段,给每个模板显式声明可以匹配的关键词,比如“order|订单|下单”。匹配时优先看这个字段,再看步骤文本。

call_deepseek_api里的temperature=0.7是个经验值。文档里这个参数用了 0.7,我使用下来发现,生成测试用例时 0.5 到 0.7 之间效果最好。太低了用例基本就是模板的复读机,太高了模型会天马行空生成一些根本不可能执行的操作。

generate_test_cases函数拼input_text的方式很关键。我没有直接把需求文本丢给 API,而是把需求文本、关键信息列表、基础模板 JSON 三段拼在一起。这样模型能同时看到原始需求、提炼的关键词和已有的模板结构,生成的用例不会脱离骨架。

4.3 参数说明与调优建议

下面这几个参数是调优时最常碰到的,列成表方便对照。

参数默认值影响范围建议
max_length500生成内容长度需求复杂度高时调到 1000,防止截断
temperature0.7输出随机性保守场景 0.3,发散场景 0.9
API_URL固定值无保持默认,不要随意改
headers无请求鉴权密钥不要硬编码,读环境变量

max_length的默认值文档里是 200,但测试用例文本通常较长,200 token 根本不够用。我一般第一版就设 1000,生成完再人工精简。

temperature是这里最需要调参的选项。之前某次生成用例时,我把温度设成 0.9,结果模型生成了“管理员登录时验证验证码是否发送到手机”这种需求里不存在的功能。降到 0.5 之后,生成结果明显老实了。

除了这两个参数,requests.post的超时时间也值得设置。不设置超时会让脚本卡死在等待响应上,尤其是 API 服务不稳定的时候。我一般会在requests.post里加timeout=30。

response = requests.post(API_URL, headers=headers, json=payload, timeout=30)

超时时间设 30 秒,超过就抛异常,再由上方调用方捕获并重试。一般公共服务不会响应太久,30 秒足够。

5. 避坑指南:DeepSeekAPI 生成测试用例最常见的五个坑

5.1 现象:生成的测试用例格式不稳定,无法直接解析

第一次跑通的时候,API 返回的generated_text里夹杂着 Markdown 表格、序号列表、破折号说明,甚至还有一句话分成两种格式的情况。我试着用正则解析用例名称和步骤,结果 50 条用例里有十来条解析失败。

原因是大模型输出格式受temperature和提示词影响很大。temperature设得高,模型就越喜欢换表达方式,今天给你 Markdown,明天给你纯文本,后天给你 JSON 带注释。

解决方法是双保险:一是在提示词里强制指定输出格式,比如“请以 JSON 数组返回,每个元素包含 test_case_name、test_steps、expected_result”;二是在解析时做容错处理,先尝试json.loads,失败后再用正则提取。我在脚本里加了一个简单兜底函数:

import re import json def parse_generated_cases(raw_text): try: cases = json.loads(raw_text) if isinstance(cases, list): return cases except json.JSONDecodeError: pass # 兜底:提取 Mo 格式中的用例块 blocks = re.findall(r"用例名称[::]\s*(.*?)\n", raw_text) return blocks

这个兜底不完美,但至少不会因为一条格式错误让整个流程崩溃。

5.2 现象:温度参数过高导致用例偏离需求

某次给一个订单查询功能生成用例,把temperature设成了 0.9,结果模型生成了“用户删除订单”的用例。需求里根本没有删除订单这个功能,这种用例一旦进入自动化框架,会直接失败,浪费排查时间。

原因是高温让模型过度发散,它会从“订单查询”联想到“订单管理”,再从“管理”联想到“删除”。大模型不知道你的系统边界在哪里,它只知道相关性。

解决方法是把temperature压到 0.4 到 0.6 之间,同时把需求里的约束条件重复一遍。我在input_text末尾加了一句话:“注意:只能基于需求文本中的功能生成用例,不要扩展需求中不存在的功能。”这条指令很管用,后续生成的用例基本不会再越界。

5.3 现象:中文需求文本预处理后丢失关键信息

有一次需求文本里写“用户输入年龄(18-60岁)”,预处理时用re.sub(r'[^\w\s]', '', text)把所有特殊符号删掉了,结果变成了“用户输入年龄1860岁”。

原因很简单,正则把所有括号、横杠都当成噪声删了,数字和单位也被误伤。

解决方法是调整噪声清洗规则,把括号替换成空格而不是删除,保留数字、单位等关键信息。我现在的预处理逻辑改成了这样:

text = re.sub(r"[\uff08\uff09\(\)【】]", " ", text) # 括号变空格 text = re.sub(r"[^\w\s\u4e00-\u9fa5::%]", " ", text) # 保留中文、数字、冒号、百分比 text = re.sub(r"\s+", " ", text).strip()

这样“18-60岁”虽然会变成“18 60 岁”,但至少不丢数字。更好的方案是直接把“-”两边的数字提取出来,作为边界值参数存到用例数据里,但那是后话。

5.4 现象:模板匹配命中过多,导致基础用例重复

模板库里如果存了十几条登录模板,多条模板的步骤文本都包含“登录”,match_templates会把所有包含“登录”的模板全返回,基础用例里出现大量重复内容。

原因是我把匹配逻辑写得太宽松,只要关键词出现在步骤里就命中。

解决方法是给每个模板增加一个keywords字段,匹配时优先查这个字段,而不是全文扫步骤。另一个思路是控制每条需求最多匹配 3 个模板,超出部分丢弃。

def match_templates(keywords, templates, max_matches=3): matched = [] for template in templates: template_keywords = template.get("keywords", []) if any(kw in template_keywords for kw in keywords): matched.append(template) if len(matched) >= max_matches: break return matched

5.5 现象:API 请求频繁返回 429 或超时

连续生成大批量用例的时候,脚本会频繁报429 Too Many Requests,或者直接超时。

原因是对 API 的调用频率没有做限制,短时间打了几百个请求,被服务端限流了。

解决方法是加限速和重试机制。常见做法是用time.sleep(0.5)控制请求间隔,配合指数退避重试。我用一个简单的装饰器实现重试:

import time def retry_on_429(func, retries=3): def wrapper(*args, **kwargs): for i in range(retries): response = func(*args, **kwargs) if response.status_code == 429: wait = 2 ** i time.sleep(wait) continue return response return response return wrapper

这个做法不是最优,但能解决大部分限流问题。如果生成的用例量很大,建议用异步队列控制并发,每次只发 5 个请求,串行处理。

6. 验证与进阶:覆盖率怎么算,用例怎么入库复用

6.1 覆盖率计算:从关键词映射到需求跟踪矩阵

覆盖率是这套方案里最容易被质疑的点。很多人会问:你说智能生成,覆盖率怎么证明?我平时用需求跟踪矩阵来量化。方法很简单:把需求拆成若干功能点,每生成一条用例,就标记它覆盖了哪些功能点。

比如需求文本是“用户可以在登录页面输入用户名和密码进行登录”,我先把“登录页面”“用户名”“密码”“登录成功”拆成四个功能点。生成的用例里如果同时包含这四个关键词,算覆盖完整;只包含“登录页面”和“用户名”,算部分覆盖。统计公式是:

覆盖率 = 至少被一条用例覆盖的功能点数量 / 总功能点数量

这个比率可以写进回归测试报告里,作为智能用例生成效果的参考。当然,这套方法比较粗糙,胜在执行简单。真正的需求覆盖测试还是需要人工确认功能点拆得是否准确。

6.2 把生成结果做成可维护的用例库

生成的用例不能只存在于终端输出里。我建议把每条用例转成统一的 JSON 结构,写回模板库或单独的用例文件。这样做的好处是后续可以直接接着用,不需要重新生成。

def save_cases(cases, output_file): with open(output_file, "w", encoding="utf-8") as f: json.dump(cases, f, ensure_ascii=False, indent=2)

保存之前,我会清理字段:只保留test_case_name、test_steps、expected_result,删除模型生成的额外解释文字。然后在test_case_name前面加需求编号前缀,比如REQ-001_正常登录测试,方便追踪需求来源。

6.3 一个值得坚持的验证习惯

刚开始用这套方案时,我犯过一个错:生成了几十条用例就直接往测试平台里导入,结果一半用例因为预期结果写得不够具体,执行时全部失败。从那以后我每次生成完都强制走一遍“三看”验证流程:一看功能点是否漏掉,二看预期结果是否可断言,三看有没有脱离需求的额外扩展。前两步靠人工,第三步靠把temperature压低。希望这个流程能帮你在智能用例生成这条路上少踩几个坑,把这套方案真正变成能落地的测试效率工具。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询