概述
在上一篇中,我们看到了AI生成Pytest用例的效果,对于一个简单的计算函数,Agent在10秒钟内生成了5个测试用例,并且覆盖了正常、异常、边界的场景,这些如果人工手写的话,则要10多分钟,如果你以为AI Agent只是帮你写代码的智能版Copilot,no no no~
AI Agent对自动化测试的改变,不在"写"这个动作上,而在"维护"这个死结上。
本篇中我们来了解一个完整的"Pytest + AI Agent"测试系统到底长什么样,数据是怎么流的,以及你自己怎么搭一个最简易的版本出来
AI Agent要解决的问题
传统的脚本驱动有三个死结:
1. 脚本和代码强绑定: 接口字段变了,脚本挂。页面元素ID变了,脚本挂。第三方服务地址换了,脚本挂。你写的每一行断言,都是对未来的一次赌博,赌这些东西不会变。
2. 维护成本随规模指数增长: 100个用例的时候,改一轮还扛得住。1000个用例的时候,改一轮需要一周。10000个用例的时候......你根本不敢随便改。
3. 人肉翻译的效率天花板: 需求文档是中文,测试步骤是中文,但你要把它们翻译成Python代码、翻译成断言。这个翻译过程没有任何复用价值,下个需求来了,重新翻一遍。
AI Agent要解决的,就是这三个死结
一个完整的AI Agent测试系统长什么样**
下图是整体结构:
┌─────────────────────────────────────┐
│ 1. 意图理解模块 │
│ (需求描述/代码变更 → 测试策略) │
└─────────────────┬───────────────────┘
↓
┌─────────────────────────────────────┐
│ 2. 用例生成模块 │
│ (测试策略 → Pytest代码) │
└─────────────────┬───────────────────┘
↓
┌─────────────────────────────────────┐
│ 3. 执行与收集模块 │
│ (运行pytest → 收集结果) │
└─────────────────┬───────────────────┘
↓
┌─────────────────────────────────────┐
│ 4. 分析与修复模块 │
│ (失败分析 → 自动修复 → 重跑) │
└─────────────────────────────────────┘
2.1 意图理解模块:把"人话"翻译成"测试策略"
传统模式下,你拿到需求文档,自己理解其中的逻辑,还要整理测试点,设计用例场景等,意图理解模块做的是同一件事,只不过它用LLM来做
输入是一段自然语言描述,比如:
"用户使用正确的用户名和密码登录后,应该能看到个人主页,主页上显示用户的昵称和头像。"
输出是一个结构化的测试策略:
json
{
"test_scenarios": [
{
"name": "正常登录",
"steps": ["访问登录页", "输入用户名", "输入密码", "点击登录"],
"expected": "跳转到个人主页,显示昵称和头像"
},
{
"name": "密码错误",
"steps": ["访问登录页", "输入用户名", "输入错误密码", "点击登录"],
"expected": "提示'用户名或密码错误',停留在登录页"
}
]
}
这个模块的价值:把"人工理解需求"变成了"AI辅助理解需求",也就是说我们只需要用自然语言,对AI描述我们要测什么就行
2.2 用例生成模块:把"测试策略"翻译成"Pytest代码"
这个模块上一篇已经演示过了------输入源代码,输出Pytest测试代码。
但在完整系统中,它不只是看源代码。它还会看:
- 你项目里的conftest.py(有哪些现成的fixture可以用)
- 你项目里的测试规范(命名规范、断言风格)
- 相关的API文档或Swagger定义
对于AI来说,上下文越丰富,生成的代码质量就越高。
2.3 执行与收集模块:跑测试,收结果
这个模块很简单,就是调用pytest.main(),然后把运行结果收集起来。
但注意一个关键点:执行和断言是确定性的。
AI生成用例,Pytest把关验证用例的正确性,assert的结果、pytest.raises捕获的异常、以及测试执行的结果是确定的
2.4 分析与修复模块
解决了写测试用例的问题,接下来该解决改测试用例的事情了,当Pytest运行用例失败,这个模块会做三件事:
- 分析失败原因:是断言错了?是元素定位变了?是接口返回格式变了?
- 提出修复方案:根据失败原因,生成对应的代码修改
- 自动修复并重跑:应用修改,重新执行Pytest,验证是否通过
这就是自愈测试(Self-healing Test)
GitHub上已经出现了ai-testing-lab这样的实验仓库,专门探索AI辅助测试和自愈测试。checkagent是一个pytest插件,专门用于测试AI Agent工作流,了解这些后,你是否觉得AI对于测试来说也很近了呢
确定性 vs 非确定性
很多人对AI Agent测试最大的疑虑是,AI生成的东西是随机的,可信度或者说准确度是否可靠?",这里需要区分两个概念:
-
AI生成是概率性的, 同样的输入,GPT今天生成的代码和明天生成的可能不一样,输出比较随机。
-
用例执行的结果是确定性的, 同样的测试代码,今天跑和明天跑,结果应该一样,除非测试对象代码变了。
所以正确的做法是,AI处理不确定性的部分,也就是用例的生成、逻辑的理解、测试失败后的修复,确定性的部分,比如执行、断言、验证则交给Pytest ,这样既提升了效率,又保证了质量。
30行代码看清Agent测试系统的结构
直接上代码,下面这个脚本模拟了一个最简单的AI Agent测试框架。
说明:这里还没有接入真正的LLM,先展示整个框架的结构组成
python
# minimal_agent_runner.py
import json
import pytest
from pathlib import Path
from typing import Dict, List
class MinimalTestAgent:
"""
一个极简的测试Agent模拟器。
不调用LLM,但展示了完整的"输入→生成→执行→输出"闭环。
"""
def __init__(self, workspace: str = "./agent_workspace"):
self.workspace = Path(workspace)
self.workspace.mkdir(exist_ok=True)
def load_scenario(self, scenario_file: str) -> Dict:
"""加载测试场景描述(模拟"意图理解")"""
with open(scenario_file, 'r') as f:
return json.load(f)
def generate_test_code(self, scenario: Dict) -> str:
"""
根据场景生成Pytest代码(模拟"用例生成")。
真实场景中这里会调用LLM,现在我们用模板硬编码。
"""
func_name = scenario['function']
test_cases = scenario['test_cases']
lines = [
"import pytest",
f"from {scenario.get('module', 'calculator')} import {func_name}",
"",
"",
f"class Test{func_name.capitalize()}:",
f' """测试 {func_name} 函数"""',
""
]
for case in test_cases:
lines.append(f" def test_{case['name']}(self):")
if 'raises' in case:
lines.append(f' with pytest.raises({case["raises"]}):')
lines.append(f" {func_name}({case['input']})")
else:
lines.append(f" assert {func_name}({case['input']}) == {case['expected']}")
lines.append("")
return "\n".join(lines)
def run_tests(self) -> Dict:
"""执行Pytest并收集结果(模拟"执行与收集")"""
result = pytest.main([
str(self.workspace / "test_generated.py"),
"-v",
"--tb=short"
])
return {"exit_code": result, "passed": result == 0}
def run(self, scenario_file: str) -> Dict:
"""完整的执行闭环"""
print("Step 1: 加载测试场景...")
scenario = self.load_scenario(scenario_file)
print("Step 2: 生成Pytest测试代码...")
test_code = self.generate_test_code(scenario)
test_file = self.workspace / "test_generated.py"
test_file.write_text(test_code)
print(f"已生成: {test_file}")
print("Step 3: 执行Pytest...")
result = self.run_tests()
print("Step 4: 测试结果")
print(f" {'✅ 全部通过' if result['passed'] else '❌ 存在失败'}")
return result
if __name__ == "__main__":
# 准备一个测试场景描述(模拟"意图")
scenario = {
"module": "calculator",
"function": "divide",
"test_cases": [
{"name": "normal_division", "input": "10, 2", "expected": "5.0"},
{"name": "negative_division", "input": "-10, 2", "expected": "-5.0"},
{"name": "divide_by_zero", "input": "10, 0", "expected": None, "raises": "ValueError"},
{"name": "zero_divided", "input": "0, 5", "expected": "0.0"},
]
}
# 保存场景文件
with open("scenario.json", "w") as f:
json.dump(scenario, f, indent=2)
# 运行Agent
agent = MinimalTestAgent()
agent.run("scenario.json")
运行一下:
bash
python minimal_agent_runner.py
输出:
Step 1: 加载测试场景...
Step 2: 生成Pytest测试代码...
已生成: ./agent_workspace/test_generated.py
Step 3: 执行Pytest...
============================= test session starts ==============================
collected 4 items
test_generated.py::TestDivide::test_normal_division PASSED
test_generated.py::TestDivide::test_negative_division PASSED
test_generated.py::TestDivide::test_divide_by_zero PASSED
test_generated.py::TestDivide::test_zero_divided PASSED
============================= 4 passed in 0.02s ===============================
Step 4: 测试结果
✅ 全部通过
这30行代码做了下面4个事情:
- 加载场景(模拟意图理解): 输入是JSON格式的"我要测什么"
- 生成代码(模拟用例生成):输出是Pytest测试用例文件
- 执行Pytest(模拟执行收集): 运行生成的用例,收集测试结果
- 输出结果(模拟分析反馈):查看测试结果是通过还是失败
五、总结
在日常的测试工作中,我们要把AI Agent当作提效的工具来用,如下表总结:
| 模块 | 做什么 | 谁来做 |
|---|---|---|
| 意图理解 | 需求→测试策略 | LLM |
| 用例生成 | 测试策略→Pytest代码 | LLM |
| 执行收集 | 跑pytest,收结果 | Pytest |
| 分析修复 | 失败→分析→修复→重跑 | LLM + Pytest |
读完这篇文章后,Agent测试的骨架就有了,但里面的AI能力还是空的,后续我们把真正的LLM接进来,从"模拟Agent"变成"真正的AI Agent测试系统"