What you can generate and how¶
Most things should be easy to generate and everything should be possible.
To support this principle Hypothesis provides strategies for most builtin types with arguments to constrain or adjust the output, as well as higherorder strategies that can be composed to generate more complex types.
This document is a guide to what strategies are available for generating data and how to build them. Strategies have a variety of other important internal features, such as how they simplify, but the data they can generate is the only public part of their API.
Functions for building strategies are all available in the hypothesis.strategies module. The salient functions from it are as follows:

hypothesis.strategies.
nothing
()[source]¶ This strategy never successfully draws a value and will always reject on an attempt to draw.
Examples from this strategy do not shrink (because there are none).

hypothesis.strategies.
just
(value)[source]¶ Return a strategy which only generates
value
.Note:
value
is not copied. Be wary of using mutable values.If
value
is the result of a callable, you can usebuilds(callable)
instead ofjust(callable())
to get a fresh value each time.Examples from this strategy do not shrink (because there is only one).

hypothesis.strategies.
none
()[source]¶ Return a strategy which only generates None.
Examples from this strategy do not shrink (because there is only one).

hypothesis.strategies.
one_of
(*args)[source]¶ Return a strategy which generates values from any of the argument strategies.
This may be called with one iterable argument instead of multiple strategy arguments. In which case
one_of(x)
andone_of(*x)
are equivalent.Examples from this strategy will generally shrink to ones that come from strategies earlier in the list, then shrink according to behaviour of the strategy that produced them. In order to get good shrinking behaviour, try to put simpler strategies first. e.g.
one_of(none(), text())
is better thanone_of(text(), none())
.This is especially important when using recursive strategies. e.g.
x = st.deferred(lambda: st.none()  st.tuples(x, x))
will shrink well, butx = st.deferred(lambda: st.tuples(x, x)  st.none())
will shrink very badly indeed.

hypothesis.strategies.
integers
(min_value=None, max_value=None)[source]¶ Returns a strategy which generates integers (in Python 2 these may be ints or longs).
If min_value is not None then all values will be >= min_value. If max_value is not None then all values will be <= max_value
Examples from this strategy will shrink towards zero, and negative values will also shrink towards positive (i.e. n may be replaced by +n).

hypothesis.strategies.
booleans
()[source]¶ Returns a strategy which generates instances of bool.
Examples from this strategy will shrink towards False (i.e. shrinking will try to replace True with False where possible).

hypothesis.strategies.
floats
(min_value=None, max_value=None, allow_nan=None, allow_infinity=None)[source]¶ Returns a strategy which generates floats.
 If min_value is not None, all values will be >= min_value.
 If max_value is not None, all values will be <= max_value.
 If min_value or max_value is not None, it is an error to enable allow_nan.
 If both min_value and max_value are not None, it is an error to enable allow_infinity.
Where not explicitly ruled out by the bounds, all of infinity, infinity and NaN are possible values generated by this strategy.
Examples from this strategy have a complicated and hard to explain shrinking behaviour, but it tries to improve “human readability”. Finite numbers will be preferred to infinity and infinity will be preferred to NaN.

hypothesis.strategies.
complex_numbers
()[source]¶ Returns a strategy that generates complex numbers.
Examples from this strategy shrink by shrinking their component real and imaginary parts.

hypothesis.strategies.
tuples
(*args)[source]¶ Return a strategy which generates a tuple of the same length as args by generating the value at index i from args[i].
e.g. tuples(integers(), integers()) would generate a tuple of length two with both values an integer.
Examples from this strategy shrink by shrinking their component parts.

hypothesis.strategies.
sampled_from
(elements)[source]¶ Returns a strategy which generates any value present in
elements
.Note that as with
just()
, values will not be copied and thus you should be careful of using mutable data.sampled_from
supports ordered collections, as well asEnum
objects.Flag
objects may also generate any combination of their members.Examples from this strategy shrink by replacing them with values earlier in the list. So e.g. sampled_from((10, 1)) will shrink by trying to replace 1 values with 10, and sampled_from((1, 10)) will shrink by trying to replace 10 values with 1.

