Pytest: generating list of floats summing up to 1 with hypothesis

Viewed 226

For a unit test, I would like to generate a list of float using the hypothesis library. There are some important constraints:

  1. The number of constituents within the list must be greater than 1 and less than 15
  2. The minimum value must be greater than 0
  3. The maximum value must be less than 1
  4. The sum of all constituents must exactly equal one (1)

So far, I was able to satisfy the first three constraints.

@given(
    strategies.lists(
        st.floats(min_value=0, max_value=1, exclude_min=True, exclude_max=True),
        min_size=2,
        max_size=15,
    )
)

How can I satisfy the fourth constraint?

1 Answers

I don't think you can directly add the constraint, but you could adapt your data so they fulfil the condition, for example:

def normalize(float_list):
    s = sum(float_list)
    return [f / s for f in float_list]


@given(
    strategies.lists(
        st.floats(min_value=0, max_value=1, exclude_min=True,
                  exclude_max=True),
        min_size=2,
        max_size=15,
    ).map(normalize)
)
def test_sum(f):
    assert abs(sum(f) - 1) < 0.0000001

E.g. you normalize the resulting list yourself so it would pass the condition. Note that this may not give you numbers that are exactly 1 (due to float number precision). Also, hypothesis may chose some edge cases (like some very small numbers), which may not be edge cases after the mapping -- this may or may not be a problem for you.

Related