一、引言:从“写提示词”到“建工程体系”
在汽车研发测试领域,座舱软件的功能迭代速度越来越快,功能测试、自动化测试、需求分析、缺陷管理等环节对效率的要求持续攀升。大语言模型的出现为测试脚本生成带来了新的可能性——测试人员只需用自然语言描述测试场景,模型就能自动生成可执行的自动化测试代码。

然而,现实远没有想象中美好。许多团队在落地过程中遇到了同样的困境:同样的需求描述,第一次生成的脚本能用,第二次就完全跑不通;同样的Prompt,换了个模型版本输出风格大变;生成的代码看似合理,但一执行就报错。

问题的根源在于,我们将Prompt当作文案来写,而不是当作工程化模块来管理。提示词不应被视为临时编写的文案,而应作为可复现、可测试的工程化模块。结构良好的提示能显著降低模型输出的不确定性,提高响应的一致性与可用性。

本文将从汽车研发测试的实际场景出发,系统阐述Prompt工程体系化建设的完整路径——从结构化提示设计、RAG知识库构建、智能Agent工作流,到效果评估与持续迭代——并结合可运行的代码示例,帮助读者构建一套让大模型稳定输出高可用测试脚本的工程化体系。

二、为什么测试脚本生成需要Prompt工程体系化?
2.1 传统方式的三大痛点
痛点一:输出不可控。 微小的Prompt变动可能导致模型响应完全反转,即便将temperature设为0,重复查询仍可能产生不一致的输出。

痛点二:缺乏领域知识。 通用大模型不了解汽车座舱的特定测试框架(如CANoe、车载操作系统API)、业务规则和代码规范,生成的脚本往往“形似而神不似”。

痛点三:无法规模化。 当测试团队有几十甚至上百个测试场景需要生成时,逐个调优Prompt的方式完全不现实。

2.2 体系化建设的核心目标
体系化Prompt工程的核心,是从“试错走向标准化,让输出可预期、可复现、可评测”。具体来说,需要实现:

可复现:相同输入在任何时候产生相同输出

可评测:能自动判断生成质量并量化打分

可迭代:基于反馈持续优化,而非一次性调参

可集成:与现有测试平台、CI/CD流水线无缝对接

三、Prompt工程体系化的四层架构
我们将体系化Prompt工程分为四个层次,从基础到高级逐步构建:

3.1 第一层:结构化提示设计(基础层)
结构化提示是将自然语言指令转化为机器可解析的工程化模板。核心原则是明确区分系统指令与用户输入,避免将上下文与指令混杂。

以下是一个针对汽车座舱测试脚本生成的结构化Prompt模板:

python
from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate

TEST_SCRIPT_GENERATION_TEMPLATE = “”"
你是一位资深的汽车座舱软件测试工程师,精通 {test_framework} 自动化测试框架。

任务

根据以下测试需求,生成可直接执行的 {test_framework} 测试脚本。

输出格式要求

  • 必须包含完整的 import 语句
  • 必须包含 setUp/tearDown 方法(如适用)
  • 每个测试方法必须包含明确的断言
  • 输出必须是纯代码,不要包含任何解释性文字

代码规范

{code_standards}

测试框架约束

{framework_constraints}

测试需求

{test_requirement}

历史相似用例参考(供风格参考)

{similar_cases}
“”"

def build_test_script_prompt(
test_framework: str,
test_requirement: str,
code_standards: str,
framework_constraints: str,
similar_cases: str = “”
) -> ChatPromptTemplate:
system_template = SystemMessagePromptTemplate.from_template(
“你是一位资深的汽车座舱软件测试工程师。”
)
human_template = HumanMessagePromptTemplate.from_template(
TEST_SCRIPT_GENERATION_TEMPLATE
)
return ChatPromptTemplate.from_messages([system_template, human_template])
结构化提示的关键在于将任务拆解为明确的字段:任务说明、输出格式、约束条件、示例参考。这种方式让模型清晰知道“要做什么”和“不能做什么”,大幅降低输出偏差。

