Agent用例生成进阶:从测试策略到Pytest代码
概述上一篇做了测试策略输入需求输出JSON。但CI流水线不认JSON它要的是pytest能跑的东西这篇就把测试策略转成Pytest代码。现在我们有策略策略里啥都有场景、预期、类型、优先级。把这些喂给AI需求进去代码出来中间不需要人动手。用例生成模块是做什么的输入测试策略JSON输出Pytest测试代码。具体点说输入是上一篇生成的策略功能名称、场景列表、步骤、预期结果。输出是一个完整的测试文件你拿过来就能用pytest命令跑。为什么要拆成两步把意图理解和用例生成合并成一步输入需求直接输出Pytest代码。听起来很爽少了一道工序但合在一起真的不好用。可能带来的问题出错了你找不到原因生成的代码挂了你不知道是需求理解错了还是代码生成环节出了岔子。日志里只有头和尾中间发生了什么是个黑盒。你想改没地方下手。策略生成错了你想手动改一下再重新生成。如果合并成一步你得重新跑一遍完整流程API费用再花一次。换个框架你得重写全部。同一个测试策略你可能想生成pytest版本的也可能想生成unittest版本的合并的话每种框架你得维护一套完整逻辑。拆开的话策略模块不用动只换生成模块就行。所以拆开更实用具体怎么做3.1 核心实现先写一个生成器类。# test_generation.pyimportjsonimportosfrompathlibimportPathfromtypingimportDict,Optionalfromdotenvimportload_dotenvfromopenaiimportOpenAIclassTestGenerationAgent: 用例生成Agent。 输入测试策略JSON和源代码输出Pytest测试代码。 def__init__(self,model:strgpt-4o):load_dotenv()self.clientOpenAI(api_keyos.getenv(OPENAI_API_KEY),base_urlos.getenv(OPENAI_BASE_URL,None))self.modelmodeldefgenerate(self,strategy:Dict,source_code:str,module_name:strapp)-str:根据测试策略和源代码生成Pytest测试代码。promptself._build_prompt(strategy,source_code,module_name)try:responseself.client.chat.completions.create(modelself.model,messages[{role:system,content:self._get_system_prompt()},{role:user,content:prompt}],temperature0.3)returnresponse.choices[0].message.contentexceptExceptionase:print(f用例生成失败:{e})returndef_get_system_prompt(self)-str:return 你是一位资深的测试开发工程师擅长用Pytest编写高质量的单元测试。 你的任务是根据提供的测试策略和源代码生成完整的Pytest测试代码。 要求 1. 测试代码必须覆盖策略中定义的所有场景 2. 使用pytest框架遵循最佳实践 3. 每个测试场景对应一个测试方法 4. 方法名用test_开头后面跟场景的英文标识 5. 使用pytest.raises处理异常场景 6. 添加适当的注释说明每个测试的用途 7. 代码风格清晰、规范 8. 只输出Python代码不要额外解释 def_build_prompt(self,strategy:Dict,source_code:str,module_name:str)-str:scenariosstrategy.get(test_scenarios,[])scenario_textjson.dumps(scenarios,indent2,ensure_asciiFalse)returnf#下面是待测试的源代码{source_code}#下面是测试策略包含需要覆盖的测试场景{scenario_text}# 请为 {module_name} 模块生成完整的Pytest测试代码。defsave_test_code(code:str,filepath:strtest_generated.py):withopen(filepath,w,encodingutf-8)asf:f.write(code)print(f测试代码已保存:{filepath})3.2 如何使用加载上一篇生成的测试策略传入源代码调用生成器。if__name____main__:# 加载上一篇生成的测试策略withopen(login_strategy.json,r,encodingutf-8)asf:strategyjson.load(f)# 被测试的源代码source_code # login.py class UserService: def __init__(self): self._users { 13800001111: {password: 123456, nickname: 张三, locked: False}, testexample.com: {password: 123456, nickname: 李四, locked: False}, } self._login_attempts {} self._locked_accounts {} def login(self, account: str, password: str) - dict: if account not in self._users: return {success: False, message: 账号不存在} user self._users[account] if user.get(locked, False): return {success: False, message: 账号已被锁定请联系客服} if account in self._locked_accounts: lock_time self._locked_accounts[account] if lock_time 0: return {success: False, message: 账号已被锁定30分钟} if user[password] ! password: self._login_attempts[account] self._login_attempts.get(account, 0) 1 if self._login_attempts[account] 5: self._locked_accounts[account] 30 return {success: False, message: 因多次登录失败账号已被锁定30分钟} return {success: False, message: 密码错误} self._login_attempts[account] 0 return { success: True, message: 登录成功, nickname: user[nickname] } agentTestGenerationAgent()test_codeagent.generate(strategy,source_code,login)iftest_code:save_test_code(test_code,test_login.py)print(\n生成的测试代码\n)print(test_code)else:print(生成失败)3.3 AI生成的代码运行上面的脚本test_login.py的内容大概是这样的。# test_login.pyimportpytestfromloginimportUserServiceclassTestUserLogin:用户登录功能的测试套件defsetup_method(self):每个测试方法执行前重置状态self.serviceUserService()deftest_login_with_phone_success(self):TC-001: 使用手机号正确登录resultself.service.login(13800001111,123456)assertresult[success]isTrueassertresult[message]登录成功assertresult[nickname]张三deftest_login_with_email_success(self):TC-002: 使用邮箱正确登录resultself.service.login(testexample.com,123456)assertresult[success]isTrueassertresult[message]登录成功assertresult[nickname]李四deftest_login_account_not_exist(self):TC-003: 登录失败-账号不存在resultself.service.login(13900001111,123456)assertresult[success]isFalseassertresult[message]账号不存在deftest_login_wrong_password(self):TC-004: 登录失败-密码错误resultself.service.login(13800001111,wrongpass)assertresult[success]isFalseassertresult[message]密码错误deftest_login_account_locked_by_admin(self):TC-005: 登录失败-账号被锁定self.service._users[13800001111][locked]Trueresultself.service.login(13800001111,123456)assertresult[success]isFalseassertresult[message]账号已被锁定请联系客服deftest_login_trigger_lock_after_5_failures(self):TC-006: 连续输错密码触发锁定account13800001111foriinrange(5):resultself.service.login(account,wrongpass)ifi4:assertresult[message]密码错误else:assertresult[message]因多次登录失败账号已被锁定30分钟assertresult[success]isFalsedeftest_login_paste_disabled(self):TC-007: 密码框禁止粘贴# 这个场景是前端约束单元测试测不了# 实际项目中需要UI自动化测试覆盖pytest.skip(前端约束需要UI自动化测试验证)deftest_login_response_time(self):TC-008: 登录接口响应时间importtime starttime.time()self.service.login(13800001111,123456)elapsed(time.time()-start)*1000assertelapsed500,f响应时间{elapsed}ms超过500ms策略里的8个场景变成了8个测试方法。每个方法对应一个场景断言也写好了。3.3 把两步串起来下面这个脚本把意图理解和用例生成串成一条线。# end_to_end.pyimportjsonfromintent_understandingimportIntentUnderstandingAgentfromtest_generationimportTestGenerationAgentdefrun_end_to_end(requirement:str,source_code:str,module_name:strapp):print(*50)print(Step 1: 意图理解)print(*50)intent_agentIntentUnderstandingAgent()strategyintent_agent.understand(requirement)iferrorinstrategy:print(f失败:{strategy[error]})returnprint(f生成{len(strategy.get(test_scenarios,[]))}个场景)withopen(strategy_output.json,w,encodingutf-8)asf:json.dump(strategy,f,indent2,ensure_asciiFalse)print(策略已保存: strategy_output.json)print(\n*50)print(Step 2: 用例生成)print(*50)gen_agentTestGenerationAgent()test_codegen_agent.generate(strategy,source_code,module_name)ifnottest_code:print(生成失败)returnwithopen(test_output.py,w,encodingutf-8)asf:f.write(test_code)print(测试代码已保存: test_output.py)print(\n*50)print(完成)print(*50)print(f场景数:{len(strategy.get(test_scenarios,[]))})print(下一步: pytest test_output.py -v)if__name____main__:requirement 需求用户登录功能 用户可以使用手机号或邮箱进行登录。 登录时需要验证密码是否正确。 登录成功后的行为 - 跳转到个人主页 - 在顶部显示用户昵称 登录失败的场景 - 手机号/邮箱不存在提示账号不存在 - 密码错误提示密码错误 - 账号被锁定提示账号已被锁定请联系客服 安全要求 - 连续输错5次密码后账号锁定30分钟 source_code class UserService: def __init__(self): self._users { 13800001111: {password: 123456, nickname: 张三, locked: False}, } self._login_attempts {} self._locked_accounts {} def login(self, account: str, password: str) - dict: if account not in self._users: return {success: False, message: 账号不存在} user self._users[account] if user.get(locked, False): return {success: False, message: 账号已被锁定请联系客服} if account in self._locked_accounts: return {success: False, message: 账号已被锁定30分钟} if user[password] ! password: self._login_attempts[account] self._login_attempts.get(account, 0) 1 if self._login_attempts[account] 5: self._locked_accounts[account] 30 return {success: False, message: 因多次登录失败账号已被锁定30分钟} return {success: False, message: 密码错误} self._login_attempts[account] 0 return {success: True, message: 登录成功, nickname: user[nickname]} run_end_to_end(requirement,source_code,login)跑完之后执行pytest test_output.py-v看到测试通过的那一刻整个流程就闭环了。需求进去代码出来中间不用你写一行。常见问题Q1生成的代码能直接用吗最好检查一遍。AI偶尔会犯错。import路径不对或者依赖的类名写错了。大问题不多小毛病难免。但比自己从头写还是能省了至少一个小时的时间Q2代码跑不通怎么办把报错信息贴给AI让它自己改。这是目前最省事的做法。把pytest的输出复制下来跟原始代码一起发给AI告诉它这段测试挂了帮我修一下。大部分情况下AI能自己搞定。Q3场景太多了生成慢怎么办拆成几批。如果一个策略有20多个场景你可以分两批生成。先让AI生成前10个保存。再生成后10个追加到同一个文件。这样每次请求的数据量小一些响应快也不容易超出AI的上下文窗口。Q4项目代码风格不一样怎么办把规范写进prompt里。比如你们项目要求测试类必须继承某个基类或者必须用特定的fixture。把这些要求写进系统提示词AI会照着做。如果你想做得更细致可以在项目里放一个规范文件每次生成之前让AI先读一遍。总结意图理解管出策略用例生成出代码中间用JSON对接。整个流程是这样的需求描述 → 测试策略 → Pytest代码 → pytest执行前三步我们已经能自动跑通了第四步就是pytest自己的事。

