Creating a Custom Strategy with Two Layers

30 views
Skip to first unread message

Jackson Anderson

unread,
Aug 4, 2019, 11:50:53 AM8/4/19
to Hypothesis users
Hello,

I attended the hypothesis tutorial at scipy last month and am trying to use it to improve testing in a package I contribute to. I am trying to use builds to create a random input for an object representing experimental data in the scikit-rf package. The trick is that this object contains numerous parameters with interlinked matrices that need to be related to each other in terms of size to have physical meaning. What I am trying to do to obtain this result is have hypothesis first pick integers to define the matrix sizes, pass this to the builds for the object, and have it use those values to generate arrays and matrices of the correct (randomly selected) sizes with random data fill. I could be wrong, but the problem I think I am having is that hypothesis does not build the first layer of strategies into integers to pass to the st.builds function I have defined. I tried a few approaches (the below code, using the @given decorator, etc) but have not figured out how to get it to build properly. The current code and error I am receiving is below. I assume I am going about the problem incorrectly, but could not find anything in the docs about generating strategies based on other strategies within a builds function. I'd appreciate any insight you all can offer.

Thanks,
Jackson


import skrf as rf
from hypothesis import given, strategies as st
from hypothesis.extra import numpy as stnp 
datatypes = st.one_of(st.integers,st.floats,st.complex_numbers)
# TODO: fix arguements for st.builds so that it generates correctly
 
def build_hypothesis_test_network(nports, npoints):
   return st.builds(
        rf.Network, 
        name=st.characters, 
        f=stnp.arrays(datatypes, [npoints]), 
        z0=stnp.arrays(datatypes, [st.sampled_from([nports, npoints])]),
        s=stnp.arrays(datatypes, [npoints, nports, nports]),
        comments=st.characters, 
        f_unit=st.sampled_from((None, 'hz', 'khz', 'mhz', 'ghz')) 
    ) 
test_ntwk = build_hypothesis_test_network(st.integers(min_value=1, max_value=20), 
                                                                      st.integers(min_value=0, max_value=100000))


Here is the error I receive when I try to run the code, although the error is not from the f_unit line itself but rather from the end of the builds function.

Traceback (most recent call last):
  test_viewer.py", line 34, in <module>
    st.integers(min_value=0, max_value=100000))
  test_viewer.py", line 30, in build_hypothesis_test_network
    f_unit=st.sampled_from((None, 'hz', 'khz', 'mhz', 'ghz'))
  site-packages\hypothesis\_strategies.py", line 1208, in builds
    @defines_strategy
  site-packages\hypothesis\_strategies.py", line 197, in cached_strategy
    if not isinstance(result, SearchStrategy) or result.is_cacheable:
  site-packages\hypothesis\searchstrategy\strategies.py", line 154, in accept
    recur(self)
  site-packages\hypothesis\searchstrategy\strategies.py", line 150, in recur
    mapping[strat] = getattr(strat, calculation)(recur)
  site-packages\hypothesis\searchstrategy\lazy.py", line 100, in calc_is_cacheable
    if isinstance(v, SearchStrategy) and not v.is_cacheable:
  site-packages\hypothesis\searchstrategy\strategies.py", line 154, in accept
    recur(self)
  site-packages\hypothesis\searchstrategy\strategies.py", line 150, in recur
    mapping[strat] = getattr(strat, calculation)(recur)
  site-packages\hypothesis\searchstrategy\lazy.py", line 100, in calc_is_cacheable
    if isinstance(v, SearchStrategy) and not v.is_cacheable:
 site-packages\hypothesis\searchstrategy\strategies.py", line 154, in accept
    recur(self)
  site-packages\hypothesis\searchstrategy\strategies.py", line 150, in recur
    mapping[strat] = getattr(strat, calculation)(recur)
  site-packages\hypothesis\searchstrategy\strategies.py", line 441, in calc_is_cacheable
    return all(recur(e) for e in self.original_strategies)
  site-packages\hypothesis\searchstrategy\strategies.py", line 441, in <genexpr>
    return all(recur(e) for e in self.original_strategies)
 site-packages\hypothesis\searchstrategy\strategies.py", line 150, in recur
    mapping[strat] = getattr(strat, calculation)(recur)
AttributeError: 'function' object has no attribute 'calc_is_cacheable' 

Pi Delport

unread,
Jan 16, 2020, 12:45:21 PM1/16/20
to Jackson Anderson, Hypothesis users
This is the kind of thing that composite strategies make a lot easier. You can probably implement your example using something along the lines of:

datatypes = st.one_of(st.integers(), st.floats(), st.complex_numbers())

@st.composite
def build_hypothesis_test_network(draw):
nports = draw(st.integers(min_value=1, max_value=20))
npoints = draw(st.integers(min_value=0, max_value=100000))

return draw(st.builds(
rf.Network,
name=st.characters(),
f=stnp.arrays(datatypes, [npoints]),
z0=stnp.arrays(datatypes, [draw(st.sampled_from([nports, npoints]))]),

s=stnp.arrays(datatypes, [npoints, nports, nports]),
        comments=st.characters(),

f_unit=st.sampled_from((None, 'hz', 'khz', 'mhz', 'ghz'))
    ))


--
You received this message because you are subscribed to the Google Groups "Hypothesis users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hypothesis-use...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/hypothesis-users/2dc61a8a-82d7-48ac-8638-d8d9a79384ec%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages