Hypothesis text策略示例分布异常:仅生成全A字符串无全B/C串
Hypothesis策略生成全A字符串频繁出现的原因解析
问题现象
调试Hypothesis自定义策略时,简化代码批量生成固定长度范围的大写字符串,发现全A字符串(如10个A)频繁出现,但从未生成全B或全C的字符串。并非要求分布均匀,但疑惑为何同类型的全字符串只有全A出现。
代码示例
注意:原代码遗漏import string,修正后如下:
import hypothesis.strategies as st import string for _ in range(100): print(st.text(alphabet=string.ascii_uppercase, min_size=10, max_size=100).example())
输出示例
MSENIKYFHSVKUUHETHVZYOTGNMRIUTEWZRSGQVIEBND NJWVCUWGDYN NHYHLZWUQBXXAFD IAIIDKHKNPLEEY BUIIFNVBQTMSRQVDU ARUBTLBBWKYXZTYJXJLRMIVTSUOJOPYVWOKBUMLQXOTQ PCUJMVOKEYZ AAAAAAAAAA IXNEZSRJEGDQBCXKUIZRSZCPBHMYYPPJ BURNHKZDYP FSAAKFESBOUA QTSQYSCDLCREWKBH AAAAAAAAAA ...
原因分析
1. example()方法的设计定位
example()并非用来生成随机样本,它是Hypothesis提供的快速验证工具,目的是返回一个能代表策略规则的"典型例子",而非遍历所有可能的边界或特殊情况。
2. 偏向"简单用例"的生成逻辑
Hypothesis在生成example()时,会优先选择结构简单的测试用例——全A字符串属于这类:重复单一字符、使用字母表首字符,符合Hypothesis对"简单"的定义。而全B/C虽然也是同类型用例,但example()不会主动遍历所有这类情况,只会快速返回一个符合要求的简单示例。
3. 缓存机制
多次调用example()时,Hypothesis会缓存之前生成的结果,这也是全A字符串频繁重复出现的原因之一。
4. 基础使用错误
原代码存在两个问题:
- 遗漏
import string,导致运行报错; - 用
example()批量生成样本是错误的用法,它不适合做批量随机生成。
正确的批量生成方式
如果需要生成随机分布的样本,应该使用generate()方法,或者结合Hypothesis的@given装饰器(更符合Hypothesis的测试场景):
方式1:使用generate()
import hypothesis.strategies as st import string # 先定义策略 strat = st.text(alphabet=string.ascii_uppercase, min_size=10, max_size=100) for _ in range(100): # 调用generate()生成随机样本 print(strat.generate())
方式2:使用@given装饰器(推荐用于测试场景)
import hypothesis.strategies as st import string from hypothesis import given, settings # 关闭"过慢"健康检查(因为打印会拖慢速度) @settings(suppress_health_check=["too_slow"]) @given(st.text(alphabet=string.ascii_uppercase, min_size=10, max_size=100)) def print_random_strings(s): print(s) # 执行函数生成样本 print_random_strings()
使用上述方式生成样本时,你会看到全B、全C等单一字符的字符串正常出现,样本分布更符合预期。
总结
example()是辅助验证工具,不是随机生成器,不能用来批量获取样本;- Hypothesis生成"简单用例"的逻辑导致全A字符串优先被返回,且缓存机制会让它重复出现;
- 批量生成随机样本请用
generate()或@given装饰器。
内容的提问来源于stack exchange,提问作者kasterma
相关产品推荐
相关产品推荐