3.2 第二层:RAG知识库增强(上下文层)
结构化提示解决了“怎么说”的问题,但无法解决“知道什么”的问题。通用大模型不了解你们公司的特定测试框架API、业务规则和代码规范。

RAG(检索增强生成) 的价值正在于此——将历史测试用例、API文档、测试规范切成小块存入向量数据库,每次生成前检索相关规范喂给大模型。

在汽车测试场景中,RAG知识库应包含以下几类内容:

API手册:车载操作系统(Android/QNX/Linux)的测试接口文档

历史用例库:过往已验证的测试脚本,作为Few-shot示例

代码规范:团队约定的命名规范、断言风格、注释要求

业务规则:座舱功能的特定逻辑(如车控指令的时序要求)

以下是RAG检索增强的完整实现:

python
import os
from typing import List, Dict
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import TextLoader, DirectoryLoader
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

class AutomotiveTestKnowledgeBase:
“”“汽车测试领域知识库,基于RAG实现”“”

def __init__(self, persist_directory: str = "./chroma_db"):
    self.persist_directory = persist_directory
    self.embeddings = OpenAIEmbeddings()
    self.vector_store = None
    self.text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000,
        chunk_overlap=200,
        separators=["\n\n", "\n", "。", ";", " "]
    )

def build_index(self, data_directories: List[str]):
    """从多个数据目录构建向量索引"""
    all_documents = []
    for directory in data_directories:
        loader = DirectoryLoader(
            directory,
            glob="**/*.txt",
            loader_cls=TextLoader,
            loader_kwargs={"encoding": "utf-8"}
        )
        documents = loader.load()
        all_documents.extend(documents)
    
    # 文档切分
    split_docs = self.text_splitter.split_documents(all_documents)
    
    # 构建向量库
    self.vector_store = Chroma.from_documents(
        documents=split_docs,
        embedding=self.embeddings,
        persist_directory=self.persist_directory
    )
    self.vector_store.persist()
    print(f"✅ 知识库构建完成,共 {len(split_docs)} 个文档块")

def retrieve_context(self, query: str, k: int = 5) -> List[Dict]:
    """检索与查询最相关的知识片段"""
    if not self.vector_store:
        self.vector_store = Chroma(
            persist_directory=self.persist_directory,
            embedding_function=self.embeddings
        )
    results = self.vector_store.similarity_search_with_score(query, k=k)
    return [
        {
            "content": doc.page_content,
            "score": score,
            "metadata": doc.metadata
        }
        for doc, score in results
    ]

def build_rag_chain(self, llm, retriever_k: int = 5):
    """构建RAG问答链"""
    retriever = self.vector_store.as_retriever(
        search_kwargs={"k": retriever_k}
    )
    
    prompt_template = """
    你是一位汽车座舱软件测试专家。请基于以下参考文档,回答用户的问题。
    
    ## 参考文档
    {context}
    
    ## 用户问题
    {question}
    
    请确保回答严格基于参考文档,不要编造不存在的信息。
    """
    
    return RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=retriever,
        chain_type_kwargs={"prompt": prompt_template}
    )

使用示例

kb = AutomotiveTestKnowledgeBase()
kb.build_index([“./api_docs/”, “./test_cases/”, “./code_standards/”])
context = kb.retrieve_context(“座舱车控测试的断言方式”)
print(f"检索到 {len(context)} 条相关规范")
研究表明,结合RAG的LLM方法能够成功生成可执行的集成测试脚本,并在实际工业场景中将测试执行工时减少43%。

3.3 第三层:智能Agent工作流(编排层)
单个Prompt + RAG检索仍然不足以应对复杂的测试脚本生成场景。对于多步骤、多工具的复杂任务,需要引入智能Agent工作流。

在汽车测试场景中,一个完整的测试脚本生成流程通常包括:

需求解析:将自然语言测试需求转化为结构化测试目标

知识检索:从知识库检索相关API、规范和历史用例

代码生成:基于检索结果生成测试脚本

