假设相当于QuickCheck频率发生器?

问题描述 投票:3回答:1

作为一个学习项目,我正在将一些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,但在5次中它将返回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中生成一些示例,这似乎正在做我认为应该做的事情。

但这是我第一次使用假设或基于属性的测试,我想知道我是否因为用简单的frequency替换one_of发行版而失去了一些重要的东西?

python haskell quickcheck property-based-testing python-hypothesis
1个回答
4
投票

据我所知,你已正确理解在这里使用frequency的目的。它用于允许偶尔错误大小的缩进而不是(1)只生成正确大小的缩进,这些缩进永远不会测试不良缩进大小;或者(2)生成随机大小的缩进,这些缩进将反复测试不良缩进,但只产生一小部分具有良好缩进的情况以测试代码的其他方面。

现在,好的和(可能)坏的缩进尺寸的5:1比例可能是非常随意的,并且很难知道1:1或10:1是否是更好的选择而没有看到正在测试的细节。

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

假设实际上并不支持用户特定的概率 - 我们从均匀分布开始,但是基于观察到的输入的覆盖范围来偏置它。 [...] - Zac Hatfield-Dodds 18年4月15日3:43

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

© www.soinside.com 2019 - 2024. All rights reserved.