I'd like to generate a strategy for NumPy testing with an output like:
array([[-2, -2],
[-3, -3],
[5, 5],
[-1, -1]], dtype=int16)
What I tried was:
import numpy as np
from hypothesis.strategies import integers
from hypothesis.extra.numpy import arrays
arrays(np.int16, (4,2), elements=integers(-10, 10)).example()
Unfortunately, I can't make values inside tuples identical so the query above returns:
array([[ 5, 5],
[-7, 5],
[ 5, 5],
[ 5, 5]], dtype=int16)
I have found that if I need to control content within an existing strategy's structure (e.g. pairs of identical values within an array) I need to skip that strategy for lower level ones with which I can build a "ready-made" value that can seed the type I care to generate.
Let's leverage that numpy.array accepts a list of lists to create an array. Let's also assume you want each row to be unique, as your example does not show duplicate rows. If that is not desired, remove the unique_by=str
from the depth_strategy
definition
# %%
"""Hypothesis strategy for array of tuples with pairs of identical values."""
from hypothesis import given, settings, strategies as st
import numpy as np
WIDTH = 2
DEPTH = 4
MIN_VALUE = -10
MAX_VALUE = 10
# Build the row - Here for clarification only
width_strategy = st.integers(MIN_VALUE, MAX_VALUE).map(
lambda i: tuple(i for _ in range(WIDTH))
)
# Build the array of rows - Here for clarification only
depth_strategy = st.lists(
width_strategy, min_size=DEPTH, max_size=DEPTH, unique_by=str
).map(lambda lot: np.array(lot, dtype=np.int64))
# All-in-One
complete_strategy = st.lists(
st.integers(MIN_VALUE, MAX_VALUE).map(
lambda i: tuple(i for _ in range(WIDTH))
),
min_size=DEPTH,
max_size=DEPTH,
unique_by=str,
).map(lambda lot: np.array(lot, dtype=np.int64))
@settings(max_examples=10)
@given(an_array=complete_strategy)
def create_numpy_array(an_array):
"""Turn list of lists into numpy array."""
print(f"A numpy array could be:\n{an_array}")
create_numpy_array()
This generates something like:
A numpy array could be:
[[ 3 3]
[ 9 9]
[-5 -5]
[ 0 0]]
A numpy array could be:
[[ 3 3]
[-2 -2]
[ 4 4]
[-5 -5]]
A numpy array could be:
[[ 7 7]
[ 0 0]
[-2 -2]
[-1 -1]]
Note that I set the max_examples to 10 as Hypothesis gives a higher occurrences ratio to values it deems "troublesome", such as zero, NaN, Infinity and such. So example() or a lower number of examples would probably generate a lot of 2x4 arrays of all zeroes. Fortunately the unique_by constraint helps us here.