面向测试用例生成的大模型微调实践:从数据构造、LoRA 适配到评测与私有化部署
本文整理一次面向软件测试工程场景的大模型微调实践。目标不是从零训练基础模型,而是在已有开源大模型基础上,通过指令数据构造、LoRA/QLoRA 轻量化适配、结构化输出评测和私有化部署,将模型能力稳定接入智能测试平台。
1. 背景:为什么在测试工程场景中做大模型微调
在汽车电子底软测试场景中,测试人员经常需要从 AUTOSAR 标准、项目需求、接口文档、历史测试用例和公共测试库中提取信息,并进一步完成测试点设计、测试用例编写、测试脚本开发和报告分析。
传统方式通常存在几个问题:
-
需求解析依赖人工经验
同一条需求可能涉及前置条件、输入类别、核心动作、预期结果、异常场景和覆盖关系。人工拆解容易出现遗漏或粒度不一致。 -
测试用例结构化程度不足
测试用例经常散落在 Excel、Markdown、脚本注释或测试报告中,字段命名、步骤描述、预期结果表达不统一,难以直接进入自动化执行链路。 -
脚本开发重复劳动较多
底软测试脚本通常需要查找公共库 API、参考历史脚本风格、适配测试环境,再补充断言与日志。大量时间消耗在重复查库和仿写上。 -
生成式模型直接调用不够稳定
仅依赖 Prompt 或通用模型,容易出现 JSON 不合法、字段缺失、测试点覆盖不足、测试步骤不可执行、编造不存在 API 等问题。
因此,在智能测试平台中,大模型能力不能只停留在“问答”或“生成文本”层面,而应形成一套可评测、可修正、可部署的工程闭环:
需求文档 / 历史用例 / 公共库 API
↓
数据清洗与指令数据构造
↓
Base 模型推理基线
↓
Prompt / RAG / LoRA 微调方案对比
↓
结构化输出评测
↓
服务化部署与平台集成
↓
用例生成 / 脚本生成 / 执行辅助
2. 项目定位:不是训练基础模型,而是做垂直场景适配
这类项目的关键边界是:不做大规模预训练,而是围绕测试工程任务做监督微调和工程化落地。
基础模型已经具备通用语言理解能力,微调要解决的是垂直领域中的稳定性和格式一致性问题,例如:
- 能否稳定识别需求类型;
- 能否把自然语言需求拆成测试点;
- 能否输出符合 Schema 的 JSON;
- 能否保留必要字段;
- 能否避免生成不可执行的测试步骤;
- 能否结合公共库 API 生成更接近项目风格的 pytest 脚本;
- 能否降低后处理、人工修正和二次返工成本。
在本实践中,模型侧主要围绕 Qwen2.5-1.5B-Instruct 进行私有化部署和 LoRA 原型验证;平台侧结合已有智能测试平台、test_agent 工作流和 Test_Framework 自动化执行底座,形成从测试资产生成到执行闭环的链路。
3. 总体技术架构
整体架构可以分为五层:
数据层
需求文档、公开需求语料、历史测试用例、公共库 API、历史测试脚本
↓
标注与构造层
清洗、去重、脱敏、teacher 标注、JSONL / messages 数据构造
↓
模型适配层
Base 推理、Prompt 优化、RAG 增强、LoRA / QLoRA 微调
↓
评测层
JSON 合法率、Schema 通过率、字段完整率、覆盖率、响应耗时
↓
平台集成层
test_agent 生成测试用例 / 脚本,Test_Framework 执行并产出日志、pcap、HTML 报告
其中,test_agent 和 Test_Framework 的职责边界可以概括为:
| 模块 | 主要职责 | 输出 |
|---|---|---|
test_agent | 需求解析、测试点设计、测试用例生成、测试脚本生成、规则校验 | JSON、Excel、pytest 脚本、生成校验报告 |
Test_Framework | UI 编排、配置驱动、pytest 执行、公共库调用、日志抓包、报告产出 | 执行结果、日志、pcap、HTML 报告 |
| 微调模型 | 提升垂直任务中的结构化输出、字段完整性和测试场景理解能力 | 更稳定的需求解析和用例生成结果 |
一个更准确的关系是:
微调模型提供垂直能力,
test_agent负责把模型能力编排成测试工程工作流,Test_Framework负责执行生成后的自动化测试资产。
4. 模型选型与部署:先建立可调用的本地基线
微调前需要先建立一个可重复评测的 Base 模型基线。这里采用 Qwen2.5-1.5B-Instruct 作为轻量模型进行验证,主要考虑:
- 参数量较小,适合单卡或云 GPU 快速验证;
- Instruct 模型具备基础指令跟随能力;
- 可通过 Hugging Face / Transformers / vLLM 快速部署;
- 便于后续 LoRA 或 QLoRA 适配。
4.1 使用 vLLM 启动 OpenAI-compatible 服务
示例命令:
python -m vllm.entrypoints.openai.api_server \
--model /data/models/Qwen2.5-1.5B-Instruct \
--served-model-name qwen2.5-1.5b-instruct \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096
启动后,可以用 OpenAI-compatible API 调用:
from openai import OpenAI
client = OpenAI(
api_key="EMPTY",
base_url="http://127.0.0.1:8000/v1",
)
resp = client.chat.completions.create(
model="qwen2.5-1.5b-instruct",
messages=[
{"role": "system", "content": "你是一个软件测试需求解析助手,只输出合法 JSON。"},
{"role": "user", "content": "系统应在通信超时时记录错误码并进入降级状态。"}
],
temperature=0.0,
)
print(resp.choices[0].message.content)
4.2 为什么先做部署而不是直接微调
直接进入微调容易忽略两个问题:
-
没有 baseline 就无法判断微调是否有效
必须先知道 Base 模型在目标任务上的 JSON 合法率、字段完整率、覆盖率和响应耗时。 -
很多问题不一定需要微调解决
Prompt、RAG、Schema 约束、后处理和规则校验可以解决一部分格式问题。微调更适合解决输出风格、领域术语、任务模式和稳定性问题。
因此推荐顺序是:
Base 模型部署
↓
构建评测集
↓
Base 指标评测
↓
Prompt / RAG 优化
↓
判断是否需要 LoRA 微调
↓
微调后与 Base / Prompt 版本对比
5. 数据集构造:从需求文本到指令微调样本
微调效果很大程度取决于数据质量。对于测试用例生成场景,数据构造的目标不是简单收集问答,而是构建“输入需求 → 结构化测试资产”的映射。
5.1 数据来源
可用数据主要包括:
| 数据来源 | 用途 |
|---|---|
| 公开软件需求数据集,如 PURE / PurePlainDataset | 构建通用需求解析样本 |
| AUTOSAR SWS / 项目需求文档 | 构建底软领域需求理解样本 |
| 历史测试用例 Excel / JSON | 提供标准字段、步骤粒度和预期结果风格 |
| 历史 pytest 测试脚本 | 提供脚本结构、fixture 使用、断言方式和日志风格 |
Test_Framework 公共库 API | 约束脚本生成只能调用真实存在的接口 |
| 评审规则 / 测试规范 | 构建规则校验与反例数据 |
5.2 数据清洗原则
清洗时重点关注以下问题:
-
去除无效文本
删除页眉页脚、目录、版权声明、无业务含义的表格残片。 -
按需求粒度切分
对规范性需求,尽量做到“一条需求一个样本”,避免一个样本里混入多个独立需求。 -
保留上下文但控制长度
可保留上级章节、术语定义和相关需求,但不应把整章内容无差别塞入 input。 -
脱敏处理
去除项目名称、客户名称、内部地址、Token、账号、日志路径等敏感信息。 -
训练集、验证集、测试集隔离
测试集不能参与训练,也不应参与 Prompt 调参,否则评测结果会失真。
5.3 指令数据格式
对于 SFT,建议使用 messages 格式:
{
"messages": [
{
"role": "system",
"content": "你是软件测试需求解析助手。请根据需求生成结构化测试点,只输出合法 JSON。"
},
{
"role": "user",
"content": "需求:系统应在 CAN 通信超时时记录错误码,并在 100ms 内进入降级状态。"
},
{
"role": "assistant",
"content": "{\"requirement_type\":\"functional\",\"test_points\":[{\"id\":\"TP-001\",\"condition\":\"CAN通信超时\",\"action\":\"触发通信超时场景\",\"expected\":\"记录错误码并在100ms内进入降级状态\"}]}"
}
]
}
如果任务是测试脚本生成,样本可以进一步加入公共库 API 摘要和相似示例:
{
"messages": [
{
"role": "system",
"content": "你是 pytest 自动化测试脚本生成助手。必须优先使用给定 API,不得编造不存在的接口。"
},
{
"role": "user",
"content": "测试用例:...\n可用API:tester.SDO_Upload_ExpeditedOrSegmented, tester.SDO_Download...\n相似脚本:..."
},
{
"role": "assistant",
"content": "import pytest\n\nclass Test_CANopen:\n def test_xxx(self, start):\n ..."
}
]
}
6. Teacher 标注:用高能力模型生成初始 gold 数据
在早期缺少足够人工标注数据时,可以用高能力模型做 teacher 标注,再通过规则和人工抽检提高质量。
推荐流程:
原始需求文本
↓
规则清洗与切分
↓
teacher 模型生成结构化输出
↓
JSON 合法性检查
↓
Schema 校验
↓
规则检查与人工抽检
↓
train / valid / test 数据集
teacher 标注不是直接拿来训练,而是要经过质量门禁。常见门禁包括:
| 检查项 | 说明 |
|---|---|
| JSON 合法性 | 是否能被 json.loads() 解析 |
| Schema 通过率 | 是否满足字段、类型、枚举值要求 |
| 字段完整性 | 是否包含需求编号、测试点、前置条件、动作、预期结果 |
| 需求一致性 | 是否遗漏或篡改原始需求含义 |
| 覆盖关系 | 测试点是否覆盖核心条件、动作和结果 |
| 可执行性 | 是否生成可以落入测试环境的步骤 |
对于关键样本,建议保留 teacher 输出、规则检查结果和人工修正记录,后续可以用于错误分析和数据迭代。
7. Prompt、RAG 与微调的边界
在智能测试平台里,Prompt、RAG 和微调解决的问题不同。
| 方案 | 适合解决 | 不适合解决 |
|---|---|---|
| Prompt | 输出格式约束、任务说明、少量示例引导 | 长期稳定性、领域风格沉淀 |
| RAG | 补充项目知识、API 文档、配置参数、历史用例 | 改变模型内在输出习惯 |
| LoRA / QLoRA | 固化领域任务模式、提升结构化输出稳定性、降低反复提示成本 | 替代知识库、记忆频繁变化的项目配置 |
| 规则校验 | 发现格式错误、字段缺失、覆盖不足 | 直接生成高质量内容 |
在测试用例生成场景中,一个实用组合是:
RAG 提供上下文
+
Prompt 约束任务和格式
+
LoRA 固化领域输出模式
+
规则校验兜底
例如,AUTOSAR 规范、公共库 API、项目配置和历史脚本经常变化,更适合放入 RAG 或上下文检索;而“如何把需求拆成测试点”“如何输出统一 JSON”“如何描述前置条件和预期结果”这类稳定模式,更适合通过 SFT/LoRA 固化。
8. LoRA / QLoRA 微调方案
8.1 LoRA 的基本思路
LoRA 的核心思想是冻结基础模型大部分参数,只在注意力层或部分线性层中加入低秩矩阵进行训练。这样可以显著降低显存和训练成本,同时让模型适配特定任务。
简化理解:
原始权重 W 不更新
+
可训练低秩增量 ΔW = A × B
↓
推理时使用 W + ΔW
在垂直测试任务中,LoRA 适合用于:
- 提高结构化 JSON 输出稳定性;
- 固化需求解析字段;
- 学习测试用例描述风格;
- 降低每次 Prompt 中重复说明规则的成本;
- 让小模型在特定任务上接近更大模型的输出风格。
8.2 QLoRA 适用场景
QLoRA 是在量化基础上进行 LoRA 训练,通常用于显存更紧张的场景。它适合:
- 单卡显存有限;
- 模型参数量较大;
- 需要降低训练成本;
- 对训练吞吐和精度有折中要求。
如果使用 1.5B 级别模型做原型验证,普通 LoRA 已经比较轻量;如果后续扩大到 7B 或更大模型,可以考虑 QLoRA。
8.3 训练参数建议
一个初始配置可以参考:
model_name_or_path: /data/models/Qwen2.5-1.5B-Instruct
stage: sft
finetuning_type: lora
template: qwen
cutoff_len: 4096
lora_rank: 8
lora_alpha: 16
lora_dropout: 0.05
target_modules: all
learning_rate: 2.0e-4
num_train_epochs: 3
per_device_train_batch_size: 1
gradient_accumulation_steps: 8
lr_scheduler_type: cosine
warmup_ratio: 0.03
logging_steps: 10
save_steps: 200
eval_steps: 200
参数不是固定答案,实际要结合数据量、输出长度、显存、验证集表现和过拟合情况调整。
8.4 防止过拟合
微调数据通常规模不大,容易过拟合。建议:
- 保留独立测试集;
- 监控 train loss 与 eval loss;
- 控制 epoch 数;
- 对同一需求避免重复增强过多;
- 保持输入表达多样性;
- 保留 hard case,而不是只保留模型容易答对的样本;
- 对输出进行 Schema 和业务规则双重评估。
9. 评测体系:不要只看“生成得像不像”
微调是否有效,必须通过统一评测集量化对比。建议至少比较三组:
Base 模型
Prompt 优化版本
LoRA 微调版本
9.1 结构化输出指标
| 指标 | 含义 |
|---|---|
| JSON 合法率 | 输出能否被标准 JSON 解析 |
| Schema 通过率 | 字段、类型、枚举值是否符合定义 |
| 字段完整率 | 必填字段是否完整 |
| 需求类型准确率 | 是否正确识别功能、性能、接口、异常、安全等类型 |
| 测试点覆盖率 | 是否覆盖需求中的核心条件、动作和预期结果 |
| 冗余率 | 是否生成重复或无关测试点 |
| 平均响应耗时 | 单条需求生成耗时 |
| 人工修正率 | 最终进入平台前需要人工修改的比例 |
9.2 一个简单的评测脚本思路
import json
from jsonschema import validate, ValidationError
def is_valid_json(text: str):
try:
return True, json.loads(text)
except Exception:
return False, None
def check_schema(obj, schema):
try:
validate(instance=obj, schema=schema)
return True
except ValidationError:
return False
def evaluate_one(pred_text, gold, schema):
json_ok, pred_obj = is_valid_json(pred_text)
if not json_ok:
return {
"json_ok": False,
"schema_ok": False,
"field_complete": 0.0,
"coverage_score": 0.0,
}
schema_ok = check_schema(pred_obj, schema)
required_fields = ["requirement_id", "requirement_type", "test_points"]
field_complete = sum(1 for f in required_fields if f in pred_obj) / len(required_fields)
# 覆盖率可结合关键词、测试点映射、人工规则或 LLM-as-Judge
coverage_score = compute_coverage(pred_obj, gold)
return {
"json_ok": True,
"schema_ok": schema_ok,
"field_complete": field_complete,
"coverage_score": coverage_score,
}
9.3 评测结果如何解读
如果 LoRA 后:
- JSON 合法率明显提升;
- Schema 通过率明显提升;
- 字段完整率提升;
- 测试点覆盖率提升;
- 平均耗时保持可接受;
- 人工修正率下降;
则说明微调对该业务任务有实际价值。
如果只是输出更流畅,但结构化指标没有提升,说明微调没有解决核心问题,可能需要回到数据质量、Prompt 约束、Schema 设计或规则校验链路重新调整。
10. 与智能测试平台的集成方式
10.1 与 test_agent 的关系
test_agent 可以作为 AI 测试工程能力层,负责:
需求解析
↓
测试点设计
↓
测试用例生成
↓
覆盖映射
↓
规则校验
↓
测试脚本生成
微调模型可以接入到其中的 LLM Adapter 中,用于替换或补充外部模型调用。这样,业务工作流不用直接关心模型部署细节,只需要调用统一模型接口。
典型调用关系:
entrypoints
↓
Task(domain_type, task_type, input_payload, workflow_name)
↓
WorkflowRegistry
↓
PlatformOrchestrator
↓
具体 Workflow
↓
LLM Adapter / RAG / 规则校验 / 文件导出
10.2 与 Test_Framework 的关系
Test_Framework 是自动化执行底座,负责:
UI 用例筛选
↓
配置驱动
↓
pytest 执行
↓
公共库调用
↓
日志 / pcap / HTML 报告
AI 微调模型不直接替代自动化执行框架,而是为其生成更稳定的测试资产:
| 阶段 | AI 能力 | Test_Framework 能力 |
|---|---|---|
| 需求理解 | 解析需求、生成测试点 | 不负责 |
| 用例设计 | 生成 JSON / Excel 测试用例 | 读取或组织可执行用例 |
| 脚本开发 | 生成 pytest 脚本骨架与逻辑 | 执行 pytest 脚本 |
| 运行验证 | 可辅助分析失败原因 | 采集日志、pcap、报告 |
| 资产沉淀 | 生成样本、回流 bad case | 沉淀公共库与执行结果 |
因此,完整闭环是:
大模型生成测试资产
↓
test_agent 编排与校验
↓
Test_Framework 自动执行
↓
证据产出与失败分析
↓
bad case 回流数据集
11. 工程经验:从测试平台到模型适配的迁移
在已有测试平台建设中,已经沉淀了几类对微调非常有价值的资产:
-
大量测试用例与脚本资产
自动化测试框架已支撑多类底软测试项目,累计沉淀大量测试脚本、测试用例和执行结果。这些资产可以转化为模型训练样本、相似示例库和评测集。 -
公共测试库 API
SOME/IP、CANopen、DoIP/UDS、SSH、Excel/JSON、日志、抓包等公共能力可以作为脚本生成的 API 约束,避免模型编造不存在的接口。 -
结构化输出经验
智能测试平台中的 JSON 合法性校验、Schema 校验、字段完整性检查、失败重试和规则修复机制,可以直接复用到微调评测和推理服务中。 -
自动化执行证据链
pytest 执行结果、日志、pcap、远端日志和 HTML 报告可以反向用于分析生成脚本是否真正可执行。 -
Agent 工作流经验
通过测试点设计、覆盖映射、规则校验、逐条用例复核等节点,可以避免“一次生成到底”的不可控问题,让模型输出进入可追踪、可修复的工程流程。
这种迁移的关键不是“把模型训练得更会聊天”,而是让模型在真实测试工程链路中承担明确职责,并接受规则和执行结果的约束。
12. 常见问题与处理策略
12.1 模型输出不是合法 JSON
处理方式:
- system prompt 明确“只输出 JSON”;
- 使用
response_format或 JSON schema 约束; - 本地做 JSON 清洗;
- 失败时自动重试;
- 将错误样本加入微调或评测集;
- 降低 temperature。
12.2 Schema 通过但业务含义错误
Schema 只能保证格式,不能保证覆盖质量。需要加入:
- 需求关键词覆盖检查;
- 测试点与需求编号映射;
- 核心动作与预期结果一致性检查;
- case_set_validator;
- 人工抽检高风险样本;
- LLM-as-Judge 作为辅助评审。
12.3 模型编造不存在的 API
处理方式:
- Prompt 中只提供检索到的 API;
- 规则中明确“不得编造 API”;
- 生成后静态扫描 API 调用;
- 结合
pytest collect做基础可执行性检查; - 对无法实现的步骤生成 TODO,而不是硬编代码。
12.4 微调后效果没有提升
优先检查:
- 数据是否太少或质量不稳定;
- train / valid / test 是否泄漏;
- 输出格式是否过于复杂;
- 训练 epoch 是否过多导致过拟合;
- 评测指标是否与训练目标一致;
- Prompt、RAG、规则校验是否已经解决了大部分问题。
12.5 小模型能否替代大模型
小模型更适合承担稳定、边界清晰、格式固定的任务,例如:
- 需求分类;
- 测试点初稿生成;
- JSON 字段补全;
- 脚本骨架生成;
- 报告摘要。
复杂推理、跨文档推断和高风险设计仍建议结合更强模型、RAG 和人工审核。
13. 后续拓展方向
13.1 从 LoRA 原型到多模型评测
可以扩展为统一评测平台,对比:
- Qwen 不同参数量模型;
- Base / Prompt / RAG / LoRA / QLoRA;
- 不同上下文长度;
- 不同推理框架;
- 不同量化方案;
- 延迟、吞吐、显存和输出质量。
13.2 从测试用例生成扩展到脚本生成
当前可以先从需求到测试用例的结构化任务开始,后续逐步扩展到:
测试用例 JSON
↓
检索公共库 API
↓
检索相似历史脚本
↓
生成 pytest 脚本骨架
↓
LLM 补全逻辑
↓
语法检查
↓
pytest collect
↓
Test_Framework 执行
13.3 从生成结果评测扩展到执行结果评测
执行后的日志、pcap 和 HTML 报告可以继续回流到 AI 系统,用于:
- 自动分析失败原因;
- 判断失败是环境问题、脚本问题还是被测件问题;
- 生成测试报告摘要;
- 形成 bad case 数据集;
- 反向优化 Prompt、规则和微调数据。
13.4 从单领域适配扩展到多领域 Profile
测试领域差异不应全部硬编码到工作流中。更好的方式是:
公共工作流引擎
+
领域 Profile
+
领域 Prompt
+
领域 Schema
+
领域规则检查器
+
领域导出模板
这样 AUTOSAR、RCP、Web、诊断、通信协议等场景可以复用同一套 Agent 与评测基础设施。
13.5 从单次生成扩展到持续学习闭环
最终目标不是一次性微调,而是形成持续迭代机制:
线上生成
↓
规则校验
↓
人工修正
↓
执行结果
↓
bad case 归档
↓
数据清洗
↓
增量评测
↓
下一轮微调或 Prompt 更新
14. 小结
面向测试用例生成的大模型微调,本质上是一个工程系统问题,而不是单纯的训练脚本问题。
实践中需要同时关注:
- 数据是否干净;
- 输出结构是否稳定;
- 评测指标是否客观;
- 模型是否真的降低人工修正成本;
- 生成内容能否进入自动化执行链路;
- 失败样本能否回流形成持续优化。
对于汽车电子底软测试这类强流程、强规范、强证据链的场景,比较合理的技术路线是:
Prompt 约束任务
+
RAG 提供项目知识
+
LoRA 固化领域输出模式
+
Agent 编排生成与校验流程
+
Test_Framework 承接自动化执行
+
评测与 bad case 回流持续优化
这样的系统既能保留大模型的生成能力,又能通过规则、数据、工作流和执行证据把生成结果纳入工程化管理。
更多推荐


所有评论(0)