语法验证:检查生成代码的语法正确性

执行验证:在沙箱环境中试运行,捕获错误

迭代修正:将错误信息反馈给模型,生成修正版本

以下是基于LangGraph构建的多智能体测试脚本生成工作流:

python
from typing import TypedDict, List, Annotated
from langgraph.graph import StateGraph, END
from langgraph.checkpoint import MemorySaver
from langchain.chat_models import ChatOpenAI
from langchain.tools import Tool
import ast
import subprocess
import tempfile

class TestGenerationState(TypedDict):
“”“工作流状态”“”
requirement: str # 原始需求
test_framework: str # 测试框架
parsed_requirement: dict # 解析后的结构化需求
retrieved_context: List[str] # 检索到的上下文
generated_code: str # 生成的代码
validation_result: dict # 验证结果
iteration_count: int # 迭代次数
max_iterations: int # 最大迭代次数
final_code: str # 最终代码

class TestScriptAgent:
“”“测试脚本生成多智能体系统”“”

def __init__(self, llm, knowledge_base):
    self.llm = llm
    self.kb = knowledge_base
    self.max_iterations = 3
    self.workflow = self._build_workflow()
    self.memory = MemorySaver()
    self.app = self.workflow.compile(checkpointer=self.memory)

def _build_workflow(self):
    workflow = StateGraph(TestGenerationState)
    
    # 注册各个节点
    workflow.add_node("parse_requirement", self._parse_requirement)
    workflow.add_node("retrieve_context", self._retrieve_context)
    workflow.add_node("generate_code", self._generate_code)
    workflow.add_node("validate_syntax", self._validate_syntax)
    workflow.add_node("execute_test", self._execute_test)
    workflow.add_node("fix_code", self._fix_code)
    
    # 定义流程
    workflow.set_entry_point("parse_requirement")
    workflow.add_edge("parse_requirement", "retrieve_context")
    workflow.add_edge("retrieve_context", "generate_code")
    workflow.add_edge("generate_code", "validate_syntax")
    
    # 条件分支:验证通过则执行,否则修复
    workflow.add_conditional_edges(
        "validate_syntax",
        self._should_execute,
        {
            "execute": "execute_test",
            "fix": "fix_code"
        }
    )
    
    # 执行后条件分支
    workflow.add_conditional_edges(
        "execute_test",
        self._should_finish,
        {
            "finish": END,
            "fix": "fix_code"
        }
    )
    
    # 修复后回到验证
    workflow.add_edge("fix_code", "validate_syntax")
    
    return workflow

def _parse_requirement(self, state: TestGenerationState):
    """节点1:解析测试需求"""
    parse_prompt = f"""
    将以下测试需求解析为结构化的测试目标,输出JSON格式:
    
    需求:{state['requirement']}
    测试框架:{state['test_framework']}
    
    输出格式:
    {{
        "test_scenario": "测试场景描述",
        "preconditions": ["前置条件1", "前置条件2"],
        "test_steps": ["步骤1", "步骤2", "步骤3"],
        "expected_results": ["预期结果1", "预期结果2"],
        "test_data": {{"key": "value"}}
    }}
    """
    response = self.llm.predict(parse_prompt)
    # 简化处理:假设返回有效JSON
    import json
    parsed = json.loads(response)
    state['parsed_requirement'] = parsed
    return state

def _retrieve_context(self, state: TestGenerationState):
    """节点2:检索相关知识"""
    query = state['parsed_requirement'].get('test_scenario', state['requirement'])
    contexts = self.kb.retrieve_context(query, k=5)
    state['retrieved_context'] = [c['content'] for c in contexts]
    return state

