【问题标题】:Hypothesis equivalent of QuickCheck frequency generator?假设等效于 QuickCheck 频率发生器?
【发布时间】:2019-08-14 11:03:08
【问题描述】:

作为一个学习项目,我正在将一些 Haskell 代码(我不熟悉)翻译成 Python(我很熟悉)...

我正在翻译的 Haskell 库具有使用 QuickCheck 基于属性的测试的测试。在 Python 方面,我使用 Hypothesis 作为基于属性的测试库。

Haskell 测试使用如下所示的辅助函数:

mkIndent' :: String -> Int -> Gen String
mkIndent' val size = concat <$> sequence [indent, sym, trailing]
  where
    whitespace_char = elements " \t"
    trailing = listOf whitespace_char
    indent = frequency [(5, vectorOf size whitespace_char), (1, listOf whitespace_char)]
    sym = return val

我的问题是关于这个助手中的frequency 生成器。 http://hackage.haskell.org/package/QuickCheck-2.12.6.1/docs/Test-QuickCheck-Gen.html#v:frequency

我理解它的意思是大部分时间它将返回 vectorOf whitespace_char 和预期的 size,但五分之一的返回 listOf whitespace_char 可能是任何长度,包括零。

在库的上下文中,不尊重size 的缩进将为被测函数建模错误的输入数据。所以我看到了偶尔产生这种输入的意义。

我目前不明白的是,为什么 5:1 的比例有利于有效输入?我本来希望基于属性的测试框架生成各种有效和无效的输入。现在我假设这有点像优化,所以它不会花费大部分时间来生成无效示例?

我的问题的第二部分是如何将其转化为假设。 AFAICT 假设没有任何等价的 frequency 生成器。

我想知道我是否应该尝试从现有的假设策略中自己构建一个frequency 策略,或者如果习语本身不值得翻译,我应该让框架生成类似的有效和无效示例?

我目前拥有的是:

from hypothesis import strategies as st

@st.composite
def make_indent_(draw, val, size):
    """
    Indent `val` by `size` using either space or tab.
    Will sometimes randomly ignore `size` param.
    """
    whitespace_char = st.text(' \t', min_size=1, max_size=1)
    trailing = draw(st.text(draw(whitespace_char)))
    indent = draw(st.one_of(
        st.text(draw(whitespace_char), min_size=size, max_size=size),
        st.text(draw(whitespace_char)),
    ))
    return ''.join([indent, val, trailing])

如果我在 shell 中生成一些示例,这似乎完全符合我的想法。

但这是我第一次使用假设或基于属性的测试,我想知道通过用简单的 one_of 替换 frequency 分发是否会丢失一些重要的东西?

【问题讨论】:

    标签: python haskell quickcheck property-based-testing python-hypothesis


    【解决方案1】:

    据我所知,您已经正确理解了在这里使用frequency 的目的。它用于允许偶尔出现大小错误的缩进,而不是(1)只生成大小正确的缩进,而不会测试错误的缩进大小;或 (2) 生成随机大小的缩进,它会一遍又一遍地测试不良缩进,但只会生成一小部分具有良好缩进的案例来测试代码的其他方面。

    现在,5:1 的好与(可能)坏缩进大小的比例可能是相当随意的,如果没有看到正在测试的细节,很难知道 1:1 还是 10:1 会是更好的选择.

    幸运的是,关于将其移植到 hypothesisHave a Strategy that does not uniformly choose between different strategies 的答案包括一条已删除的评论:

    假设实际上并不支持特定于用户的概率 - 我们从均匀分布开始,但会根据观察到的输入的覆盖范围对其进行偏差。 [...] – Zac Hatfield-Dodds 2018 年 4 月 15 日 3:43

    这表明“假设”包在使用one_of 以增加覆盖率时会自动调整权重,这意味着它可能会在您的make_indent_ 实现中自动增加具有正确大小的案例的权重,使其成为一种自动版本frequency.

    【讨论】:

    • 我们实际上最终删除了覆盖特性,因为它们对单元测试规模来说是一个净负面因素(尽管非常适合使用其他工具进行多日模糊测试),但保留了各种启发式方法。不过,这并没有改变我们的基本建议:在 one_of 中首先放置更简单的策略,然后让 Hypothesis 计算分布。
    猜你喜欢
    • 1970-01-01
    • 2019-03-31
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多