I have a function which takes two arguments, an integer x
and a list l
of floats. This function requires that len(l) == x
.
I wish to write a unit test, with my function arguments x
and l
both being generated by hypothesis
strategies. How can I force l
to have the correct length? hypothesis.strategies.lists
has min_size
and max_size
arguments, but in this case they need to depend on x
, which is generated by another strategy.
At present, I am setting both min_size
and max_size
to be the largest possible value of x
, then slicing the list with l[:x]
when I actually call the function (see code below). However, this approach (a) is very slow and (b) typically fails hypothesis
‘s health checks with
E hypothesis.errors.FailedHealthCheck: It looks like your
strategy is filtering out a lot of data. Health check found 50
filtered examples but only 9 good ones. This will make your tests much
slower, and also will probably distort the data generation quite a
lot. You should adapt your strategy to filter less. This can also be
caused by a low max_leaves parameter in recursive() calls
(At least, real examples are slow and fail the health check. The toy function in my minimal code below is OK.)
Is there a better approach to designing the strategies in this case?
Using Python 3.12.2 and hypothesis 6.102.4. My code:
from hypothesis import strategies, given
def my_function(x, l):
"""Dummy function requiring length of list `l` to match integer `x`"""
if len(l) != x:
raise ValueError
# Hypothesis strategies
max_int = 100
int_st = strategies.integers(min_value=1, max_value=max_int)
float_st = strategies.floats(min_value=0, max_value=1)
floats_list_st = strategies.lists(float_st, min_size=max_int, max_size=max_int)
@given(x=int_st, l=floats_list_st)
def test_my_function(x, l):
"""Test of my_function(), where length of `l` is limited to `x`"""
# Make sure list has correct length by slicing it here
my_function(x, l[:x])