如何创建Hypothesis策略在指定范围内实现均匀采样?
问题与解决方案
问题背景
你编写了如下测试代码:
test_a.py
import unittest import hypothesis import hypothesis.extra.numpy import numpy as np from hypothesis import strategies as st SHAPE = (10, ) ARRAY_STRATEGY = hypothesis.extra.numpy.arrays(float, SHAPE, elements=st.floats(min_value=-1, max_value=1)) ZERO_ONE_STRATEGY = st.floats(min_value=0, max_value=1) class TestMyClass(unittest.TestCase): @hypothesis.settings(max_examples=10) @hypothesis.given( value=ZERO_ONE_STRATEGY, arr1=ARRAY_STRATEGY, arr2=ARRAY_STRATEGY, arr3=ARRAY_STRATEGY, ) def test_something(self, value: float, arr1: np.ndarray, arr2: np.ndarray, arr3: np.ndarray) -> None: print(value)
执行测试时,输出全是0.0:
$ pytest test_a.py --capture=no 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
你需要让value以1/(max_examples-1)的粒度在0到1范围内均匀采样,而非随机采样。
解决方法
直接生成固定的均匀分布数值列表,用st.sampled_from创建策略,确保每次测试取到不同的均匀分布值。具体修改如下:
- 定义测试次数常量
MAX_EXAMPLES,和装饰器中的参数保持一致; - 计算采样粒度
step = 1 / (MAX_EXAMPLES - 1); - 生成从0到1的均匀数值列表;
- 用
st.sampled_from包装这个列表作为value的策略。
修改后的完整代码:
import unittest import hypothesis import hypothesis.extra.numpy import numpy as np from hypothesis import strategies as st SHAPE = (10, ) MAX_EXAMPLES = 10 # 和settings中的max_examples保持一致 ARRAY_STRATEGY = hypothesis.extra.numpy.arrays(float, SHAPE, elements=st.floats(min_value=-1, max_value=1)) # 生成均匀分布的数值列表:0.0, 1/9, 2/9, ..., 1.0 step = 1 / (MAX_EXAMPLES - 1) ZERO_ONE_STRATEGY = st.sampled_from([i * step for i in range(MAX_EXAMPLES)]) class TestMyClass(unittest.TestCase): @hypothesis.settings(max_examples=MAX_EXAMPLES) @hypothesis.given( value=ZERO_ONE_STRATEGY, arr1=ARRAY_STRATEGY, arr2=ARRAY_STRATEGY, arr3=ARRAY_STRATEGY, ) def test_something(self, value: float, arr1: np.ndarray, arr2: np.ndarray, arr3: np.ndarray) -> None: print(value)
执行测试时,value会依次输出0.0, 0.111..., 0.222..., ..., 1.0,完全覆盖0到1的范围,且粒度符合要求。
补充说明
原策略st.floats(min_value=0, max_value=1)默认会优先生成边界值(如0.0、1.0),测试次数较少时容易出现重复采样的情况。而st.sampled_from会严格遍历你提供的所有数值,确保均匀覆盖。
内容的提问来源于stack exchange,提问作者ringo
相关产品推荐
相关产品推荐