def _generate_code(self, state: TestGenerationState):
    """节点3:生成测试脚本"""
    context_str = "\n\n".join(state['retrieved_context'])
    
    gen_prompt = f"""
    基于以下信息,生成 {state['test_framework']} 测试脚本。
    
    ## 测试需求
    场景:{state['parsed_requirement']['test_scenario']}
    前置条件:{state['parsed_requirement']['preconditions']}
    测试步骤:{state['parsed_requirement']['test_steps']}
    预期结果:{state['parsed_requirement']['expected_results']}
    
    ## 参考上下文
    {context_str}
    
    ## 要求
    1. 使用 {state['test_framework']} 框架规范
    2. 包含完整的import和类定义
    3. 每个步骤对应一个测试方法或断言
    4. 只输出代码,不要解释
    """
    
    code = self.llm.predict(gen_prompt)
    state['generated_code'] = code
    state['iteration_count'] = state.get('iteration_count', 0) + 1
    return state

def _validate_syntax(self, state: TestGenerationState):
    """节点4:语法验证"""
    code = state['generated_code']
    result = {"valid": False, "errors": []}
    
    try:
        ast.parse(code)
        result["valid"] = True
    except SyntaxError as e:
        result["errors"].append({
            "type": "syntax_error",
            "message": str(e),
            "line": e.lineno
        })
    
    state['validation_result'] = result
    return state

def _should_execute(self, state: TestGenerationState):
    """决定是否执行测试"""
    if state['validation_result']['valid']:
        return "execute"
    return "fix"

def _execute_test(self, state: TestGenerationState):
    """节点5:执行测试(沙箱环境)"""
    code = state['generated_code']
    result = {"passed": False, "errors": [], "output": ""}
    
    try:
        with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
            f.write(code)
            temp_file = f.name
        
        # 使用pytest执行
        proc = subprocess.run(
            ["pytest", temp_file, "-v", "--tb=short"],
            capture_output=True,
            text=True,
            timeout=30
        )
        result["output"] = proc.stdout + proc.stderr
        result["passed"] = proc.returncode == 0
        
        if not result["passed"]:
            # 提取错误信息
            result["errors"] = self._extract_errors(proc.stderr)
            
    except Exception as e:
        result["errors"].append({"type": "execution_error", "message": str(e)})
    finally:
        if 'temp_file' in locals():
            os.unlink(temp_file)
    
    state['validation_result'] = result
    return state

def _should_finish(self, state: TestGenerationState):
    """决定是否完成"""
    if state['validation_result']['passed']:
        return "finish"
    if state['iteration_count'] >= state.get('max_iterations', 3):
        return "finish"  # 达到最大迭代次数
    return "fix"

def _fix_code(self, state: TestGenerationState):
    """节点6:修复代码"""
    errors = state['validation_result'].get('errors', [])
    error_msg = "\n".join([e['message'] for e in errors])
    
    fix_prompt = f"""
    以下测试脚本执行失败,请修复:
    
    ## 原始代码
    {state['generated_code']}
    
    ## 错误信息
    {error_msg}
    
    请输出修复后的完整代码。
    """
    
    fixed_code = self.llm.predict(fix_prompt)
    state['generated_code'] = fixed_code
    state['iteration_count'] += 1
    return state

def _extract_errors(self, stderr: str) -> List[dict]:
    """从pytest输出中提取错误信息"""
    errors = []
    lines = stderr.split('\n')
    for line in lines:
        if 'E       ' in line or 'AssertionError' in line:
            errors.append({"type": "test_failure", "message": line.strip()})
    return errors

def generate(self, requirement: str, test_framework: str = "pytest") -> dict:
    """执行完整的测试脚本生成流程"""
    initial_state = {
        "requirement": requirement,
        "test_framework": test_framework,
        "parsed_requirement": {},
        "retrieved_context": [],
        "generated_code": "",
        "validation_result": {},
        "iteration_count": 0,
        "max_iterations": self.max_iterations,
        "final_code": ""
    }
    
    config = {"configurable": {"thread_id": "test_gen_001"}}
    result = self.app.invoke(initial_state, config)
    
    return {
        "success": result['validation_result'].get('passed', False),
        "code": result['generated_code'],
        "iterations": result['iteration_count'],
        "errors": result['validation_result'].get('errors', [])
    }

使用示例

llm = ChatOpenAI(model=“gpt-4”, temperature=0.1)
agent = TestScriptAgent(llm, kb)

