AI Agent 改完代码后,回归测试用于确认:这次修改满足新要求的同时,已有的关键行为仍然符合约定。 新增搜索功能能够找到结果,还需要检查原有筛选、默认参数、排序和数据处理是否保持正常。

IBM 对回归测试的介绍强调了代码修改后检查已有功能的目的。把这个原则用于 AI 辅助开发,重点是建立可重复的验证依据,而不是依赖 Agent 的“已修复”说明。

本文主要讨论编码 Agent 修改软件后的验证流程,后半部分再讨论 Agent 本身作为被测应用 的情况。Python 示例为作者编写的本地教学案例,没有运行真实模型,也不代表某个商业 Agent 的检出能力或真实项目事故。资料核对日期为 2026 年 11 月 3 日。

回归测试、缺陷复测与测试层次

一次修改通常需要回答两类问题:原来的缺陷是否已经修复,以及与它有关的既有行为是否受到影响。二者都重要,覆盖范围却不相同。

验证目的 关注的问题 列表筛选示例
缺陷复测 原先失败的条件是否恢复正确 停用状态筛选是否只返回停用项
回归测试 修改后,已有约定是否仍成立 默认查询、启用筛选、顺序和输入数据是否保持正常
新功能测试 新要求是否实现 关键词搜索及与状态筛选的组合是否正确

这些目的可能由同一组测试共同覆盖,不必为每个概念复制一套相同用例。一个缺陷修复后的测试,也可以长期保留为回归用例。

“回归”说明为什么测试;单元、集成、端到端说明测试覆盖的层次;手动与自动化说明如何执行。一个端到端用例可以承担回归验证,单元测试也可以保护原有接口。IBM 的文章涉及多种方法,实际选择应结合变更影响、风险与执行成本,不需要每次更新都套用全部分类。

Agent 修改代码时需要保护哪些约定

编码 Agent 可以阅读实现、生成补丁、补充测试并调用工具。但它仍可能漏掉调用方依赖的隐含条件,尤其是默认值、空值、布尔值、兼容字段和异常路径。

例如,需求是“给任务列表增加关键词搜索”,原有行为包括:

  • enabled=None 不按状态筛选。
  • enabled=True 只返回启用项,enabled=False 只返回停用项。
  • 未填写关键词时,保持原有查询结果和顺序。
  • 查询不修改传入的数据。

如果验收只检查“输入 Alpha 后能搜到任务”,便可能漏掉 False 筛选失效的问题。测试依据应来自需求、公共接口和已确认的行为;旧版本中的已知缺陷不应该因为“以前就是这样”而被固定成正确答案。

Google Testing Blog 关于行为测试的文章建议主要围绕公共接口验证行为,让测试不依赖经常变化的实现细节。对 Agent 编写的补丁,同样应检查业务结果,而不只是验证某个辅助函数是否被调用。

布尔筛选的回归测试示例

这个例子只处理内存中的虚构任务。参数范围限定为 enabled 取 None、True 或 False,keyword 为字符串,不展开完整接口的输入校验。

新增搜索时,一种可能的错误是把条件写成:

1
2
if enabled:
result = [task for task in result if task["enabled"] is enabled]

False 和 None 都不会进入这段分支,但它们在约定中代表不同含义。只测试 enabled=True 就发现不了这个问题。

在独立示例目录中创建修正后的 example.py。空关键词不筛选名称,非空关键词忽略大小写,返回结果沿用输入顺序:

1
2
3
4
5
6
7
8
def select_tasks(tasks, *, enabled=None, keyword=""):
result = tasks
if enabled is not None:
result = [task for task in result if task["enabled"] is enabled]
if keyword:
needle = keyword.casefold()
result = [task for task in result if needle in task["name"].casefold()]
return [task["id"] for task in result]

将以下内容保存为同一目录中的 test_example.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from copy import deepcopy
import unittest
from example import select_tasks

TASKS = [
{"id": "t1", "name": "Alpha", "enabled": True},
{"id": "t2", "name": "Alpha backup", "enabled": False},
{"id": "t3", "name": "Beta", "enabled": True},
]

