用 Claude 和基于属性的测试发现 Python 生态系统中的 Bug¶
原文:Finding bugs across the Python ecosystem with Claude and property-based testing
日期:2026-01-14
作者:Muhammad Maaz (MATS, Anthropic), Liam DeVoe (Northeastern University), Zac Hatfield-Dodds (Anthropic), Nicholas Carlini (Anthropic)
团队:前沿红队
论文:arXiv | GitHub | Bug 浏览
摘要¶
研究团队构建了一个 AI 智能体,通过推断代码的通用属性并应用基于属性的测试(类似模糊测试),在 NumPy、SciPy、Pandas 等顶级 Python 包中发现了真实 Bug,多个已被上游合并修复。
作者开发了一个智能体,通过推断代码的通用属性并应用基于属性的测试(类似模糊测试)来识别大型软件项目中的 Bug。该智能体在 NumPy、SciPy 和 Pandas 等顶级 Python 包中发现了 Bug。经过严格的人工验证后,Bug 正在报告给开发者,其中多个已被修复。
引言¶
基于属性的测试不是验证特定输入/输出对,而是指定代码应满足的通用不变量,然后自动搜索反例——这与 LLM 从上下文理解"什么应该成立"的能力天然契合。
文章对比了两种测试范式:
| 测试类型 | 方法 | 局限 |
|---|---|---|
| 基于示例的测试 | 开发者编写特定输入/输出对(如验证排序函数对 [2, 10, 5, 4] 返回 [2, 4, 5, 10]) | 难以覆盖边缘情况 |
| 基于属性的测试 | 开发者指定通用属性/不变量(如 "JSON 反序列化是序列化的逆操作")+ 有效输入描述,框架自动搜索反例 | 需要人类洞察力来识别属性 |
这项工作在 2025 年 NeurIPS Deep Learning for Code Workshop 上发表,源自 MATS 项目。
作者聚焦于广泛发现 Bug——不仅限于安全漏洞。他们引用了一篇关于智能合约的相关博客文章,其中几乎所有漏洞都是逻辑 Bug。
验证流程¶
验证过程刻意严格:
1. 选择最高优先级 Bug 进行审查
2. 发送给三位专家人工审查员(平均每个 Bug 一小时)
3. 任何审查员不确定的 Bug 被丢弃
4. 作者自身再手动审查剩余候选
5. 仅对有信心的 Bug 向维护者提交
代码示例¶
# 基于示例的测试
def test_sort():
assert my_sort([1,3,2]) == [1,2,3]
assert my_sort([1,0,-5]) == [-5,0,1]
# 基于属性的测试(使用 Hypothesis)
from hypothesis import given, strategies as st
@given(st.lists(st.integers()))
def test_sort(lst):
result = my_sort(lst)
for i in range(len(result)-1):
assert result[i] <= result[i+1]
两种测试代码的方式。基于示例的单元测试验证特定的手动指定输入。
基于属性的测试智能体¶

智能体的工作流程。
智能体作为自定义 Claude Code 命令构建,采用"阅读-推断属性-编写测试-运行反思"的循环,通过自我反思降低误报率。
智能体接受指向目标(Python 文件、模块或函数)的单一参数。流程如下:
- 阅读并理解目标——阅读代码、文档、探索与代码库的关系
- 提出属性——基于发现的信息
- 编写基于属性的测试——使用 Hypothesis 框架
- 运行测试并反思——判断失败是真实 Bug 还是测试需要调整;检查通过的测试是否非平凡
- 编写格式化 Bug 报告——当确信发现真实 Bug 时
智能体使用待办清单进行长程多步推理。核心设计优先级是通过自我反思循环和将属性锚定在文档中来减少误报。
示例运行¶
文章展示了一段经编辑的转录,其中 Claude 识别了 numpy.random.wald 中的一个 Bug——该函数有时返回负数,这违反了 Wald 分布的性质。实际修复追踪到灾难性抵消问题,并开发了更数值稳定的公式。参见已合并修复。
评估¶
统计数据¶
| 指标 | 数值 |
|---|---|
| 测试的热门 Python 包数量 | 超过 100 个 |
| 覆盖领域 | 数值计算、解析、数据库等 |
| 生成的 Bug 报告总数 | 984 份 |
| 50份手动审查报告中的有效 Bug 率 | 56% |
| 有效且可报告率 | 32% |
| 高分报告(经排名评分)的有效率 | 86% |
| 高分报告中有效且可报告率 | 81% |
两阶段评估¶
| 阶段 | 模型 | 方法 |
|---|---|---|
| 第一阶段 | Claude Opus 4.1 | 对每个包运行智能体;手动审查 50 份报告;开发排名标准 |
| 第二阶段 | Sonnet 4.5 | 对 10 个重要包运行(每个多次);更复杂的评估智能体;3 位专家人工审查员 |
作者注意到"Opus 4.1 和 Sonnet 4.5 的自我反思能力相比 Sonnet 4 有显著提升。"
已验证的 Bug¶
numpy — numpy.random.wald 返回负数¶
| 项目 | 详情 |
|---|---|
| 问题 | Wald 分布采样应只产生正数 |
| 根因 | 代码中的灾难性抵消 |
| 修复效果 | 新公式相对误差"比之前算法低近十个数量级" |
| 状态 | 已合并: numpy/numpy#29609 |
aws-lambda-powertools — slice_dictionary() 重复返回第一个分片¶
| 项目 | 详情 |
|---|---|
| 问题 | 未递增迭代器 |
| 检测方法 | 测试分片后重组应返回原始字典 |
| 状态 | 已合并: powertools-lambda-python#7246 |
cloudformation-cli-java-plugin — item_hash() 对所有列表产生相同哈希¶
| 项目 | 详情 |
|---|---|
| 问题 | 使用了返回 None 的 .sort() 就地方法 |
| 检测方法 | 测试不同输入的哈希应不同 |
| 状态 | 已提交: cloudformation-cli#1106 |
tokenizers — EncodingVisualizer.calculate_label_colors() 缺少闭括号¶
| 项目 | 详情 |
|---|---|
| 问题 | 返回无效的 HSL CSS |
| 检测方法 | 对输出进行 HSL 颜色代码正则匹配 |
| 状态 | 已合并: tokenizers#1853 |
python-dateutil — easter() 在某些儒略历年份返回非周日¶
| 项目 | 详情 |
|---|---|
| 问题 | 维护者确认为预期行为(不同历法系统) |
| 状态 | 无效: dateutil#1437 |
python-dateutil 案例说明了一个局限:"从具有微妙或复杂语义的代码中推导属性仍然很困难。"
结论¶
LLM "特别擅长从上下文中识别代码块_应该_为真的属性"——基于属性的测试的高层语义保证使其成为与 LLM 配对的天然选择。
核心要点:
- LLM "特别擅长从上下文中识别关于给定代码块应该为真的属性"
- 基于属性的测试的高层语义保证使其成为与 LLM 配对的天然选择
- 将 LLM 应用于测试和 Bug 发现是一个重要的研究方向
- 未来工作包括自动补丁生成——如果正确性属性能被完全指定,"纠正 Bug 就变得显著更容易"