Provide example to hypothesis module and use len-function

111 Views Asked by At

the following code causes my test function to fail when running:

from hypothesis import given, example
import hypothesis.strategies as st
import unittest

class SomeObject():
    def __init__(self, symbol, value):
        self.__symbol = symbol
        self.__value = value

@st.composite
def sheet_names(draw, cnt=1, cnt_min_value=0):
    if (not cnt):
        cnt = draw(st.integers(min_value=cnt_min_value, max_value=3))
    return (cnt, draw(st.lists(st.text(min_size=1).filter(lambda x: '\n' not in x), min_size=cnt, max_size=cnt, unique=True)))

@st.composite
def get_objects(draw, min_cnt=0):
    cnt = draw(st.integers(min_value=min_cnt, max_value=3))
    symbols = draw(st.lists(st.text(min_size=1), min_size=cnt, max_size=cnt, unique=True))
    values = draw(st.lists(st.one_of(st.integers(), st.floats(allow_nan=False), st.text()), min_size=cnt, max_size=cnt))
    objects = list()
    for i in range(len(symbols)):
        objects.append(SomeObject(symbols[i], values[i]))
    return objects

class TestClass(unittest.TestCase):
    @given(sheet_names=sheet_names(cnt=False, cnt_min_value=1), specs=get_objects(min_cnt=1))
    @example(sheet_names=sheet_names(cnt=2), specs=get_objects(min_cnt=1))
    def test_example(self, sheet_names, specs):
        for i in range(len(sheet_names)):
            pass

The error message is:

TypeError: object of type 'LazyStrategy' has no len()

and occurs in function test_example (in the for-loop). If I remove the @example-line the code runs without any problem but I cannot be sure that the case mentioned in the @example has been covered.

Question: How can I on the one hand side write a generic test (for which I need the len-function) and at the same time name explicit examples for hypothesis?

1

There are 1 best solutions below

0
On BEST ANSWER

As Azat Ibrakov says, your problem is that the @example decorator takes values, not strategies. For example:

# Bad - strategies don't work here!
@example(sheet_names=sheet_names(cnt=2), specs=get_objects(min_cnt=1))

# Good - passing values which could be generated.
@example(
    sheet_names=(2, ["sheet1", "sheet2]),
    specs=[<SomeObject ...>, <SomeObject ...>, <SomeObject ...>]
)

Hypothesis added an explicit warning about strategies-in-@example in version 5.36.1.