一、🧠 原理概述
Hypothesis 的核心由两部分组成:
1. 策略(strategies)定义"什么样"的数据
你用 hypothesis.strategies
定义数据类型,比如:
java
@given(st.integers())
这表示 "任意整数"。
你可以定制规则,比如:
ini
st.integers(min_value=0, max_value=1000)
st.lists(st.text(), min_size=1, max_size=5)
st.dictionaries(st.text(), st.integers())
这些叫做 策略对象(strategy),它描述了数据的"分布空间"。
2. 生成器 + 假设驱动搜索 + Shrinking 缩减失败案例
Hypothesis 不是瞎生成数据,而是采用类似搜索和优化的思路:
✅ 自动生成数据 + 路径覆盖
- 它尝试生成多种数据组合:小的、大的、负数、空值、重复项、特殊字符、边界条件等
- 会特别尝试边界值、极端情况、稀有值
❌ 发现失败 → 自动"缩减"成最小反例
- 一旦测试失败,Hypothesis 会尝试找出 最简单能重现错误的输入(称为 shrinking)
举例:
python
@given(st.lists(st.integers()))
def test_sum_non_negative(xs):
assert sum(xs) >= 0
错误的假设:和永远非负
Hypothesis 可能生成 [1, 2, -100]
导致失败,但它最终会缩减 成 [-1]
或 [-2]
,报告最小反例,便于你 debug。
📦 数据生成机制举个例子
以 st.text()
为例,它内部其实做了:
markdown
1. 生成字符串长度(可能是0、1、2、1000等)
2. 生成字符(可能是ASCII、emoji、控制字符、换行等)
3. 随机拼接形成字符串
同样,st.floats()
会生成:
- 正数、负数、0.0、-0.0
- 无穷大
inf
、-inf
NaN
- 边界值,如
1e-308
,1e308
等
你甚至可以明确要求排除某些值:
ini
st.floats(allow_nan=False, allow_infinity=False)
二、🧪 入门组合:pytest + Hypothesis
我们从基础到进阶带你入门:
✅ 1. 安装
pip install pytest hypothesis
✅ 2. 用 pytest 写基本测试
python
# test_math.py
def add(x, y):
return x + y
def test_add():
assert add(1, 2) == 3
运行测试:
pytest
✅ 3. 引入 Hypothesis 做"自动化输入测试"
python
from hypothesis import given
import hypothesis.strategies as st
def add(x, y):
return x + y
@given(st.integers(), st.integers())
def test_add_commutative(x, y):
assert add(x, y) == add(y, x)
🧠 解读:
@given(st.integers(), st.integers())
会自动生成很多组整数 (x, y)- 然后 pytest 会反复运行
test_add_commutative(x, y)
来测试这个性质是否成立 - 这是"属性测试":不是测试特定输入,而是测试一个通用规律/属性
✅ 4. 再举一个进阶例子:字符串逆转
python
@given(st.text())
def test_reverse_twice(s):
assert s == s[::-1][::-1]
解释: 任何字符串 s
,反转两次应该和原来一样。
Hypothesis 会生成各种字符串(包括空的、emoji、换行、乱码等),帮你找 bug!
✅ 5. 缩减失败输入(最强大功能之一)
比如你写了这个错误的函数:
python
def is_palindrome(s):
return s == s[::-1] and len(s) > 1
@given(st.text())
def test_palindrome_reverse(s):
assert is_palindrome(s) == (s == s[::-1])
一旦出错,Hypothesis 会自动缩减出最简单的反例 (比如 ''
),帮你快速定位 bug。
✅ 6. 常用策略(strategies)示例
类型 | 示例 |
---|---|
整数 | st.integers(min_value=0, max_value=100) |
浮点 | st.floats(allow_nan=False) |
字符串 | st.text() |
列表 | st.lists(st.integers()) |
字典 | st.dictionaries(st.text(), st.integers()) |
布尔值 | st.booleans() |
你也可以组合它们构造复杂的数据结构。
📦 推荐项目结构
my_project/
├── my_module.py
├── test_my_module.py ← 用 pytest + Hypothesis 写测试
用命令运行所有测试:
pytest
🚀 入门小任务建议
你可以试着写几个函数,并用 pytest + Hypothesis 验证它们:
is_even(n)
:是否是偶数reverse(s)
:反转字符串sort_list(lst)
:排序后是否不减少元素divide(x, y)
:注意 y=0 的情况
练习答案如果可以大家可以分享在评论区
GitHub:github.com/HypothesisW...