class SelectTasksTests(unittest.TestCase):
def test_filter_combinations(self):
cases = [
(None, "", ["t1", "t2", "t3"]),
(True, "", ["t1", "t3"]),
(False, "", ["t2"]),
(None, "ALPHA", ["t1", "t2"]),
(False, "alpha", ["t2"]),
(True, "beta", ["t3"]),
(False, "beta", []),
(None, "missing", []),
]
for enabled, keyword, expected in cases:
with self.subTest(enabled=enabled, keyword=keyword):
self.assertEqual(
select_tasks(deepcopy(TASKS), enabled=enabled, keyword=keyword),
expected,
)

def test_does_not_modify_input(self):
tasks = deepcopy(TASKS)
before = deepcopy(tasks)
select_tasks(tasks, enabled=False, keyword="alpha")
self.assertEqual(tasks, before)

if __name__ == "__main__":
unittest.main()

在这两个文件所在目录运行:

1
python -m unittest -v

示例只使用 Python 标准库。subTest 把不同参数组合单独标记,某个组合失败时能够定位相应条件;其行为见 Python unittest 文档。这里有两个测试方法,其中一个包含多组子测试,不能把方法数量直接当作覆盖范围。

作者在隔离临时目录中核对了三个版本:新增关键词之前的基线、刻意使用 if enabled: 的错误版本,以及上面的修正版本。原有筛选用例在基线中通过,在错误版本中能够暴露 False 的退化;修正后,原有约定和新增组合均通过。错误版本是人工构造的演示,不是某个 Agent 的实际输出。

这些结果只验证列出的输入组合和输入不被修改的约定,没有验证界面、数据库、并发或真实模型行为。为更大的应用增加回归覆盖时,需要继续沿调用链选择测试。

False筛选退化的旧约定、错误条件、修正和验证范围

图1:作者原创教学示意,对应上面的虚构任务案例;不是Agent实际输出或运行截图。

按变更影响选择回归范围

回归范围应由依赖关系和风险决定,不能只按修改了几行代码来判断。共享解析函数的一行改动,可能同时影响导入、导出和界面展示。

修改位置 适合优先检查的行为 可能需要补充的验证
筛选、排序或参数转换 默认值、空结果、边界与旧调用方式 组合条件和调用方集成
配置或数据格式 旧格式读取、保存后重读、失败时的数据保留 迁移与恢复路径
界面和浏览器交互 可见状态、按钮操作、错误提示 不同窗口尺寸、主题与真实交互路径
后台任务与资源管理 启动、取消、完成和重复执行 监听器、线程、连接及退出清理
模型、提示词或工具定义 既有任务能否继续完成 工具参数、权限边界、最终状态与质量评估

这张表是选测建议,不是已经在某个项目上执行的测试清单。局部纯函数可以从快速用例开始;涉及共享接口、数据迁移或核心流程时,再扩大到集成与关键端到端路径。发布前还需要符合项目约定的完整检查。

界面回归应验证用户实际看到和操作的结果。Playwright 的最佳实践强调用户可见行为、测试隔离与稳定定位。针对界面布局的改动,仅通过一个纯函数测试,不能证明按钮可点击或窄屏内容没有被遮挡。

测试失败时核对原因与基线

修改前运行相关测试,可以帮助区分已有失败与本次回归。已经完成修改时,也可以在独立工作目录中检查变更起点,保留当前现场;不应为了制造干净基线而丢弃未提交内容。

失败需要结合证据分类:

  • 预期未变,结果改变:检查实现或调用关系是否退化。
  • 需求明确改变:依据批准后的新约定修改测试,同时评估兼容影响。
  • 测试绑定实现细节:调整不再适用的设置或断言,但继续保护真实行为。
  • 结果偶发变化:检查共享状态、执行顺序、清理、网络依赖,也排查产品中的竞态。

pytest 的不稳定测试说明列出了系统状态未受控、隔离不足及断言过严等原因。偶发失败不应自动归咎于环境,也不能靠重复运行到通过一次就宣告修复。

Agent 同时修改实现和测试时,需要检查断言差异。删除失败用例、放宽阈值或让预期值跟着错误实现变化,都会削弱原有保障。合理调整测试当然可以进行,但应能解释行为约定为什么改变,并留下相应依据。