result = agent.generate(
requirement=“”"
测试座舱车控功能:用户通过中控屏点击"车窗升"按钮,
系统应发送CAN指令,车窗电机响应并完成上升动作。
验证点:1. CAN指令发送成功 2. 车窗状态变为"已关闭"
“”",
test_framework=“pytest”
)

print(f"生成{‘成功’ if result[‘success’] else ‘失败’},迭代{result[‘iterations’]}次")
print(result[‘code’])
3.4 第四层:效果评估与持续迭代(优化层)
体系化的最后一块拼图是建立可量化的评估体系。没有度量就无法优化。

评估维度应包括:

维度 指标 测量方式
正确性 脚本执行通过率 自动执行测试脚本
完整性 覆盖的测试场景数 与需求用例对比
规范性 代码风格符合率 静态代码分析
稳定性 多次生成一致性 同一输入重复生成10次
以下是一个自动化评估框架的实现:

python
class TestScriptEvaluator:
“”“测试脚本质量评估器”“”

def __init__(self, llm):
    self.llm = llm

def evaluate(self, requirement: str, generated_code: str) -> dict:
    """评估生成的测试脚本质量"""
    
    # 1. 语法正确性
    syntax_valid = self._check_syntax(generated_code)
    
    # 2. 执行通过率(需要实际运行)
    execution_result = self._run_test(generated_code)
    
    # 3. 需求覆盖度(LLM评估)
    coverage = self._assess_coverage(requirement, generated_code)
    
    # 4. 代码规范性
    style_score = self._check_style(generated_code)
    
    # 5. 输出一致性(重复生成对比)
    consistency = self._check_consistency(requirement)
    
    return {
        "syntax_valid": syntax_valid,
        "execution_passed": execution_result["passed"],
        "coverage_score": coverage,
        "style_score": style_score,
        "consistency_score": consistency,
        "overall_score": (
            syntax_valid * 0.2 +
            execution_result["passed"] * 0.3 +
            coverage * 0.25 +
            style_score * 0.15 +
            consistency * 0.1
        )
    }

def _check_syntax(self, code: str) -> bool:
    try:
        ast.parse(code)
        return True
    except SyntaxError:
        return False

def _run_test(self, code: str) -> dict:
    # 沙箱执行逻辑(同上)
    pass

def _assess_coverage(self, requirement: str, code: str) -> float:
    prompt = f"""
    对比测试需求和生成的测试代码,评估需求覆盖度(0-1之间):
    
    需求:{requirement}
    代码:{code[:2000]}
    
    输出一个0-1之间的数值。
    """
    response = self.llm.predict(prompt)
    try:
        return float(response.strip())
    except:
        return 0.5

def _check_style(self, code: str) -> float:
    # 可使用pylint等工具
    pass

def _check_consistency(self, requirement: str, n: int = 10) -> float:
    # 同一需求生成n次,计算输出相似度
    pass

四、汽车测试场景的实战案例
案例:座舱车控功能测试脚本生成
背景:某车企座舱团队需要为“车窗控制”功能生成自动化测试脚本,覆盖正常场景和异常场景。

传统方式:测试工程师手动编写pytest脚本,每个场景约需30-60分钟。

AI增强方式:使用上述体系化Prompt工程+RAG+Agent工作流。

输入需求:

text
测试场景:座舱车控-车窗上升
前置条件:车辆上电,车窗处于开启状态(位置>0%)
测试步骤:

  1. 用户点击中控屏"车窗升"按钮
  2. 系统发送CAN总线指令(ID: 0x1A2, Data: [0x01, 0x64])
  3. 车窗电机执行上升动作
    预期结果:
  4. CAN指令发送成功,总线监控到对应报文
  5. 车窗位置在3秒内变为0%(完全关闭)
  6. 中控屏显示"车窗已关闭"
    异常场景:
  7. 车窗已完全关闭时点击"车窗升"按钮,系统应提示"已处于关闭状态"
  8. CAN总线通信超时时,系统应提示"通信异常,请检查网络"
    生成的pytest脚本(简化示例):

