목차

Testing stochastic AI models with Hypothesis

Example-based testing - issues

def merge_sort(list1, list2):
    merged_list = list1 + list2
    return sorted(list(dict.fromkeys(merged_list)))

Property-based testing


Metamorphic Testing

rfmfigx.jpg

Overview of Hypothesis library

Hypothesis Library

@given(st.integers(), st.integers())
def test_given_integers_add_is_commutative(x, y):
    assert x + y == y + x

@given(st.floats(allow_nan=False, allow_infinity=False), st.floast(allow_nan=False, allow_infinity=False))
def test_given_floats_add_is_commutative(x, y):
    assert x + y == y + x

Hypothesis basic strategies

@given(arrays(int, st.shared(array_shapes(min_dims=3, max_dims=5), key="shape")), arrays(int, st.shared(array_shapes(min_dims=3, max_dims=5), key="shape")))
def test_given_arrays_multiply_is_commutative(arr1, arr2):
    np.array_equal(arr1 * arr2, arr2 * arr1)

@given(array_shapes(min_dims=3, max_dims=5), st.data())
def test_given_arrays_multiply_is_commutative(arr_shape, data):
    arr1 = data.draw(arrays(int, arr_shape))
    arr2 = data.draw(arrays(int, arr_shape))
    np.array_equal(arr1 * arr2, arr2 * arr1)

merge_sort test

@given(st.lists(st.integers() | st.floats(allow_nan=False)), st.lists(st.integers() | st.floats(allow_nan=False)))
def test_commutativity(list1, list2):
    assert merge_sort(list1, list2) == merge_sort(list2, list1)

Define you own strategy

class Rectangle:
    """ A class of Python object that describe the properties of a rectangle """
    def __init__(self, width, height, center=(0, 0)):
        self.width = width
        self.height = height
        self.center = center
 
    def __repr__(self):
        return "Rectangle(width={w}, height={h}, center={c})".format(h=self.height, w=self.widht, c=self.center)
 
    def __lt__(self, other):
        return self.get_area() < other.get_area()
 
    def get_area(self):
        return self.with * self.height
 
def rectangle_list_strategy():
    return st.lists(st.builds(Rectangle, st.integers(min_value=0), st.integers(min_value=0), st.tuples(st.integers(), st.integers())))
 
@given(rectangle_list_strategy())
def test_given_rectangle_list_sort_is_distinct(rectangle_list):
    assert sorted(rectangle_list) == sorted(sorted(rectangle_list))

Transforming data functions

Filtering

@given(st.integers().filter(lambda num: num % 2 ==0))
def test_given_even_number_transform_is_even(num):
    assert (num + 2) % 2 == 0

Mapping

@given(st.integers().map(lambda num: num * 2))
def test_given_even_numbers_transform_is_even(num):
    assert (num + 2) % == 0

Debug hypothesis strategies

def list_strategy():
    return st.lists(st.one_of(st.integers(), st.floats(allow_nan=False)))

Repeatable random testing

Shrinking

Additional Components

from scipy import ndimage
from hypothesis.extra.numpy import arrays, array_shapes
 
@composite
def add_additional_blobs_to_prediction_strategy(draw, blob_prediction):
    dilated_blob_mask = ...
    ...
    return prediction
 
@given(arrays(bool, array_shape(min_dims=3, min_side=10)), st.data())  
def test_given_prediction_adding_blobs_return_include_features(raw_prediction, data):
    modified_prediction = data.draw(add_additional_blobs_to_prediction_strategy(raw_prediction))
    assert np.all(np.isin(extract_blob_mask_features(raw_prediction), extract_blob_mask_features(modified_prediction)))

Source


관련 문서