相关新闻

C++函数指针语法和类型

C++函数指针语法和类型

函数指针是 C/C 中一种将函数地址作为变量存储和传递的机制,它允许程序在运行时动态选择并调用不同的函数,是实现回调、策略模式和插件系统的核心基础。核心语法结构函数指针的声明语法遵循“返回类型 (*指针名)(参数列表)”的格式。例如,声明…

2026/8/23 23:48:50 阅读更多 →
Go服务生产环境的生存规则,你知道几条?

Go服务生产环境的生存规则,你知道几条?

Go 让你很容易就能写出一段“能编译、能通过冒烟测试、一遇到真实流量就跪”的代码。这门语言默认给你很少——没有运行时异常可以捕获,没有框架护栏,没有魔法。这是个特性,但这也意味着:让一个服务在生产环境活下去的规则&#x…

2026/8/23 23:48:50 阅读更多 →
后备箱里的汉中乡愁:一台车,装满故乡的烟火与牵挂

后备箱里的汉中乡愁:一台车,装满故乡的烟火与牵挂

对于很多汉中家庭,汽车后备箱,是独属于陕南人的乡愁容器。逢年过节从乡下返回城里,后备箱被父母塞得满满当当:自家腌制的腊肉、土蜂蜜、新鲜蔬菜、核桃馍,大大小小袋子塞满每一处缝隙。车子,成为城乡之间情…

2026/8/23 23:47:50 阅读更多 →

最新新闻

P2327 [SCOI2005] 扫雷

P2327 [SCOI2005] 扫雷

P2327 [SCOI2005] 扫雷 题目分析 本题是一个有趣的递推问题。棋盘是 n2n \times 2n2 的,第一列可能埋有地雷,第二列没有地雷。 关键点:由于棋盘只有2列,第二列每个格子只能与第一列的 3个方向(左上、左、左下&#…

2026/8/24 1:35:22 阅读更多 →
VSCode配置Vetur与Prettier实现Vue代码保存自动格式化

VSCode配置Vetur与Prettier实现Vue代码保存自动格式化

1. 项目概述:为什么我们需要“保存即格式化”? 作为一名长期在Vue项目里摸爬滚打的前端开发者,我敢说,代码格式的一致性绝对是团队协作的“生命线”。你肯定遇到过这种情况:从Git上拉下同事的代码,满屏的缩…

2026/8/24 1:35:22 阅读更多 →
AI辅助编程与Bot开发:从理念到快速交付的工程实践

AI辅助编程与Bot开发:从理念到快速交付的工程实践

这次我们来看一个关于 Cursor AI 和 Bot 开发文化的讨论。核心不是某个具体的工具或模型,而是一种开发理念和工程实践。对于开发者而言,理解这种“热爱交付”的文化,远比掌握某个单一技术更有价值。它能直接影响你的项目迭代速度、团队协作效…

2026/8/24 1:35:22 阅读更多 →
异构大模型智能体协同:迭代式批判与路由控制器(ICRC)设计与实现

异构大模型智能体协同:迭代式批判与路由控制器(ICRC)设计与实现

1. 项目缘起:当异构大模型智能体需要协同工作最近在折腾一个多智能体协作的项目,遇到了一个挺有意思的挑战:我们手头有几个不同“出身”的大语言模型智能体,有的擅长逻辑推理,有的精于创意生成,还有的对特定…

2026/8/24 1:35:22 阅读更多 →
[AI][昇腾950]TA 学习

[AI][昇腾950]TA 学习

TA(Transaction Layer,事务层)学习笔记 一、TA 在协议栈中的定位 UB 协议栈自顶向下四层: Transaction(TA) → Transport(TP/CTP) → Network(NL) → DataLinkPhysical(DL_PHY)↓H112 SerDesTA 是最上层,面向软件…

2026/8/24 1:35:22 阅读更多 →
DBeaver 数据比较 + 性能监控实战指南:数据对不上、越查越慢?一篇讲透

DBeaver 数据比较 + 性能监控实战指南:数据对不上、越查越慢?一篇讲透

DBeaver 数据比较 性能监控实战指南:数据对不上、越查越慢?一篇讲透 【免费下载链接】dbeaver Free universal database tool and SQL client 项目地址: https://gitcode.com/GitHub_Trending/db/dbeaver 你是不是也遇到过这种头疼时刻&#xff…

2026/8/24 1:34:22 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →