假设库:补充一些其他策略的策略
Hypothesis library: strategy for the complement of some other strategy
我正在使用 Hypothesis 库进行单元测试。使用此库,您无需手动选择输入,而是定义要测试的完整输入集。 Hypothesis 然后将从这个集合中抽样以寻找破坏函数的输入。这也称为基于 属性 的测试。在假设中,这些集合称为策略。
现在我想对验证某些输入的函数进行单元测试:
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 库中是否有可以生成这样输入的策略?
我确实找到了使用正则表达式执行此操作的方法:
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) 这只测试所有三个输入都错误的情况,而不仅仅是其中一个输入错误。
不幸的是,Hypothesis 无法计算策略的补充,因为策略可以由任意 user-supplied 代码(包括 side-effects!)组成。比如hypothesis.extra.django.from_model(User)
的补码应该是什么,将生成的实例插入到数据库中? (无效,不在数据库中,...)
在更具体的情况下,您可以采用您的规范的补充,然后从该补充中推导出策略。您的正则表达式技巧是一个很好的例子 - 显式 set-complement 往往比天真的“生成一些东西 right-ish 并过滤掉有效实例”方法更有效。
我正在使用 Hypothesis 库进行单元测试。使用此库,您无需手动选择输入,而是定义要测试的完整输入集。 Hypothesis 然后将从这个集合中抽样以寻找破坏函数的输入。这也称为基于 属性 的测试。在假设中,这些集合称为策略。
现在我想对验证某些输入的函数进行单元测试:
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 库中是否有可以生成这样输入的策略?
我确实找到了使用正则表达式执行此操作的方法:
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) 这只测试所有三个输入都错误的情况,而不仅仅是其中一个输入错误。
不幸的是,Hypothesis 无法计算策略的补充,因为策略可以由任意 user-supplied 代码(包括 side-effects!)组成。比如hypothesis.extra.django.from_model(User)
的补码应该是什么,将生成的实例插入到数据库中? (无效,不在数据库中,...)
在更具体的情况下,您可以采用您的规范的补充,然后从该补充中推导出策略。您的正则表达式技巧是一个很好的例子 - 显式 set-complement 往往比天真的“生成一些东西 right-ish 并过滤掉有效实例”方法更有效。