「Prompt 模板设计」是AI大模型使用中非常重要的一环,也是我们接下来的整个测试自动化流程的核心引擎,直接决定 AI 输出的代码 / 用例是否精准、可运行。通俗来讲,整个Prompt模板就是你发给AI大模型的问题内容。


一、 Prompt 的核心构成

优质 Prompt 的底层逻辑是「让 AI 完全理解你的场景 + 约束 + 期望」,建议包含以下6个要素:

  1. 角色定位:给 AI 明确的专业身份(带年限 + 技术栈,而非笼统的 “测试工程师”);
  2. 场景背景:补充项目 / 环境信息(让 AI 贴合实际场景,而非泛泛输出);
  3. 核心任务:拆分具体步骤(避免 AI 遗漏关键操作);
  4. 技术约束:明确框架版本、代码规范、性能要求(减少无效输出);
  5. 输出格式:精确到文件结构、注释要求、呈现形式(直接复用);
  6. 迭代引导:让 AI 自查输出是否符合要求(提升一次通过率)。

二、测试自动化「Prompt 模板库」

每个模板都包含上述 6 个模块,直接复制到你的代码中,deepseek-chat会输出远超之前的精准结果:

模板 1:生成企业级 Playwright UI 自动化代码(带 Page Object 模式)
角色:你是拥有5年全栈测试自动化经验的专家,精通Python3.9+、Playwright1.40+、pytest框架,熟悉Page Object设计模式和企业级测试代码规范。
场景背景:我正在测试一个Web项目(基于Vue3开发),当前需要测试「用户登录功能」,页面核心元素如下:
- 用户名输入框:id="username"(必填,支持手机号/邮箱)
- 密码输入框:id="password"(必填,6-20位字符)
- 登录按钮:class="login-btn"(点击后跳转到首页)
- 错误提示:id="error-msg"(登录失败时显示)
核心任务:生成符合以下要求的UI自动化测试代码:
1. 采用Page Object模式,拆分页面对象类(LoginPage)和测试用例类;
2. 测试用例覆盖3个场景:正向登录(正确账号密码)、反向登录(密码错误)、空值登录(用户名未填);
3. 每个用例包含前置条件(启动浏览器)、步骤、断言、后置条件(关闭浏览器)。
技术约束:
- Playwright版本指定为1.40.0,使用同步API(而非异步);
- 代码符合PEP8规范,变量命名采用蛇形命名法;
- 包含异常处理(如元素定位失败、超时)和详细注释(类/方法/关键步骤);
- 不依赖第三方库(仅使用playwright、pytest内置功能)。
输出格式:
1. 先输出「文件结构说明」(说明每个文件的作用和存放路径);
2. 再分别输出2个文件的完整代码(LoginPage.py、test_login.py);
3. 最后输出「运行说明」(包含安装依赖、执行命令、预期结果);
4. 只输出可直接复制的内容,不要多余解释。
迭代引导:输出前请自查:是否符合Page Object模式?是否覆盖所有测试场景?代码是否可直接运行?是否包含异常处理和注释?
模板 2:生成接口测试代码(带签名验证 + 数据驱动)
角色:你是资深接口测试专家,精通Python requests库、接口签名验证、pytest数据驱动测试,熟悉RESTful API规范。
场景背景:我需要测试一个「用户注册接口」,接口信息如下:
- 接口URL:https://api.example.com/v1/user/register
- 请求方法:POST
- 请求头:Content-Type: application/json;Authorization: Bearer {token}(token固定为"test_token_123")
- 签名规则:将请求体JSON字符串+密钥"test_secret"拼接后,用MD5加密作为sign参数,放入请求体。
核心任务:生成数据驱动的接口测试代码,覆盖以下场景:
1. 正向用例:必填参数完整(username、password、email);
2. 反向用例:缺少必填参数(无email)、参数格式错误(email无@)、密码长度不足(5位);
3. 每个用例包含请求构造、签名生成、响应断言(状态码、返回信息、数据格式)。
技术约束:
- 使用pytest的@pytest.mark.parametrize实现数据驱动;
- 签名生成逻辑需封装为独立函数(可复用);
- 包含请求超时处理(10秒)和异常捕获(如网络错误、接口500错误);
- 输出响应日志(包含请求参数、响应结果、耗时)。
输出格式:
1. 输出单个文件test_register_api.py的完整代码;
2. 代码中包含测试数据列表、签名函数、测试用例函数;
3. 末尾添加「运行步骤」和「预期结果说明」;
4. 代码可直接复制运行,无需修改。
迭代引导:自查是否包含签名逻辑?测试数据是否覆盖所有场景?断言是否全面?是否有日志输出?
模板 3:设计复杂场景测试用例(带风险等级 + 优先级)
角色:你是测试用例设计专家,擅长基于需求文档设计全量测试用例,熟悉等价类划分、边界值分析、场景法,有电商项目测试经验。
场景背景:需求是「电商购物车结算功能」,核心流程:选择购物车商品→勾选结算→填写收货地址→选择支付方式→提交订单。
核心规则:
1. 商品库存≥1时可结算,库存不足时提示“库存不足”;
2. 收货地址需填写完整(姓名、电话、省市区、详细地址),否则无法下一步;
3. 支持微信/支付宝支付,未选择支付方式时提示“请选择支付方式”;
4. 订单提交后,库存扣减、购物车对应商品删除。
核心任务:设计完整的测试用例集,要求:
1. 覆盖正向流程、反向流程、边界场景、异常场景(如网络中断、页面刷新);
2. 每个用例包含:用例ID、用例名称、前置条件、操作步骤、预期结果、风险等级(高/中/低)、优先级(P0/P1/P2);
3. 风险等级:涉及支付、库存的场景为高风险;功能异常为中风险;UI显示为低风险;
4. 优先级:核心流程(正向结算)为P0,反向场景为P1,边界/异常场景为P2。
输出格式:
1. 用Markdown表格呈现所有测试用例;
2. 表格列顺序:用例ID、用例名称、前置条件、操作步骤、预期结果、风险等级、优先级;
3. 先输出「用例设计说明」(说明覆盖的场景类型),再输出表格;
4. 不要多余解释,表格清晰易读。
迭代引导:自查是否覆盖所有核心规则?是否包含异常场景?风险等级和优先级划分是否合理?步骤和预期结果是否对应?
模板 4:分析测试失败日志并给出修复方案(带根因定位)
角色:你是测试问题排查专家,精通Playwright、接口测试常见报错,擅长从日志中定位根因,能给出具体可落地的修复方案。
场景背景:我运行Playwright UI自动化测试时,「购物车结算」用例失败,以下是完整报错日志和相关代码片段:
【报错日志】:
AssertionError: Expected page to have URL containing "/order/confirm", but got "https://example.com/cart"
Traceback (most recent call last):
  File "test_cart.py", line 45, in test_checkout
    page.wait_for_url("**/order/confirm", timeout=10000)
  File "/usr/local/lib/python3.9/site-packages/playwright/sync_api/_generated.py", line 984, in wait_for_url
    self._sync(
  File "/usr/local/lib/python3.9/site-packages/playwright/_impl/_sync_base.py", line 104, in _sync
    return task.result()
TimeoutError: Waiting for url "**/order/confirm" failed: Timeout 10000ms exceeded

【相关代码片段】:
def test_checkout(page):
    # 选择商品并点击结算
    page.locator(".cart-item").nth(0).check()  # 勾选第一个商品
    page.locator(".checkout-btn").click()  # 点击结算按钮
    page.wait_for_url("**/order/confirm", timeout=10000)  # 等待跳转订单确认页
    assert "/order/confirm" in page.url  # 断言跳转成功

核心任务:
1. 根因分析:从代码、页面逻辑、Playwright特性三个维度排查失败原因(可能的原因:元素定位错误、页面未加载完成、点击未触发跳转、超时时间不足);
2. 给出具体修复方案:包括代码修改细节(逐行标注修改点)、Playwright API使用优化、排查步骤(如何验证根因);
3. 补充预防措施:如何避免类似问题再次发生(如增加等待条件、优化定位方式)。
输出格式:
1. 分3个部分:根因分析(标序号)、修复方案(含修改后代码)、预防措施;
2. 代码修改部分用diff格式(+表示新增,-表示删除)呈现;
3. 语言简洁,步骤清晰,可直接按方案操作。
迭代引导:自查修复方案是否能解决超时问题?是否考虑多种可能原因?修改后的代码是否可直接运行?

三、模板迭代优化技巧(提升精准度)

Prompt模板不是一成不变的,需要根据 AI 的输出动态优化:

  1. 补充关键信息:如果生成的代码元素定位失败,可在 Prompt 中补充页面 HTML 片段(如「搜索框的 HTML 是<input id="kw" name="wd">」);
  2. 避免模糊描述:把 “生成代码” 改成 “生成可直接运行的 Playwright 代码”,把 “设计用例” 改成 “设计覆盖正向 / 反向 / 边界值的用例集”;
  3. 增加否定约束:如果 AI 输出多余解释,可在模板末尾加「不要输出任何解释,只输出代码 / 表格」;
  4. 迭代验证:每次用模板生成内容后,运行验证,若不符合要求,把问题补充到下一次的 Prompt 中(如「上次生成的代码缺少断言,请补充断言逻辑」)。

四、验证模板效果的步骤

把模板中的content部分替换到测试用例的messages中,示例:

messages = [
    {
        "role": "user",
        "content": """角色:你是拥有5年全栈测试自动化经验的专家...(完整模板内容)"""
    }
]
# 调用API
answer = deepseek.send_message(messages)
print(answer)
  • 检查输出是否符合「可直接运行、满足约束、格式正确」的要求;
  • 若输出不符合,根据问题调整模板(如补充关键信息、增加约束),再次验证;
  • 最终得到稳定输出的模板,存入你的模板库,后续直接复用。

五、拓展(车速有点快~按需引入)

痛点:将完整Prompt硬编码在测试脚本中,不仅导致代码冗余、修改困难,还增加了出错风险。

优化方案:将Prompt模板独立为配置文件或工具类,测试脚本仅负责调用而非编写

步骤 1:创建 Prompt 配置文件(prompt_templates.json)

在项目根目录新建config/prompt_templates.json,存放所有测试场景的 Prompt 模板(6个参数对应Prompt的6个要素,可自行修改):

{
  "playwright_ui": {
    "role": "你是一位拥有6年企业级Web自动化测试经验的工程师...",
    "context_feedback": "无",
    "task": "请为「电商购物车结算功能」生成可直接运行的UI自动化测试代码...",
    "constraint": "## 技术约束\n- 必须使用Page Object设计模式...",
    "output_format": "1. 先输出JSON格式的「文件清单」...",
    "self_check": "输出前请校验:\n- 代码是否符合Page Object模式?..."
  },
  "api_test": {
    "role": "你是一位资深接口测试工程师...",
    "context_feedback": "无",
    "task": "请为「用户登录接口」生成数据驱动的接口测试代码...",
    "constraint": "## 技术约束\n- 接口信息:URL=https://api.deepseek.com/v1/user/login...",
    "output_format": "1. 输出单个文件test_login_api.py的完整代码...",
    "self_check": "输出前请校验:\n- 签名函数是否正确实现MD5加密?..."
  },
  "case_design": {
    "role": "你是一位高级测试用例设计师...",
    "context_feedback": "无",
    "task": "请为「商品库存修改接口」设计完整测试用例集...",
    "constraint": "## 技术约束\n- 接口信息:URL=/v1/product/stock...",
    "output_format": "1. 先输出「用例设计说明」(Markdown)...",
    "self_check": "输出前请校验:\n- 用例是否覆盖所有核心规则?..."
  }
}

Prompt配置文件字段说明:

步骤2:编写 PromptManager工具类(utils/prompt_manager.py)
import json
import os
from typing import Dict, Optional

class PromptManager:
    """纯Prompt管理类,只负责Prompt的读取、参数替换、校验,不耦合任何API逻辑"""
    def __init__(self, config_path: str = "config/prompt_templates.json"):
        self.config_path = config_path
        self._load_templates()  # 初始化时加载模板

    def _load_templates(self) -> None:
        """私有方法:加载Prompt配置文件,只在初始化时执行"""
        if not os.path.exists(self.config_path):
            raise FileNotFoundError(f"Prompt配置文件不存在:{self.config_path}")
        with open(self.config_path, "r", encoding="utf-8") as f:
            self.templates: Dict = json.load(f)

    def get_template(self, template_name: str) -> Dict:
        """获取原始模板(供内部/外部调用,方便拓展)"""
        if template_name not in self.templates:
            raise ValueError(f"无此Prompt模板:{template_name}")
        return self.templates[template_name]

    def render_prompt(self, template_name: str, context_feedback: str = "无", **kwargs) -> str:
        """核心方法:渲染参数化Prompt,返回完整字符串"""
        template = self.get_template(template_name)
        
        # 拼接基础模板结构
        prompt_parts = [
            f"# 角色定义\n{template['role']}",
            f"\n# 上下文反馈\n【历史反馈】:{context_feedback}",
            f"\n# 任务描述\n{template['task']}",
            f"\n# 约束条件\n{template['constraint']}",
            f"\n# 输出格式\n{template['output_format']}",
            f"\n# 自检规则\n{template['self_check']}"
        ]
        full_prompt = "\n".join(prompt_parts)
        
        # 动态替换参数(支持自定义变量)
        for key, value in kwargs.items():
            full_prompt = full_prompt.replace(f"{{{key}}}", str(value) or "无")
        
        return full_prompt

    # 拓展示例:后续加新功能,只改这个类,不影响API类
    def reload_templates(self) -> None:
        """重新加载模板(比如配置文件改了,不用重启程序)"""
        self._load_templates()

    def list_all_templates(self) -> list:
        """列出所有模板名称(方便管理/调试)"""
        return list(self.templates.keys())
步骤3:在DeepSeekAPI 类中实例化PromptManager(utils/deepseek_api.py)
import requests
from typing import List, Dict, Optional
from utils.prompt_manager import PromptManager  # 聚合独立的PromptManager

class DeepSeekAPI:
    """只负责DeepSeek API调用,通过聚合PromptManager简化Prompt使用,不耦合Prompt逻辑"""
    def __init__(self, api_key: str, prompt_config_path: str = "config/prompt_templates.json"):
        # API核心配置
        self.api_key = api_key
        self.base_url = "https://api.deepseek.com/v1/chat/completions"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }
        self.default_model = "deepseek-chat"
        
        # 聚合PromptManager(而非硬编码其逻辑)
        self.prompt_manager = PromptManager(config_path=prompt_config_path)

    # 基础API调用方法(独立,方便单独调用API)
    def send_message(self, messages: List[Dict]) -> str:
        """纯API调用方法,和Prompt解耦,可单独使用"""
        payload = {
            "model": self.default_model,
            "messages": messages,
            "temperature": 0.7,
            "max_tokens": 2000
        }
        try:
            response = requests.post(
                url=self.base_url,
                headers=self.headers,
                json=payload,
                timeout=30
            )
            response.raise_for_status()
            return response.json()["choices"][0]["message"]["content"]
        except Exception as e:
            raise Exception(f"DeepSeek API调用失败:{str(e)}")

    # 一键调用方法(整合Prompt+API,简化使用)
    def send_message_with_prompt(self, template_name: str, context_feedback: str = "无", **kwargs) -> str:
        """对外简化调用,内部仍由独立类处理"""
        # 1. 调用独立的PromptManager渲染Prompt
        prompt = self.prompt_manager.render_prompt(
            template_name=template_name,
            context_feedback=context_feedback,** kwargs
        )
        # 2. 调用独立的API发送方法
        messages = [{"role": "user", "content": prompt}]
        return self.send_message(messages)

    # 拓展示例:切换模型(不影响PromptManager)
    def switch_model(self, model_name: str) -> None:
        """切换调用的模型(chat/reasoner)"""
        self.default_model = model_name