hypothesis.strategies.
lists
(elements=None, min_size=None, average_size=None, max_size=None, unique_by=None, unique=False)[source]¶ Returns a list containing values drawn from elements with length in the interval [min_size, max_size] (no bounds in that direction if these are None). If max_size is 0 then elements may be None and only the empty list will be drawn.
average_size may be used as a size hint to roughly control the size of the list but it may not be the actual average of sizes you get, due to a variety of factors.
If unique is True (or something that evaluates to True), we compare direct object equality, as if unique_by was lambda x: x. This comparison only works for hashable types.
if unique_by is not None it must be a function returning a hashable type when given a value drawn from elements. The resulting list will satisfy the condition that for i != j, unique_by(result[i]) != unique_by(result[j]).
Examples from this strategy shrink by trying to remove elements from the list, and by shrinking each individual element of the list.

hypothesis.strategies.
sets
(elements=None, min_size=None, average_size=None, max_size=None)[source]¶ This has the same behaviour as lists, but returns sets instead.
Note that Hypothesis cannot tell if values are drawn from elements are hashable until running the test, so you can define a strategy for sets of an unhashable type but it will fail at test time.
Examples from this strategy shrink by trying to remove elements from the set, and by shrinking each individual element of the set.

hypothesis.strategies.
frozensets
(elements=None, min_size=None, average_size=None, max_size=None)[source]¶ This is identical to the sets function but instead returns frozensets.

hypothesis.strategies.
iterables
(elements=None, min_size=None, average_size=None, max_size=None, unique_by=None, unique=False)[source]¶ This has the same behaviour as lists, but returns iterables instead.
Some iterables cannot be indexed (e.g. sets) and some do not have a fixed length (e.g. generators). This strategy produces iterators, which cannot be indexed and do not have a fixed length. This ensures that you do not accidentally depend on sequence behaviour.

hypothesis.strategies.
fixed_dictionaries
(mapping)[source]¶ Generates a dictionary of the same type as mapping with a fixed set of keys mapping to strategies. mapping must be a dict subclass.
Generated values have all keys present in mapping, with the corresponding values drawn from mapping[key]. If mapping is an instance of OrderedDict the keys will also be in the same order, otherwise the order is arbitrary.
Examples from this strategy shrink by shrinking each individual value in the generated dictionary.

hypothesis.strategies.
dictionaries
(keys, values, dict_class=<type 'dict'>, min_size=None, average_size=None, max_size=None)[source]¶ Generates dictionaries of type dict_class with keys drawn from the keys argument and values drawn from the values argument.
The size parameters have the same interpretation as for lists.
Examples from this strategy shrink by trying to remove keys from the generated dictionary, and by shrinking each generated key and value.

hypothesis.strategies.
streaming
(elements)[source]¶ Generates an infinite stream of values where each value is drawn from elements.
The result is iterable (the iterator will never terminate) and indexable.
Examples from this strategy shrink by trying to shrink each value drawn.
Deprecated since version 3.15.0: Use
data()
instead.

hypothesis.strategies.
characters
(whitelist_categories=None, blacklist_categories=None, blacklist_characters=None, min_codepoint=None, max_codepoint=None, whitelist_characters=None)[source]¶ Generates unicode text type (unicode on python 2, str on python 3) characters following specified filtering rules.
 When no filtering rules are specifed, any character can be produced.
 If
min_codepoint
ormax_codepoint
is specifed, then only characters having a codepoint in that range will be produced.  If
whitelist_categories
is specified, then only characters from those Unicode categories will be produced. This is a further restriction, characters must also satisfymin_codepoint
andmax_codepoint
.  If
blacklist_categories
is specified, then any character from those categories will not be produced. Any overlap betweenwhitelist_categories
andblacklist_categories
will raise an exception, as each character can only belong to a single class.  If
whitelist_characters
is specified, then any additional characters in that list will also be produced.  If
blacklist_characters
is specified, then any characters in that list will be not be produced. Any overlap betweenwhitelist_characters
andblacklist_characters
will raise an exception.
The
_codepoint
arguments must be integers between zero andsys.max_unicode
. The_characters
arguments must be collections of lengthone unicode strings, such as a unicode string.The
_categories
arguments must be used to specify either the oneletter Unicode major category or the twoletter Unicode general category. For example,('Nd', 'Lu')
signifies “Number, decimal digit” and “Letter, uppercase”. A single letter (‘major category’) can be given to match all corresponding categories, for example'P'
for characters in any punctuation category.Examples from this strategy shrink towards the codepoint for
'0'
, or the first allowable codepoint after it if'0'
is excluded.

hypothesis.strategies.
text
(alphabet=None, min_size=None, average_size=None, max_size=None)[source]¶ Generates values of a unicode text type (unicode on python 2, str on python 3) with values drawn from alphabet, which should be an iterable of length one strings or a strategy generating such. If it is None it will default to generating the full unicode range (excluding surrogate characters). If it is an empty collection this will only generate empty strings.
min_size, max_size and average_size have the usual interpretations.
Examples from this strategy shrink towards shorter strings, and with the characters in the text shrinking as per the alphabet strategy.

hypothesis.strategies.
from_regex
(regex)[source]¶ Generates strings that contain a match for the given regex (i.e. ones for which
re.search()
will return a nonNone result).regex
may be a pattern orcompiled regex
. Both bytestrings and unicode strings are supported, and will generate examples of the same type.You can use regex flags such as
re.IGNORECASE
,re.DOTALL
orre.UNICODE
to control generation. Flags can be passed either in compiled regex or inside the pattern with a(?iLmsux)
group.Some regular expressions are only partly supported  the underlying strategy checks local matching and relies on filtering to resolve contextdependent expressions. Using too many of these constructs may cause healthcheck errors as too many examples are filtered out. This mainly includes (positive or negative) lookahead and lookbehind groups.
If you want the generated string to match the whole regex you should use boundary markers. So e.g.
r"\A.\Z"
will return a single character string, while"."
will return any string, andr"\A.$"
will return a single character optionally followed by a"\n"
.Examples from this strategy shrink towards shorter strings and lower character values.

hypothesis.strategies.
binary
(min_size=None, average_size=None, max_size=None)[source]¶ Generates the appropriate binary type (str in python 2, bytes in python 3).
min_size, average_size and max_size have the usual interpretations.
Examples from this strategy shrink towards smaller strings and lower byte values.

hypothesis.strategies.
randoms
()[source]¶ Generates instances of Random (actually a Hypothesis specific RandomWithSeed class which displays what it was initially seeded with)
Examples from this strategy shrink to seeds closer to zero.

hypothesis.strategies.
random_module
()[source]¶ If your code depends on the global random module then you need to use this.
It will explicitly seed the random module at the start of your test so that tests are reproducible. The value it passes you is an opaque object whose only useful feature is that its repr displays the random seed. It is not itself a random number generator. If you want a random number generator you should use the randoms() strategy which will give you one.
Examples from these strategy shrink to seeds closer to zero.

hypothesis.strategies.
builds
(*callable_and_args, **kwargs)[source]¶ Generates values by drawing from
args
andkwargs
and passing them to the callable (provided as the first positional argument) in the appropriate argument position.e.g.
builds(target, integers(), flag=booleans())
would draw an integeri
and a booleanb
and calltarget(i, flag=b)
.If the callable has type annotations, they will be used to infer a strategy for required arguments that were not passed to builds. You can also tell builds to infer a strategy for an optional argument by passing the special value
hypothesis.infer
as a keyword argument to builds, instead of a strategy for that argument to the callable.Examples from this strategy shrink by shrinking the argument values to the callable.

hypothesis.strategies.
from_type
(thing)[source]¶ Looks up the appropriate search strategy for the given type.
from_type
is used internally to fill in missing arguments tobuilds()
and can be used interactively to explore what strategies are available or to debug type resolution.You can use
register_type_strategy()
to handle your custom types, or to globally redefine certain strategies  for example excluding NaN from floats, or use timezoneaware instead of naive time and datetime strategies.The resolution logic may be changed in a future version, but currently tries these four options:
 If
thing
is in the default lookup mapping or userregistered lookup, return the corresponding strategy. The default lookup covers all types with Hypothesis strategies, including extras where possible.  If
thing
is from thetyping
module, return the corresponding strategy (special logic).  If
thing
has one or more subtypes in the merged lookup, return the union of the strategies for those types that are not subtypes of other elements in the lookup.  Finally, if
thing
has type annotations for all required arguments, it is resolved viabuilds()
.
 If

