Working with the python testing framework hypothesis
, I would like to achieve a rather complex composition of testing strategies: 1. I would like to test against create strings s
which consist of a unique character set. 2. Each of these examples I want to run through a function func(s: str, n: int) -> Tuple[str, int]
which takes a string s
and an integer n
as a parameters. Here, I want to make the integer be populated by hypothesis as well, but the maximum value of n
should be len(s)
, the length of s
. I've tried to use flatmap
, but do not understand it sufficiently yet to get it to work. Here is the minimal example of what I've tried:
from typing import Tuple
from hypothesis import given
from hypothesis.strategies import text, integers
def func(s: str, n: int) -> Tuple[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)))
)
When I try to use this new strategy,
@given(tup=confined_tuple_str_int)
def test_foo(tup):
pass
I get a FAILED test, claiming
test_foo - TypeError: 'LazyStrategy' object cannot be interpreted as an integer
In the line for i in range(n):
, in func
, n
is not an integer, but a LazyStrategy
object.
That tells me, I have some misconception of how flatmap
works, but I cannot figure it out on my own.
What do I need to do, to define my testing strategy properly?
With
flatmap
, you cannot combine two dependent strategies - this can be done using thecomposite
decorator instead:The
draw
argument allows you to get the drawn value of a strategy (e.g. an example) - in this case a unique string - and use it to create a strategy dependent on that value - in this case an integer strategy dependent on the string length. After also drawing an example from that strategy, the composite decorator creates a new strategy from these example values and returns it.Disclaimer: I'm new to
hypothesis
, so my terminology may be a bit off.Edit: Updated to make sure that the order of examples is preserved, as suggested by Zac Hatfield-Dodds in the comments.