问题描述
使用python测试框架hypothesis
,我想实现一个相当复杂的测试策略组合:1.我想对由唯一字符集组成的创建字符串s
进行测试。 2.我想通过函数func(s: str,n: int) -> Tuple[str,int]
运行每个示例,该函数以字符串s
和整数n
作为参数。在这里,我也想通过假设填充整数,但是n
的最大值应为len(s)
,即s
的长度。我尝试使用flatmap
,但对它的理解还不足以使其正常工作。这是我尝试过的最小示例:
from typing import Tuple
from hypothesis import given
from hypothesis.strategies import text,integers
def func(s: str,int]:
for i in range(n):
pass # I do something here on s,which is not relevant to the question
return (s,n)
# 1. Create the strategy for unique character strings:
unique_char_str = text().map(lambda s: "".join(set(s)))
#2. Create the complex strategy with flatmap:
confined_tuple_str_int = unique_char_str.flatmap(
lambda s: func(s,integers(min_value=0,max_value=len(s)))
)
当我尝试使用这种新策略时,
@given(tup=confined_tuple_str_int)
def test_foo(tup):
pass
我得到了失败的测试,声称
test_foo-TypeError:“ LazyStrategy”对象无法解释为整数
在for i in range(n):
的{{1}}行中,func
不是整数,而是n
对象。
这告诉我,我对LazyStrategy
的工作方式有一些误解,但我无法自行解决。
我该怎么做才能正确定义我的测试策略?
解决方法
使用flatmap
时,您无法组合两种依赖策略-可以使用composite
装饰器来完成:
@composite
def confined_tuple_str_int(draw,elements=text()):
s = draw(lists(characters(),unique=True).map("".join))
i = draw(integers(min_value=0,max_value=len(s)))
return func(s,i)
@given(confined_tuple_str_int())
def test_foo(tup):
print(tup)
通过draw
参数,您可以获取策略的绘制值(例如,示例)-在这种情况下为唯一字符串-并使用它来创建依赖于该值的策略-在这种情况下为整数策略取决于字符串长度。在还从该策略中提取了一个示例之后,复合装饰器将根据这些示例值创建一个新策略,并将其返回。
免责声明:我是hypothesis
的新手,所以我的术语可能有点过头。
编辑:已更新,以确保保留示例顺序,如Zac Hatfield-Dodds在评论中所建议。