在假设中跳过伪造的例子

Posted

技术标签:

【中文标题】在假设中跳过伪造的例子【英文标题】:Skipping falsifying examples in Hypothesis 【发布时间】:2017-01-30 02:03:45 【问题描述】:

故事:

我目前正在使用hypothesis 和custom generation strategy 对函数进行单元测试,试图找到一个特定的输入来“破坏”我当前的解决方案。这是我的测试的样子:

from solution import answer

# skipping mystrategy definition - not relevant

@given(mystrategy)
def test(l):
    assert answer(l) in 0, 1, 2

基本上,当answer() 函数不返回 0 或 1 或 2 时,我正在寻找可能的输入。

这是我的当前工作流程的样子:

运行测试

hypothesis 查找产生AssertionError 的输入:

$ pytest test.py 
=========================================== test session starts ============================================
...
------------------------------------------------ Hypothesis ------------------------------------------------
Falsifying example: test(l=[[0], [1]])

使用此特定输入调试函数,尝试了解此输入/输出是否合法且函数是否正常工作

问题:

如何跳过这个伪造的生成示例(在这种情况下为[[0], [1]])并要求hypothesis 为我生成一个不同的示例?


这个问题也可以解释为:如果发现一个伪造的例子,我可以要求hypothesis不要终止,而是生成更多的伪造例子吗?

【问题讨论】:

我不熟悉假设,但我知道它因为断言而停止。如果您只是想暂时解决这个问题,您可以打印一条失败消息,但实际上并不断言。因此,框架会认为它通过并继续运行。 @KennyOstrom 是的,但是hypothesis 在生成大量样本输入方面做得很好也很快。我可以解决它有一组输入来忽略并将这个“不在”检查添加到测试本身,但这不会扩展..另外我确信hypothesis有一个内置的方法来解决这个问题,此时我对图书馆还不够熟悉。谢谢! 【参考方案1】:

目前没有办法让 Hypothesis 在发现失败后继续尝试(它可能会在某个时候发生,但目前还不清楚应该采取什么样的正确行为,而且这不是优先事项),但是您可以使用assume 功能让它忽略特定类别的故障。​​

例如你可以跳过这个例子:

@given(mystrategy)
def test(l):
    assume(l != [[0], [1]])
    assert answer(l) in 0, 1, 2

Hypothesis 将跳过您调用带有 False 参数的任何示例,并且不将它们计入它运行的示例预算。

您可能会发现这只会导致示例的细微变化,但您可以传递更复杂的表达式来假设忽略示例类别。

您的实际用例是什么?她的正常预期使用模式是修复导致假设失败的错误并让它以这种方式找到新的错误。我知道这并不总是实用的,但我对原因很感兴趣。

【讨论】:

明白了,再次感谢!当然,这是一个编码挑战(虽然不能提供细节)。我想我在这里有点暴力,但我知道如果我的解决方案返回的结果不是 0、1、2,这可能是一个错误,但不一定..目前,我正在尝试生成不同的输入并手动检查函数的行为方式,希望能发现我无法看到的问题。将与assume() 合作,谢谢。 你试过用 find() 代替 given() 吗?如果您对生成的值感兴趣而不是对本身进行测试,它可能是一个更好的工具 我是具有此功能的 R 相关包的作者。其动机是让长时间运行的测试在一夜之间完成并报告所有发现的错误。当测试运行得非常快且无需额外成本时,就更难激发它了。想到要在一夜之间运行测试,人们会感到畏缩,但我正在开发一个大数据库,有些测试......很大,而且每个测试都有不小的延迟。

以上是关于在假设中跳过伪造的例子的主要内容,如果未能解决你的问题,请参考以下文章

在 Vim 中跳过撤消步骤

如何在函数调用中跳过可选参数?

如何向PHP伪造自己的ip

跨站请求伪造CSRF原理

如果不与其他表共享 ID,如何从 SQL 中跳过值

使用CURL伪造来源网址与IP