步骤4:测试脚本调用(既便捷,又保留拓展性)
# test_cases/test_deepseek_opt.py
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.deepseek_api import DeepSeekAPI

API_KEY = "你的API Key"

def test_optimal_solution():
    """调用示例:一键使用,且保留拓展性"""
    # 初始化API(自动聚合PromptManager)
    deepseek = DeepSeekAPI(api_key=API_KEY)
    
    # 场景1:一键调用(简化使用)
    answer = deepseek.send_message_with_prompt(
        template_name="playwright_ui",  # 对应prompt_templates.json里的key
        function_name="电商购物车结算功能",  # 模板的参数占位符 非必填
        # page_elements="搜索框id=kw,搜索按钮id=su"  # 模板的参数占位符 非必填
        # 上面这两个占位符必须和 Prompt 模板里 task 的核心方向一致,否则导致AI理解偏离需求
    )
    print(f"✅ 一键调用结果:\n{answer}...")

    # 场景2:单独使用PromptManager(拓展/调试)
    prompt = deepseek.prompt_manager.render_prompt(
        template_name="api_test",
        context_feedback="上次生成的签名函数缺空值处理"
    )
    print(f"\n🔍 单独获取Prompt:\n{prompt}...")

    # 场景3:单独调用API(拓展/自定义消息)
    custom_messages = [{"role": "user", "content": "自定义提问:生成pytest基础用例"}]
    custom_answer = deepseek.send_message(custom_messages)
    print(f"\n📝 自定义API调用结果:\n{custom_answer}...")

if __name__ == "__main__":
    test_optimal_solution()
验证成果

1.打开终端运行脚本命令:pytest test_cases/test_deepseek_opt.py -s -v

2.成功标志 PASSED

3.可能失败(读取超时错误)

Exception: DeepSeek API调用失败:HTTPSConnectionPool(host='api.deepseek.com', port=443): Read timed out

诱因:超时时间设置过短,不足以完成大 Prompt 的响应传输

修复方案:延长超时时间&精准异常捕获(utils/deepseek_api.py

import requests
from typing import List, Dict
from utils.prompt_manager import PromptManager


class DeepSeekAPI:
    """只负责DeepSeek API调用,通过聚合PromptManager简化Prompt使用,不耦合Prompt逻辑"""

    def __init__(self, api_key: str, prompt_config_path: str = "config/prompt_templates.json"):
        # API核心配置
        self.api_key = api_key
        self.base_url = "https://api.deepseek.com/v1/chat/completions"
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }
        self.default_model = "deepseek-chat"

        # 聚合PromptManager(而非硬编码其逻辑)
        self.prompt_manager = PromptManager(config_path=prompt_config_path)

    # 基础API调用方法(优化超时&异常捕获)
    def send_message(self, messages: List[Dict]) -> str:
        """纯API调用方法,和Prompt解耦,可单独使用"""
        payload = {
            "model": self.default_model,
            "messages": messages,
            "temperature": 0.7,
            "max_tokens": 2000
        }
        try:
            # 延长超时时间到60秒,增加连接超时+读取超时分开配置
            response = requests.post(
                url=self.base_url,
                headers=self.headers,
                json=payload,
                timeout=(10, 60)  # (连接超时10s, 读取超时60s) 按需修改
            )
            response.raise_for_status()
            return response.json()["choices"][0]["message"]["content"]
        # 精准捕获不同异常,方便排查
        except requests.exceptions.ConnectTimeout:
            raise Exception("DeepSeek API调用失败:连接服务器超时(检查网络/服务器是否可达)")
        except requests.exceptions.ReadTimeout:
            raise Exception("DeepSeek API调用失败:读取响应超时(延长超时时间/减少max_tokens)")
        except requests.exceptions.ConnectionError:
            raise Exception("DeepSeek API调用失败:网络连接错误(检查网络/代理)")
        except requests.exceptions.HTTPError as e:
            raise Exception(f"DeepSeek API返回错误码:{e.response.status_code},详情:{e.response.text}")
        except Exception as e:
            raise Exception(f"DeepSeek API调用失败:{str(e)}")

    # 一键调用方法(整合Prompt+API,简化使用)
    def send_message_with_prompt(self, template_name: str, context_feedback: str = "无", **kwargs) -> str:
        """对外简化调用,内部仍由独立类处理"""
        # 1. 调用独立的PromptManager渲染Prompt
        prompt = self.prompt_manager.render_prompt(
            template_name=template_name,
            context_feedback=context_feedback, **kwargs
        )
        # 2. 调用独立的API发送方法
        messages = [{"role": "user", "content": prompt}]
        return self.send_message(messages)

    # 拓展示例:切换模型(不影响PromptManager)
    def switch_model(self, model_name: str) -> None:
        """切换调用的模型(chat/reasoner)"""
        self.default_model = model_name

总结

核心成果:设计了AI测试场景的Prompt模板工程化方案,涵盖代码生成、用例设计、问题排查等核心场景;

关键突破:通过独立的PromptManager类抽离模板,取代脚本硬编码方式,实现模板的集中管理、参数化渲染与动态迭代;

方案亮点:采用“独立类 + 聚合调用”架构,确保Prompt管理与API调用的职责分离(便于维护与扩展),同时提供一键调用方法,简化使用流程;

落地价值:为AI生成高质量测试资产(代码/用例)奠定基础,显著减少重复编写Prompt的成本,提升测试自动化效率。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