3

I started using hypothesis to write my tests. I like it, but I am stuck to generate some kind of data.

I have a test that use list of data, which can be constructed from tuple(key, value).

Key can be text, integer or float, value can be anything comparable. For one test, all keys must be the same type, and all values must be the same type.

The only way I found to generate data I want is something like that:

@given(
    st.one_of(
        st.lists(st.tuples(st.integers(), st.integers())),
        st.lists(st.tuples(st.integers(), st.floats())),
        st.lists(st.tuples(st.integers(), st.text())),
        st.lists(st.tuples(st.floats(), st.integers())),
        st.lists(st.tuples(st.floats(), st.floats())),
        st.lists(st.tuples(st.floats(), st.text())),
        #...
    ))
def test_stuff(lst):
   data = [Mydata(k, v) for k, v in lst]
   #...

Is there a better way to generate all data type combination I want to test ?

Alexander
  • 105,104
  • 32
  • 201
  • 196
Jyhess
  • 33
  • 4
  • I think I understand, but could you elaborate with some sample data? – Alexander Jan 18 '18 at 17:20
  • Here here some examples: lst_1=[(1, 0), (2, 4), (6, 4)], lst_2=[(1, 'foo'), (2, 'bar'), (6, 'baz')], lst_3=[('a', 3), ('g', 45), ('jnsdfi', 12)] – Jyhess Jan 18 '18 at 17:22
  • `st.lists(st.tuples(st.integers(), st.integers()))` => `[(1, 0), (2, 4), (6, 4)]` and `st.lists(st.tuples(st.integers(), st.floats()))` => `[(1, 0.0), (2, 4.0), (6, 4.0)]`? – Alexander Jan 18 '18 at 17:23
  • Yes, it's the kind of data I would like to generate – Jyhess Jan 18 '18 at 17:25
  • 1
    `one_of(*[st.lists(st.tuples(k, v)) for k in key_types for v in value_types])`, maybe? It’s not that clean, but… – Ry- Jan 18 '18 at 17:30
  • It seems to works. Thanks Ryan. You can promote this comment in answer and I will accept it to close this question. – Jyhess Jan 18 '18 at 17:52

1 Answers1

1

My preferred way to do this is to choose the key and value strategies in @given, then construct your strategy and draw from it inside your test. The "all keys must be of the same one of these types" thing is an unusual requirement, but interactive data is very powerful:

@given(
    st.data(), 
    key_st=st.sampled_from([st.integers(), st.floats(), st.text()]),
    value_st=st.sampled_from([st.integers(), st.floats(), st.text()]),
)
def test_stuff(data, key_st, value_st):
    test_data = data.draw(st.lists(st.builds(Mydata, key_st, value_st)))
    ...  # TODO: assert things about test_data

I've also used st.builds() rather than going via tuples - since we're calling it inside the test, any exceptions in Mydata will be (minimised) test failures rather than errors.

Zac Hatfield-Dodds
  • 2,455
  • 6
  • 19