假设库:对其他策略进行补充的策略



我正在使用假设库进行单元测试。使用这个库,您不需要手工挑选输入,而是定义要测试的完整输入集。然后,假设将从这个集合中采样,以寻找破坏函数的输入。这也被称为基于属性的测试。在假说中,这些集合被称为策略。

现在我想对一个验证某些输入的函数进行单元测试:

GRIDSIZE_FORMAT = "^[0-9]+x[0-9]+$"
CELL_FORMAT = "^[A-Z]+[0-9]+$"
def _validate(gridsize, walls, entrance):
if not re.match(GRIDSIZE_FORMAT, gridsize):
raise ValueError(f"grid size '{gridsize}' does not match format '{GRIDSIZE_FORMAT}'")
for wall in walls:
if not re.match(CELL_FORMAT, walls):
raise ValueError(f"wall '{wall}' does not match format '{CELL_FORMAT}'")
if not re.match(CELL_FORMAT, entrance):
raise ValueError(f"entrance '{entrance}' does not match format '{CELL_FORMAT}'")

为了正确地测试这个函数;除了X〃以外的任何东西;,X是该函数的正确输入格式。

假设库中是否有一种策略可以生成这样的输入?

不幸的是,假设无法计算策略的补码,因为策略可以由任意用户提供的代码组成(包括副作用!(。例如,将生成的实例插入数据库的hypothesis.extra.django.from_model(User)的补码应该是什么?(无效,不在数据库中,…(

在更具体的情况下,您可以使用规范的补码,然后从该补码派生策略。您的正则表达式技巧就是一个很好的例子——显式集补码往往会使其比天真的"补码"更高效;生成正确的东西,并过滤掉有效的实例";方法

我确实找到了用正则表达式实现这一点的方法:

from hypothesis import strategies as st
not_cellpattern = st.from_regex(f'(?!{CELL_FORMAT})')
@given(
gridsize = st.from_regex(f'(?!{GRIDSIZE_FORMAT})'),
walls = st.lists(not_cellpattern),
entrance = not_cellpattern
)
def test_validate(gridsize, walls, entrance):
try:
_validate(gridsize, walls, entrance)
except ValueError:
pass
else:
raise Exception(f"_validate did not catch faulty input '{gridsize}', '{walls}', '{entrance}'")

但这并不完全正确:1(我必须将自己限制在字符串中,2(这只测试所有三个输入都错误的情况,而不仅仅是其中一个。

最新更新