python
import pytest
import time
from unittest.mock import Mock, patch
from can_interface import CANController
from window_controller import WindowController

class TestWindowControl:
“”“座舱车控-车窗控制测试套件”“”

@pytest.fixture
def controller(self):
    """初始化车窗控制器"""
    can = CANController(interface="virtual")
    return WindowController(can_interface=can)

@pytest.fixture
def can_monitor(self):
    """CAN总线监控"""
    return Mock()

def test_window_up_normal(self, controller, can_monitor):
    """TC-001: 正常场景-车窗上升"""
    # 前置条件:车窗处于开启状态
    controller.set_window_position(50)  # 50%开启
    assert controller.get_window_position() == 50
    
    # 执行:点击车窗升
    controller.window_up()
    
    # 验证1:CAN指令发送
    can_monitor.assert_called_with(
        can_id=0x1A2,
        data=[0x01, 0x64]
    )
    
    # 验证2:车窗在3秒内完全关闭
    time.sleep(3)
    assert controller.get_window_position() == 0
    
    # 验证3:UI状态更新
    assert controller.get_ui_status() == "已关闭"

def test_window_up_already_closed(self, controller):
    """TC-002: 异常场景-已关闭时点击上升"""
    controller.set_window_position(0)
    
    with pytest.raises(WindowAlreadyClosedError) as exc_info:
        controller.window_up()
    
    assert "已处于关闭状态" in str(exc_info.value)

def test_window_up_can_timeout(self, controller):
    """TC-003: 异常场景-CAN通信超时"""
    with patch('can_interface.CANController.send', side_effect=TimeoutError):
        with pytest.raises(CommunicationError) as exc_info:
            controller.window_up()
        
        assert "通信异常" in str(exc_info.value)

效果数据:

脚本生成时间:从30-60分钟降至2-5分钟

首次生成通过率:约65-75%(经1-2轮迭代后达90%+)

测试覆盖度:人工编写平均覆盖70%边界场景,AI生成覆盖95%+

五、落地建议与避坑指南
5.1 落地路径
从POC开始:选择1-2个高频、低复杂度的测试场景验证可行性

构建领域知识库:这是提升质量的关键——投入时间整理API文档、历史用例和代码规范

建立评估基线:在引入AI前记录人工编写的质量标准,作为对比基准

小范围试点:选择1个测试团队试用,收集反馈后迭代

规模化推广:将成熟的Prompt模板、知识库和Agent工作流标准化,赋能更多团队

5.2 常见陷阱
陷阱1:过分依赖简单Prompt。 单纯的提示词工程难以应对复杂测试场景。必须结合RAG和多智能体协作。

陷阱2:忽视输出验证。 生成代码后不加验证就直接使用,风险极高。务必建立语法检查+沙箱执行的验证闭环。

陷阱3:Prompt版本管理缺失。 随着团队扩大,Prompt数量呈指数增长。需要对Prompt进行版本控制,结合测试用例进行回归验证。

陷阱4:上下文过载。 上下文过长或噪声过多会导致“上下文坍塌”,模型忽略早期重要信息。应限制上下文token数量,优先注入结构化信息。

六、总结与展望
Prompt工程体系化建设的本质,是将大模型从“黑盒”变成“可编程的执行单元”。通过结构化提示设计、RAG知识库增强、智能Agent工作流编排和自动化效果评估,我们能够让大模型稳定地、可预期地生成高可用的测试脚本。

在汽车研发测试领域,这一体系的价值尤为突出——座舱软件迭代快、测试场景多、质量要求高。体系化的Prompt工程不仅能将测试脚本生成效率提升5-15倍,更能将测试覆盖度和质量提升到新的水平。

下一步,随着多智能体协作、自适应Prompt优化等技术的发展,测试脚本生成将从“半自动”走向“全自动”,从“生成脚本”走向“生成完整的测试方案”。而这一切的基石,正是今天我们所建设的——Prompt工程体系。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