hypothesis.strategies.
fractions
(min_value=None, max_value=None, max_denominator=None)[source]¶ Returns a strategy which generates Fractions.
If min_value is not None then all generated values are no less than min_value. If max_value is not None then all generated values are no greater than max_value. min_value and max_value may be anything accepted by the
Fraction
constructor.If max_denominator is not None then the denominator of any generated values is no greater than max_denominator. Note that max_denominator must be None or a positive integer.
Examples from this strategy shrink towards smaller denominators, then closer to zero.

hypothesis.strategies.
decimals
(min_value=None, max_value=None, allow_nan=None, allow_infinity=None, places=None)[source]¶ Generates instances of
decimals.Decimal
, which may be: A finite rational number, between
min_value
andmax_value
.  Not a Number, if
allow_nan
is True. None means “allow NaN, unlessmin_value
andmax_value
are not None”.  Positive or negative infinity, if
max_value
andmin_value
respectively are None, andallow_infinity
is not False. None means “allow infinity, unless excluded by the min and max values”.
Note that where floats have one
NaN
value, Decimals have four: signed, and either quiet or signalling. See the decimal module docs for more information on special values.If
places
is not None, all finite values drawn from the strategy will have that number of digits after the decimal place.Examples from this strategy do not have a well defined shrink order but try to maximize human readability when shrinking.
 A finite rational number, between

hypothesis.strategies.
recursive
(base, extend, max_leaves=100)[source]¶ base: A strategy to start from.
extend: A function which takes a strategy and returns a new strategy.
max_leaves: The maximum number of elements to be drawn from base on a given run.
This returns a strategy
S
such thatS = extend(base  S)
. That is, values may be drawn from base, or from any strategy reachable by mixing applications of  and extend.An example may clarify:
recursive(booleans(), lists)
would return a strategy that may return arbitrarily nested and mixed lists of booleans. So e.g.False
,[True]
,[False, []]
, and[[[[True]]]]
are all valid values to be drawn from that strategy.Examples from this strategy shrink by trying to reduce the amount of recursion and by shrinking according to the shrinking behaviour of base and the result of extend.

hypothesis.strategies.
permutations
(values)[source]¶ Return a strategy which returns permutations of the collection
values
.Examples from this strategy shrink by trying to become closer to the original order of values.

hypothesis.strategies.
datetimes
(min_value=datetime.datetime(1, 1, 1, 0, 0), max_value=datetime.datetime(9999, 12, 31, 23, 59, 59, 999999), timezones=none(), min_datetime=None, max_datetime=None)[source]¶ A strategy for generating datetimes, which may be timezoneaware.
This strategy works by drawing a naive datetime between
min_datetime
andmax_datetime
, which must both be naive (have no timezone).timezones
must be a strategy that generates tzinfo objects (or None, which is valid for naive datetimes). A value drawn from this strategy will be added to a naive datetime, and the resulting tzaware datetime returned.Note
tzaware datetimes from this strategy may be ambiguous or nonexistent due to daylight savings, leap seconds, timezone and calendar adjustments, etc. This is intentional, as malformed timestamps are a common source of bugs.
hypothesis.extra.timezones()
requires thepytz
package, but provides all timezones in the Olsen database. If you also want to allow naive datetimes, combine strategies likenone()  timezones()
.Alternatively, you can create a list of the timezones you wish to allow (e.g. from the standard library,
datetutil
, orpytz
) and usesampled_from()
. Ensure that simple values such as None or UTC are at the beginning of the list for proper minimisation.Examples from this strategy shrink towards midnight on January 1st 2000.
The following arguments have been renamed:
 min_datetime has been renamed to min_value
 max_datetime has been renamed to max_value
Use of the old names has been deprecated and will be removed in a future version of Hypothesis.

hypothesis.strategies.
dates
(min_value=datetime.date(1, 1, 1), max_value=datetime.date(9999, 12, 31), min_date=None, max_date=None)[source]¶ A strategy for dates between
min_date
andmax_date
.Examples from this strategy shrink towards January 1st 2000.
The following arguments have been renamed:
 max_date has been renamed to max_value
 min_date has been renamed to min_value
Use of the old names has been deprecated and will be removed in a future version of Hypothesis.

hypothesis.strategies.
times
(min_value=datetime.time(0, 0), max_value=datetime.time(23, 59, 59, 999999), timezones=none(), min_time=None, max_time=None)[source]¶ A strategy for times between
min_time
andmax_time
.The
timezones
argument is handled as fordatetimes()
.Examples from this strategy shrink towards midnight, with the timezone component shrinking as for the strategy that provided it.
The following arguments have been renamed:
 min_time has been renamed to min_value
 max_time has been renamed to max_value
Use of the old names has been deprecated and will be removed in a future version of Hypothesis.

hypothesis.strategies.
timedeltas
(min_value=datetime.timedelta(999999999), max_value=datetime.timedelta(999999999, 86399, 999999), min_delta=None, max_delta=None)[source]¶ A strategy for timedeltas between
min_value
andmax_value
.Examples from this strategy shrink towards zero.
The following arguments have been renamed:
 max_delta has been renamed to max_value
 min_delta has been renamed to min_value
Use of the old names has been deprecated and will be removed in a future version of Hypothesis.

hypothesis.strategies.
composite
(f)[source]¶ Defines a strategy that is built out of potentially arbitrarily many other strategies.
This is intended to be used as a decorator. See the full documentation for more details about how to use this function.
Examples from this strategy shrink by shrinking the output of each draw call.
Returns a strategy that draws a single shared value per run, drawn from base. Any two shared instances with the same key will share the same value, otherwise the identity of this strategy will be used. That is:
>>> s = integers() # or any other strategy >>> x = shared(s) >>> y = shared(s)
In the above x and y may draw different (or potentially the same) values. In the following they will always draw the same:
>>> x = shared(s, key="hi") >>> y = shared(s, key="hi")
Examples from this strategy shrink as per their base strategy.

hypothesis.strategies.
choices
()[source]¶ Strategy that generates a function that behaves like random.choice.
Will note choices made for reproducibility.
Deprecated since version 3.15.0: Use
data()
withsampled_from()
instead.Examples from this strategy shrink by making each choice function return an earlier value in the sequence passed to it.

hypothesis.strategies.
uuids
(version=None)[source]¶ Returns a strategy that generates
UUIDs
.If the optional version argument is given, value is passed through to
UUID
and only UUIDs of that version will be generated.All returned values from this will be unique, so e.g. if you do
lists(uuids())
the resulting list will never contain duplicates.Examples from this strategy don’t have any meaningful shrink order.

hypothesis.strategies.
runner
(default=not_set)[source]¶ A strategy for getting “the current test runner”, whatever that may be. The exact meaning depends on the entry point, but it will usually be the associated ‘self’ value for it.
If there is no current test runner and a default is provided, return that default. If no default is provided, raises InvalidArgument.
Examples from this strategy do not shrink (because there is only one).

hypothesis.strategies.
data
()[source]¶ This isn’t really a normal strategy, but instead gives you an object which can be used to draw data interactively from other strategies.
It can only be used within
@given
, notfind()
. This is because the lifetime of the object cannot outlast the test body.See the rest of the documentation for more complete information.
Examples from this strategy do not shrink (because there is only one), but the result of calls to each draw() call shrink as they normally would.

hypothesis.strategies.
register_type_strategy
(custom_type, strategy)[source]¶ Add an entry to the global typetostrategy lookup.
This lookup is used in
builds()
and@given
.builds()
will be used automatically for classes with type annotations on__init__
, so you only need to register a strategy if one or more arguments need to be more tightly defined than their typebased default, or if you want to supply a strategy for an argument with a default value.strategy
may be a search strategy, or a function that takes a type and returns a strategy (useful for generic types).

hypothesis.strategies.
deferred
(definition)[source]¶ A deferred strategy allows you to write a strategy that references other strategies that have not yet been defined. This allows for the easy definition of recursive and mutually recursive strategies.
The definition argument should be a zeroargument function that returns a strategy. It will be evaluated the first time the strategy is used to produce an example.
Example usage:
>>> import hypothesis.strategies as st >>> x = st.deferred(lambda: st.booleans()  st.tuples(x, x)) >>> x.example() (((False, (True, True)), (False, True)), (True, True)) >>> x.example() True
Mutual recursion also works fine:
>>> a = st.deferred(lambda: st.booleans()  b) >>> b = st.deferred(lambda: st.tuples(a, a)) >>> a.example() True >>> b.example() (False, (False, ((False, True), False)))
Examples from this strategy shrink as they normally would from the strategy returned by the definition.
Shrinking¶
When using strategies it is worth thinking about how the data shrinks. Shrinking is the process by which Hypothesis tries to produce human readable examples when it finds a failure  it takes a complex example and turns it into a simpler one.
Each strategy defines an order in which it shrinks  you won’t usually need to care about this much, but it can be worth being aware of as it can affect what the best way to write your own strategies is.
The exact shrinking behaviour is not a guaranteed part of the API, but it doesn’t change that often and when it does it’s usually because we think the new way produces nicer examples.
Possibly the most important one to be aware of is
one_of()
, which has a preference for values
produced by strategies earlier in its argument list. Most of the others should
largely “do the right thing” without you having to think about it.
Adapting strategies¶
Often it is the case that a strategy doesn’t produce exactly what you want it to and you need to adapt it. Sometimes you can do this in the test, but this hurts reuse because you then have to repeat the adaption in every test.
Hypothesis gives you ways to build strategies from other strategies given functions for transforming the data.
Mapping¶
map
is probably the easiest and most useful of these to use. If you have a
strategy s
and a function f
, then an example s.map(f).example()
is
f(s.example())
, i.e. we draw an example from s
and then apply f
to it.
e.g.:
>>> lists(integers()).map(sorted).example()
[25527, 24245, 23118, 93, 70, 7, 0, 39, 40, 65, 88, 112, 6189, 9480, 19469, 27256, 32526, 1566924430]
Note that many things that you might use mapping for can also be done with
builds()
.
Filtering¶
filter
lets you reject some examples. s.filter(f).example()
is some
example of s
such that f(example)
is truthy.
>>> integers().filter(lambda x: x > 11).example()
26126
>>> integers().filter(lambda x: x > 11).example()
23324
It’s important to note that filter
isn’t magic and if your condition is too
hard to satisfy then this can fail:
>>> integers().filter(lambda x: False).example()
Traceback (most recent call last):
...
hypothesis.errors.NoExamples: Could not find any valid examples in 20 tries
In general you should try to use filter
only to avoid corner cases that you
don’t want rather than attempting to cut out a large chunk of the search space.
A technique that often works well here is to use map to first transform the data
and then use filter
to remove things that didn’t work out. So for example if
you wanted pairs of integers (x,y) such that x < y you could do the following:
>>> tuples(integers(), integers()).map(sorted).filter(lambda x: x[0] < x[1]).example()
[8543729478746591815, 3760495307320535691]
Chaining strategies together¶
Finally there is flatmap
. flatmap
draws an example, then turns that
example into a strategy, then draws an example from that strategy.
It may not be obvious why you want this at first, but it turns out to be quite useful because it lets you generate different types of data with relationships to each other.
For example suppose we wanted to generate a list of lists of the same length:
>>> rectangle_lists = integers(min_value=0, max_value=10).flatmap(
... lambda n: lists(lists(integers(), min_size=n, max_size=n)))
>>> find(rectangle_lists, lambda x: True)
[]
>>> find(rectangle_lists, lambda x: len(x) >= 10)
[[], [], [], [], [], [], [], [], [], []]
>>> find(rectangle_lists, lambda t: len(t) >= 3 and len(t[0]) >= 3)
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> find(rectangle_lists, lambda t: sum(len(s) for s in t) >= 10)
[[0], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
In this example we first choose a length for our tuples, then we build a strategy which generates lists containing lists precisely of that length. The finds show what simple examples for this look like.
Most of the time you probably don’t want flatmap
, but unlike filter
and
map
which are just conveniences for things you could just do in your tests,
flatmap
allows genuinely new data generation that you wouldn’t otherwise be
able to easily do.
(If you know Haskell: Yes, this is more or less a monadic bind. If you don’t know Haskell, ignore everything in these parentheses. You do not need to understand anything about monads to use this, or anything else in Hypothesis).
Recursive data¶
Sometimes the data you want to generate has a recursive definition. e.g. if you wanted to generate JSON data, valid JSON is:
 Any float, any boolean, any unicode string.
 Any list of valid JSON data
 Any dictionary mapping unicode strings to valid JSON data.
The problem is that you cannot call a strategy recursively and expect it to not just blow up and eat all your memory. The other problem here is that not all unicode strings display consistently on different machines, so we’ll restrict them in our doctest.
The way Hypothesis handles this is with the recursive()
function
which you pass in a base case and a function that, given a strategy for your data type,
returns a new strategy for it. So for example:
>>> from string import printable; from pprint import pprint
>>> json = recursive(none()  booleans()  floats()  text(printable),
... lambda children: lists(children)  dictionaries(text(printable), children))
>>> pprint(json.example())
['dy',
[None, True, 6.297399055778002e+16, False],
{'a{h\\:694K~{mY>a1yA:#CmDYb': None},
'\\kP!4',
{'#1J1': '',
'cx.': None,
"jv'A?qyp_sB\n$62g": [],
'qgnP': [False, inf, 'la)']},
[],
{}]
>>> pprint(json.example())
{'': None,
'(Rt)': 1.192092896e07,
',': [],
'6': 2.2250738585072014e308,
'HA=/': [],
'YU]gy8': inf,
'l': None,
'nK': False}
>>> pprint(json.example())
[]
That is, we start with our leaf data and then we augment it by allowing lists and dictionaries of anything we can generate as JSON data.
The size control of this works by limiting the maximum number of values that can be drawn from the base strategy. So for example if we wanted to only generate really small JSON we could do this as:
>>> small_lists = recursive(booleans(), lists, max_leaves=5)
>>> small_lists.example()
[False]
>>> small_lists.example()
True
>>> small_lists.example()
[]
Composite strategies¶
The @composite
decorator lets you combine other strategies in more or less
arbitrary ways. It’s probably the main thing you’ll want to use for
complicated custom strategies.
The composite decorator works by giving you a function as the first argument that you can use to draw examples from other strategies. For example, the following gives you a list and an index into it:
>>> @composite
... def list_and_index(draw, elements=integers()):
... xs = draw(lists(elements, min_size=1))
... i = draw(integers(min_value=0, max_value=len(xs)  1))
... return (xs, i)
draw(s)
is a function that should be thought of as returning s.example()
,
except that the result is reproducible and will minimize correctly. The
decorated function has the initial argument removed from the list, but will
accept all the others in the expected order. Defaults are preserved.
>>> list_and_index()
list_and_index()
>>> list_and_index().example()
([21904], 0)
>>> list_and_index(booleans())
list_and_index(elements=booleans())
>>> list_and_index(booleans()).example()
([True], 0)
Note that the repr will work exactly like it does for all the builtin strategies: it will be a function that you can call to get the strategy in question, with values provided only if they do not match the defaults.
You can use assume
inside composite functions:
@composite
def distinct_strings_with_common_characters(draw):
x = draw(text(), min_size=1)
y = draw(text(alphabet=x))
assume(x != y)
return (x, y)
This works as assume
normally would, filtering out any examples for which the
passed in argument is falsey.
Drawing interactively in tests¶
There is also the data()
strategy, which gives you a means of using
strategies interactively. Rather than having to specify everything up front in
@given
you can draw from strategies in the body of your test:
@given(data())
def test_draw_sequentially(data):
x = data.draw(integers())
y = data.draw(integers(min_value=x))
assert x < y
If the test fails, each draw will be printed with the falsifying example. e.g. the above is wrong (it has a boundary condition error), so will print:
Falsifying example: test_draw_sequentially(data=data(...))
Draw 1: 0
Draw 2: 0
As you can see, data drawn this way is simplified as usual.
Test functions using the data()
strategy do not support explicit
@example(...)
s. In this case, the best option is usually to construct
your data with @composite
or the explicit example, and unpack this within
the body of the test.
Optionally, you can provide a label to identify values generated by each call
to data.draw()
. These labels can be used to identify values in the output
of a falsifying example.
For instance:
@given(data())
def test_draw_sequentially(data):
x = data.draw(integers(), label='First number')
y = data.draw(integers(min_value=x), label='Second number')
assert x < y
will produce the output:
Falsifying example: test_draw_sequentially(data=data(...))
Draw 1 (First number): 0
Draw 2 (Second number): 0