【问题标题】:Howto validate correctness of functions which use random?如何验证使用随机函数的正确性?
【发布时间】:2012-06-11 16:52:38
【问题描述】:

在一些应用程序域(例如 GameDev)中,许多函数应该使用随机值创建以产生它们的输出。以下是其中一个示例:

def generate_key(monster_key_drop_coef):
    key_letters = string.ascii_uppercase
    rand = random.random()
    if monster_key_drop_coef < rand:
        return None

    button = {}
    button["type"] = random.choice([1,2,3])
    button["letter"] = random.choice(key_letters)
    return button

这个函数根据几个随机操作生成物品的掉落。如果您想自动验证此功能的正确性,则会出现问题。生成的值不是确定性的,编写回归测试似乎是不可能的。

我的问题是:

  1. 是否可以为这种类型的代码编写有用的回归测试? 职能?
  2. 在这种情况下,是否有任何通用方法可以创建其他类型的测试?

【问题讨论】:

  • 关于这个主题的书籍有很多。示例:johndcook.com/Beautiful_Testing_ch10.pdf
  • 模拟 RNG 以提供已知结果(然后使用已知期望结果的特定输出进行测试)是一种方法。

标签: python testing random regression-testing


【解决方案1】:

下面介绍了一个有用的单元测试:

def test_generate_key():
    button_list = []
    for _ in range(1, 1000):
        button_list.append(generate_key(0.2))

    is_all_none = True
    is_not_none = False
    for key in button_list:
        is_all_none &= (key is None)
        is_not_none |= (key is not None)

    assert is_all_none == False
    assert is_not_none == True

它验证函数签名,覆盖函数代码的所有行(很有可能)并且在 99.999% 的情况下会通过。还验证了该函数从 1000 中产生至少一个下降,有时不会产生下降。 0.2 是物品掉落的概率。

【讨论】:

    【解决方案2】:

    我会重写函数以使用依赖注入(随机数生成器作为参数传递给函数)。然后,您可以传递一个随机数生成器的模拟,以使用不同的确定性“随机”输入来测试您的函数。

    当然,您也可以测试不依赖于随机调用结果的断言。如:

    • 函数返回 None 或带有键“type”和“letter”的 dict。
    • 如果返回字典,则值的类型和范围都合适。

    我永远不会编写具有不确定结果的单元测试,即使是千分之一。我关心每一次测试失败,随机结果会令人不安。你最好封装你的随机性,这样函数就可以独立于随机数生成器进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多