假设等效于 QuickCheck 频率发生器?
Hypothesis equivalent of QuickCheck frequency generator?
作为一个学习项目,我正在将一些 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
我理解它的意思是 大多数时候 它会 return vectorOf whitespace_char
符合预期 size
,但五分之一次它将 return 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
分布是否丢失了一些重要的东西?
据我所知,您已经正确理解了此处使用 frequency
的目的。它用于允许偶尔错误大小的缩进,而不是 (1) 仅生成正确大小的缩进,这永远不会测试错误的缩进大小;或 (2) 生成随机大小的缩进,这将一遍又一遍地测试错误的缩进,但只生成一小部分具有良好缩进的案例来测试代码的其他方面。
现在,5:1 好的缩进大小与(潜在的)坏的缩进大小的比率可能是相当随意的,很难知道 1:1 或 10:1 是更好的选择没有看到正在测试的细节。
幸运的是,关于将此移植到 hypothesis
,Have a Strategy that does not uniformly choose between different strategies 的答案包括一条已删除的评论:
Hypothesis doesn't actually support user-specific probabilities - we start with a uniform distribution, but bias it based on coverage from observed inputs. [...] – Zac Hatfield-Dodds Apr 15 '18 at 3:43
这表明 "hypothesis" 包在使用 one_of
增加覆盖率时会自动调整权重,这意味着它可能会在您的 make_indent_
实现中自动增加大小正确的案例的权重, 使其成为 frequency
.
的一种自动版本
作为一个学习项目,我正在将一些 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
我理解它的意思是 大多数时候 它会 return vectorOf whitespace_char
符合预期 size
,但五分之一次它将 return 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
分布是否丢失了一些重要的东西?
据我所知,您已经正确理解了此处使用 frequency
的目的。它用于允许偶尔错误大小的缩进,而不是 (1) 仅生成正确大小的缩进,这永远不会测试错误的缩进大小;或 (2) 生成随机大小的缩进,这将一遍又一遍地测试错误的缩进,但只生成一小部分具有良好缩进的案例来测试代码的其他方面。
现在,5:1 好的缩进大小与(潜在的)坏的缩进大小的比率可能是相当随意的,很难知道 1:1 或 10:1 是更好的选择没有看到正在测试的细节。
幸运的是,关于将此移植到 hypothesis
,Have a Strategy that does not uniformly choose between different strategies 的答案包括一条已删除的评论:
Hypothesis doesn't actually support user-specific probabilities - we start with a uniform distribution, but bias it based on coverage from observed inputs. [...] – Zac Hatfield-Dodds Apr 15 '18 at 3:43
这表明 "hypothesis" 包在使用 one_of
增加覆盖率时会自动调整权重,这意味着它可能会在您的 make_indent_
实现中自动增加大小正确的案例的权重, 使其成为 frequency
.