创建生成不重复整数的Hypothesis策略报错,求解决方案
Hypothesis自定义唯一整数策略报错修复
问题代码
尝试创建生成不重复整数的Hypothesis策略时编写的代码:
import hypothesis import hypothesis.strategies as strategies def unique(strat): previous = set() @strategies.composite def new_strategy(draw): while True: value = draw(strat) if value not in previous: previous.add(value) return value return new_strategy strategy = unique(strategies.integers(min_value=0, max_value=1000)) @hypothesis.given(num=strategy) def test_unique(num): pass
报错信息
运行pytest时触发的错误:
@check_function def check_strategy(arg, name="") if not isinstance(arg, SearchStrategy): hint = "" if isinstance(arg, (list, tuple)): hint = ", such as st.sampled_from({}),".format(name or "...") if name: name += "=" raise InvalidArgument( "Expected a SearchStrategy%s but got %s%r (type=%s)" % (hint, name, arg, type(arg).__name__) ) E hypothesis.errors.InvalidArgument: Expected a SearchStrategy but got mapping['num']=<function accept.<locals>.new_strategy at 0x7f30622418b0> (type=function)
错误原因
- 策略类型错误:
@strategies.composite装饰的函数是一个策略工厂,必须调用它才能生成SearchStrategy实例。原代码直接返回了工厂函数,而非实例化后的策略对象。 - 状态共享风险:
previous集合定义在unique函数闭包中,会被所有测试用例共享,当所有整数都被取过一次后,后续测试会进入死循环。
修复方案
修正后的代码如下:
import hypothesis import hypothesis.strategies as strategies def unique(strat): @strategies.composite def new_strategy(draw): # 使用shared创建测试内共享的集合,每个测试用例拥有独立实例 previous = draw(strategies.shared(strategies.just(set()), key="unique_integers")) while True: value = draw(strat) if value not in previous: previous.add(value) return value # 调用工厂函数,返回真正的SearchStrategy实例 return new_strategy() strategy = unique(strategies.integers(min_value=0, max_value=1000)) @hypothesis.given(num=strategy) def test_unique(num): pass
关键修复点
- 将
return new_strategy改为return new_strategy():确保返回的是Hypothesis要求的SearchStrategy实例,而非工厂函数。 - 用
strategies.shared管理唯一集合:每个测试用例运行时会初始化独立的集合,既保证单个测试内生成的整数不重复,又避免不同测试之间的状态污染。
内容的提问来源于stack exchange,提问作者Daniel Walker
相关产品推荐
相关产品推荐

