如何对带有条件的概率分布进行单元测试?函数拆分方案探讨
验证拆分后的均匀概率分布方案
这个拆分思路太赞了!把非确定性逻辑和业务逻辑(生成分布)彻底分离,确实是测试这类随机函数的最佳实践之一。针对你要确定性验证均匀分布的需求,我给你梳理几个具体的实现和测试步骤:
1. 先明确generate_choices的输出规范
既然目标是均匀分布,那generate_choices(elems)的输出结构得清晰可验证。比如:
- 如果用字典格式:对于输入
["a", "b", "c"],应该返回{"a": 1/3, "b": 1/3, "c": 1/3} - 如果用索引权重数组:返回
[1/3, 1/3, 1/3]
只要结构能被后续的choose函数正确识别就行,核心是每个元素的概率完全相等。
2. 编写纯确定性的分布验证测试
这一步完全不需要碰rand(),直接对generate_choices的输出做断言,确保它符合均匀分布的要求:
def test_generate_uniform_distribution(): # 测试普通多元素场景 elems = ["apple", "banana", "cherry"] dist = generate_choices(elems) # 验证总概率和为1(容忍极小浮点误差) total_prob = sum(dist.values()) assert abs(total_prob - 1.0) < 1e-9 # 验证每个元素的概率等于1/元素数量 expected_prob = 1.0 / len(elems) for elem, prob in dist.items(): assert abs(prob - expected_prob) < 1e-9 # 测试边界场景:单元素列表 single_elem = ["test"] single_dist = generate_choices(single_elem) assert single_dist["test"] == 1.0 # 测试空列表(根据你的需求,这里可以断言抛出异常或返回空结构) try: generate_choices([]) assert False, "Empty list should raise an error" except ValueError: pass
用浮点误差容忍是因为像1/3这样的分数在二进制浮点数里是无限循环的,直接相等判断会失败。
3. 可选:给choose函数做确定性验证
虽然choose是rand()的轻量包装,但可以通过固定随机种子来让它的输出可预测,从而验证抽样逻辑的正确性:
import random def test_choose_deterministic(): dist = {"heads": 0.5, "tails": 0.5} # 固定随机种子,让rand()的输出完全可预测 random.seed(123) # 第一次调用会得到确定的结果(根据你的抽样实现,这里假设是heads) assert choose(dist) == "heads" # 重置种子后,再次调用应该得到相同结果 random.seed(123) assert choose(dist) == "heads"
这样既验证了choose的抽样逻辑符合分布要求,又保持了测试的确定性。
4. 别忘了特殊场景测试
如果你的业务允许输入有重复元素(比如[1,1,2]),要提前明确均匀分布的定义:是每个位置等概率,还是每个唯一元素等概率?比如前者的话,1的总概率应该是2/3,后者则是1/2。根据需求补充对应的测试用例即可。
内容的提问来源于stack exchange,提问作者sshine
相关产品推荐
相关产品推荐