Agent 本身需要额外的行为评估

如果应用本身包含 Agent,仅保护外围 Python 函数还不够。模型、提示词、工具描述或编排方式变化,都可能影响同一任务的完成方式。

Anthropic 对 Agent 评估的介绍区分任务、单次尝试、执行记录和最终结果,也区分能力探索与回归评估。对已能处理的任务保留回归集,有助于发现新版本的退化;这不意味着所有 Agent 都使用同一阈值。

以下为作者建议的检查对象,需按实际应用定义成功条件:

检查对象 可验证的结果示例
工具选择与参数 使用适合当前任务的工具,必填字段与目标对象正确
权限边界 只读任务没有发起写入调用,相关业务状态保持不变
错误处理 工具超时后按约定停止或有限重试,没有假报成功
最终状态 需要生成的文件或记录确实存在,内容符合约定
回答质量 事实有依据,完整性与表达满足明确的评价标准

“任务已完成”这句回复不能替代文件、数据库或工具执行结果。相反,也不必要求每次尝试采用完全相同的工具顺序:只有业务确实依赖的顺序才应作为硬约束。

对于能够明确判定的结果,优先使用代码和状态断言;对开放式回答,可以结合清晰的评分标准、模型评审与人工抽查。模型评审也需要校准,不能让一个平均质量分掩盖越权调用等硬性失败。

比较版本时,应记录代码提交、模型标识、提示词与工具定义版本、测试数据、初始状态、运行条件和评价器。对存在随机性的任务安排多次尝试,记录失败分布及具体案例;一次成功不代表持续稳定,参数相同也不保证输出逐字一致。这是评估设计建议,本文没有实际调用模型来测量通过率。

软件回归测试与Agent行为评估的对象、证据和结论范围

图2:作者原创概念示意;软件行为与Agent行为分别验证,本文未进行真实模型评测。

把回归检查接入 Agent 开发流程

一套可执行的协作流程可以按以下顺序组织:

  1. 明确新要求、需要保留的行为和不在本次范围内的内容。
  2. 记录变更基线与已有失败,为实际缺陷保留能复现它的用例。
  3. 实现最小相关修改,补齐新行为及受影响旧行为的测试。
  4. 在隔离环境中运行相关检查,按证据处理失败,再检查最终差异。
  5. 根据影响扩大必要验证;Agent应用另比较任务数据集、工具调用与最终状态。
  6. 汇报通过、失败和未覆盖范围,按项目权限决定合并或发布。

测试环境应使用脱敏样本、临时目录与受控工具。不要为了验证重试或取消行为,直接反复执行真实发布、私信、付款等外部操作;模拟工具可以验证本地控制逻辑,真实服务的行为需要另外安排验证。

LangSmith 对评估类型的说明将发布前的离线评估与生产中的在线观察分开。上线后发现的真实失败可以脱敏后加入后续回归集;生产监测也不能反过来替代发布前检查。

让 Agent 参与生成用例、分析影响和整理结果,可以减少部分重复工作,但通过率、检出率或节省时间都需要实际测量。本文引用 IBM 关于AI辅助测试的讨论作为背景,没有把它当作特定产品的效率证明。

需要把上述流程与审查、任务隔离连接起来,可以继续阅读AI Code Review与人工代码审查和什么时候创建Git任务分支。回归测试提供已验证行为的证据,合并与生产发布仍按项目约定执行。

参考资料

资料于2026年11月3日核对。IBM为用户指定的概念参考,工具官方文档用于说明相应能力;Anthropic与LangSmith资料属于其评估实践。本文流程与教学代码为作者整理,不宣称复现了这些机构的产品效果。

  1. IBM:什么是回归测试?,概念、影响分析与方法背景。
  2. Google Testing Blog:Test Behavior, Not Implementation,围绕公共行为设计测试。
  3. Python:unittest,标准库测试与子测试。
  4. Playwright:Best Practices,用户可见行为与测试隔离。
  5. pytest:Flaky tests,不稳定测试的原因与处理思路。
  6. Anthropic:Demystifying evals for AI agents,Agent评估的对象、尝试、结果与回归集。
  7. LangChain:Evaluation types,离线与在线评估的分工。