Refactor Hypothesis strategy for self-tests (#706)
* Ease Hypothesis shrinking This is a tiny performance improvement for shrinking. Unconditionally drawing and conditionally *using* these boolean flags minimises the impact of mutating other parts of an input on the structure here, which in turn means more attempts will be valid. * Refactor Hypothesis strategy Using the composite decorator allows for a much clearer imperative description of how the class is constructed.
This commit is contained in:
parent
bc527b9f29
commit
f6ffab7be0
|
@ -46,14 +46,8 @@ def maybe_underscore_prefix(source):
|
|||
to_underscore = not to_underscore
|
||||
|
||||
|
||||
def _create_hyp_class(attrs):
|
||||
"""
|
||||
A helper function for Hypothesis to generate attrs classes.
|
||||
"""
|
||||
return make_class("HypClass", dict(zip(gen_attr_names(), attrs)))
|
||||
|
||||
|
||||
def _create_hyp_nested_strategy(simple_class_strategy):
|
||||
@st.composite
|
||||
def _create_hyp_nested_strategy(draw, simple_class_strategy):
|
||||
"""
|
||||
Create a recursive attrs class.
|
||||
|
||||
|
@ -62,47 +56,17 @@ def _create_hyp_nested_strategy(simple_class_strategy):
|
|||
the simpler class, a list of simpler classes, a tuple of simpler classes,
|
||||
an ordered dict or a dict mapping the string "cls" to a simpler class.
|
||||
"""
|
||||
# Use a tuple strategy to combine simple attributes and an attr class.
|
||||
def just_class(tup):
|
||||
combined_attrs = list(tup[0])
|
||||
combined_attrs.append(attr.ib(default=attr.Factory(tup[1])))
|
||||
return _create_hyp_class(combined_attrs)
|
||||
|
||||
def list_of_class(tup):
|
||||
default = attr.Factory(lambda: [tup[1]()])
|
||||
combined_attrs = list(tup[0])
|
||||
combined_attrs.append(attr.ib(default=default))
|
||||
return _create_hyp_class(combined_attrs)
|
||||
|
||||
def tuple_of_class(tup):
|
||||
default = attr.Factory(lambda: (tup[1](),))
|
||||
combined_attrs = list(tup[0])
|
||||
combined_attrs.append(attr.ib(default=default))
|
||||
return _create_hyp_class(combined_attrs)
|
||||
|
||||
def dict_of_class(tup):
|
||||
default = attr.Factory(lambda: {"cls": tup[1]()})
|
||||
combined_attrs = list(tup[0])
|
||||
combined_attrs.append(attr.ib(default=default))
|
||||
return _create_hyp_class(combined_attrs)
|
||||
|
||||
def ordereddict_of_class(tup):
|
||||
default = attr.Factory(lambda: OrderedDict([("cls", tup[1]())]))
|
||||
combined_attrs = list(tup[0])
|
||||
combined_attrs.append(attr.ib(default=default))
|
||||
return _create_hyp_class(combined_attrs)
|
||||
|
||||
# A strategy producing tuples of the form ([list of attributes], <given
|
||||
# class strategy>).
|
||||
attrs_and_classes = st.tuples(list_of_attrs, simple_class_strategy)
|
||||
|
||||
return st.one_of(
|
||||
attrs_and_classes.map(just_class),
|
||||
attrs_and_classes.map(list_of_class),
|
||||
attrs_and_classes.map(tuple_of_class),
|
||||
attrs_and_classes.map(dict_of_class),
|
||||
attrs_and_classes.map(ordereddict_of_class),
|
||||
)
|
||||
cls = draw(simple_class_strategy)
|
||||
factories = [
|
||||
cls,
|
||||
lambda: [cls()],
|
||||
lambda: (cls(),),
|
||||
lambda: {"cls": cls()},
|
||||
lambda: OrderedDict([("cls", cls())]),
|
||||
]
|
||||
factory = draw(st.sampled_from(factories))
|
||||
attrs = draw(list_of_attrs) + [attr.ib(default=attr.Factory(factory))]
|
||||
return make_class("HypClass", dict(zip(gen_attr_names(), attrs)))
|
||||
|
||||
|
||||
bare_attrs = st.builds(attr.ib, default=st.none())
|
||||
|
@ -177,11 +141,9 @@ def simple_classes(
|
|||
private, and if `private_attrs=False`, no attributes will be private.
|
||||
"""
|
||||
attrs = draw(list_of_attrs)
|
||||
frozen_flag = draw(st.booleans()) if frozen is None else frozen
|
||||
slots_flag = draw(st.booleans()) if slots is None else slots
|
||||
weakref_slot_flag = (
|
||||
draw(st.booleans()) if weakref_slot is None else weakref_slot
|
||||
)
|
||||
frozen_flag = draw(st.booleans())
|
||||
slots_flag = draw(st.booleans())
|
||||
weakref_flag = draw(st.booleans())
|
||||
|
||||
if private_attrs is None:
|
||||
attr_names = maybe_underscore_prefix(gen_attr_names())
|
||||
|
@ -202,9 +164,9 @@ def simple_classes(
|
|||
return make_class(
|
||||
"HypClass",
|
||||
cls_dict,
|
||||
slots=slots_flag,
|
||||
frozen=frozen_flag,
|
||||
weakref_slot=weakref_slot_flag,
|
||||
slots=slots_flag if slots is None else slots,
|
||||
frozen=frozen_flag if frozen is None else frozen,
|
||||
weakref_slot=weakref_flag if weakref_slot is None else weakref_slot,
|
||||
)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue