astrofrog / fast-histogram

:zap: Fast 1D and 2D histogram functions in Python :zap:

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Improve how we generate test cases with hypothesis

astrofrog opened this issue · comments

At the moment, the test_1d_compare_with_numpy and test_2d_compare_with_numpy tests are slightly hacky in how they generate test cases. Here's the code for the 1-d case:

@given(values=arrays(dtype='<f8', shape=st.integers(0, 200),
elements=st.floats(-1000, 1000), unique=True),
nx=st.integers(1, 10),
xmin=st.floats(-1e10, 1e10),
xmax=st.floats(-1e10, 1e10),
weights=st.booleans(),
dtype=st.sampled_from(['>f4', '<f4', '>f8', '<f8']))
@settings(max_examples=500)
def test_1d_compare_with_numpy(values, nx, xmin, xmax, weights, dtype):
if xmax <= xmin:
return
values = values.astype(dtype)
size = len(values) // 2
if weights:
w = values[:size]
else:
w = None
x = values[size:size * 2]

What I'm trying to do is generate two arrays x and w which have the same dtype (either 32-bit or 64-bit floats, big or little endian), have the same 1-d size (sampled between 0 and 200), and have values in the range -1000, 1000. So at the moment I generate a 64-bit array, cast it inside the test, then split it into two. It would be cleaner to be able to directly generate the two arrays directly with the correct dtype, but I can't figure out how to do this.

@Zac-HD - do you have any suggestions how I might be able to achieve this in a cleaner way?

Maybe an st.composite strategy? That's my usual approach for arguments with dependencies, or just go for st.data() and do it inside the test function. Like:

@st.composite
def pairs_of_arrays(draw, shapes, dtypes, **kwargs):
    shape = draw(shapes)
    dtype = draw(dtypes)
    arr_strat = arrays(shape, dtype, **kwargs)
    return draw(st.tuples(arr_strat, arr_strat))

@given(
    x_and_w=pairs_of_arrays(
        shapes=array_shapes(max_dims=2),
        dtypes=st.sampled_from(['>f4', '<f4', '>f8', '<f8']),
        elements=st.floats(-1000, 1000),
        unique=True,
    ),
    ...
)
def test_1d_or_2d_compare_with_numpy(x_and_w, nx, xmin, xmax, use_weights):
    ...