Search code examples
pythonpython-hypothesis

Hypothesis with flatmap not evaluating


I was trying to adapt the documentation's example of

integers(min_value=0, max_value=10).flatmap(lambda n:
... lists(lists(integers(), min_size=n, max_size=n)))

to generate tuples of 3 integers with 2/3 bounded by another integer,

@given(integers(min_value=0).flatmap(
    lambda n: tuples(n, integers(min_value=0, max_value=n),
                     integers(min_value=0, max_value=n)))
)
def testIdentityConfiguration(self, config):
    cipher = ShiftCipher(base=config[0], key=config[1])
    assert cipher.decipher(cipher.cipher(config[2])) == config[2]

but when running, I get this unfortunate stack trace:

/usr/bin/python3.4 /opt/pycharm-eap/helpers/pycharm/utrunner.py ./py4175/ true
Testing started at 1:05 AM ...

Error
Traceback (most recent call last):
  File ./.hypothesis/eval_source/hypothesis_temporary_module_065b4bdcf5d456cb3454a65c416569a728b57d13.py", line 5, in testIdentityConfiguration
    return f(self, config)
  File "/usr/lib/python3.4/site-packages/hypothesis/core.py", line 574, in wrapped_test
    print_example=True
  File "/usr/lib/python3.4/site-packages/hypothesis/executors/executors.py", line 25, in default_executor
    return function()
  File "/usr/lib/python3.4/site-packages/hypothesis/core.py", line 354, in run
    args, kwargs = search_strategy.reify(template)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/reprwrapper.py", line 49, in reify
    return self.wrapped_strategy.reify(value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/collections.py", line 65, in reify
    e.reify(v) for e, v in zip(self.element_strategies, value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/collections.py", line 65, in <listcomp>
    e.reify(v) for e, v in zip(self.element_strategies, value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/reprwrapper.py", line 49, in reify
    return self.wrapped_strategy.reify(value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/strategies.py", line 570, in reify
    return self.pack(self.mapped_strategy.reify(value))
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/collections.py", line 65, in reify
    e.reify(v) for e, v in zip(self.element_strategies, value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/collections.py", line 65, in <listcomp>
    e.reify(v) for e, v in zip(self.element_strategies, value)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/strategies.py", line 570, in reify
    return self.pack(self.mapped_strategy.reify(value))
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/flatmapped.py", line 48, in pack
    return morpher.become(strategy(self.expand(source)))
  File "./test_shiftCipher.py", line 22, in <lambda>
    integers(min_value=0, max_value=n)))
  File "./.hypothesis/eval_source/hypothesis_temporary_module_319ade46afdab08a61611170bc661bd6b6fd0507.py", line 5, in tuples
    return f(*args)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 60, in accept
    result = strategy_definition(*args, **kwargs)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 296, in tuples
    check_strategy(arg)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 704, in check_strategy
    check_type(SearchStrategy, arg)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 700, in check_type
    u'Expected %s but got %r' % (typ_string, arg,))
hypothesis.errors.InvalidArgument: Expected SearchStrategy but got 0

I tried fiddling with it and appending .example(), and found that removing the inner strategies and replacing with n, for example, worked, but as soon as I start using n as a named parameter for a strategy inside tuples(), I get errors.

>>> integers(min_value=0).flatmap(lambda n: tuples(integers())).example()
(64608439914476552176530421138352852526387959835075692,)
>>> integers(min_value=0).flatmap(lambda n: tuples(integers(max_value=n), n, n)).example()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/strategies.py", line 180, in example
    return self.reify(template)
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/strategies.py", line 570, in reify
    return self.pack(self.mapped_strategy.reify(value))
  File "/usr/lib/python3.4/site-packages/hypothesis/searchstrategy/flatmapped.py", line 48, in pack
    return morpher.become(strategy(self.expand(source)))
  File "<stdin>", line 1, in <lambda>
  File "/home/automaticgiant/.hypothesis/eval_source/hypothesis_temporary_module_319ade46afdab08a61611170bc661bd6b6fd0507.py", line 5, in tuples
    return f(*args)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 60, in accept
    result = strategy_definition(*args, **kwargs)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 296, in tuples
    check_strategy(arg)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 704, in check_strategy
    check_type(SearchStrategy, arg)
  File "/usr/lib/python3.4/site-packages/hypothesis/strategies.py", line 700, in check_type
    u'Expected %s but got %r' % (typ_string, arg,))
hypothesis.errors.InvalidArgument: Expected SearchStrategy but got 2141

The example does work though, and I don't see what I'm doing differently.

>>> integers(min_value=0, max_value=10).flatmap(lambda n: lists(lists(integers(), min_size=n, max_size=n))).example()
[[1957906, -3927073, 1876867, 492990922734139702838975287237616327198, 492990922734140672665065292763226913988, 4186129, 635696, 735953], [977765, 662451, 2759000, 492990922734140711822396894681675189101, 492990922734140140158168324233263255663, 502143, 492990922734141746996796422812724739185, 3227613], [191664, 1300515, 6482528, 319283, 492990922734139897662167042663997531115, -226596, 1857994, -2393348], [492990922734140767301167355759734660951, 492990922734141461616337923400083108003, 1468992, 102685, 4244493, 1977953, 492990922734139734438833331715382851781, 492990922734140941311965044331252036070], [492990922734141430613716803754769814902, 1164764, 792352, 6460430, 3863822, 417933, 1028367, 432653], [2746989, 492990922734141389068775096311538140111, 4793474, 3268143, 492990922734141844525243524499904826155, 492990922734141432975588324538413774052, 623043, 492990922734141596377315916430022252257], [9504628, 1439524, 1326537, -538366, 17202268, 6657340, -193066, 492990922734140889793117657227743959252], [4746341, -6393188, -7151787, 493297, 3660059, 409056, 3637009, 4590205], [24937195, 16772388, 743193, 984896, 492990922734141467947711670459172987084, 12441478, 3305605, 492990922734140542336176512792898536606], [492990922734141613464414328216081125830, 575678, 506603, 8455965, 1364227, 7266247, 492990922734141353198805511032911152831, -1599128], [492990922734141428921575729841494299316, 3389901, 5125705, 492990922734141764000051227681110176844, -1307326, 492990922734141167074970978157562738862, 492990922734141148113320874830396899884, 8909536]]
>>>

Solution

  • I think you've misunderstood the documentation for the tuples function. The arguments to tuples are strategies, and it produces a tuple of the same length as the number of arguments with values drawn from the corresponding arguments.

    The first argument to your call to tuples is 'n', which is an integer drawn from the outer strategy, not itself a strategy. If you wanted a strategy that always returns that value you need to wrap it as one by using just(n).