Skip to content

Commit 2f4f6b5

Browse files
pradeep90sobolevn
andauthored
Allow users to override hardcoded hypothesis strategies (#2066)
Co-authored-by: sobolevn <mail@sobolevn.me>
1 parent 983056c commit 2f4f6b5

File tree

8 files changed

+583
-339
lines changed

8 files changed

+583
-339
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ See [0Ver](https://0ver.org/).
2828

2929
- Make `hypothesis` plugin test laws from user-defined interfaces too
3030
- Make `hypothesis` plugin accept user-defined strategies
31+
- Allow users to override the `hypothesis` plugin's strategies for types, such
32+
as `TypeVar` and `Callable`.
3133

3234
### Bugfixes
3335

docs/pages/contrib/hypothesis_plugins.rst

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,8 @@ So, you don't have to. Example:
3232
3333
assert st.from_type(Result).example()
3434
35-
This is a convenience thing only.
36-
37-
38-
strategy_from_container
39-
-----------------------
40-
41-
We provide a utility function
42-
to create ``hypothesis`` strategy from any container.
43-
44-
You can use it to easily register your own containers.
45-
46-
.. code:: python
47-
48-
from hypothesis import strategies as st
49-
from returns.contrib.hypothesis.containers import strategy_from_container
50-
51-
st.register_type_strategy(
52-
YourContainerClass,
53-
strategy_from_container(YourContainerClass),
54-
)
55-
56-
You can also pass ``use_init`` keyword argument
57-
if you wish to use ``__init__`` method to instantiate your containers.
58-
Turned off by default.
59-
Example:
60-
61-
.. code:: python
62-
63-
st.register_type_strategy(
64-
YourContainerClass,
65-
strategy_from_container(YourContainerClass, use_init=True),
66-
)
67-
68-
Or you can write your own ``hypothesis`` strategy. It is also fine.
35+
This means you can use ``Result``, ``Maybe``, etc. in your own property tests,
36+
and ``hypothesis`` will generate values for them as expected.
6937

7038

7139
check_all_laws
@@ -140,8 +108,26 @@ like ``Future``, ``ReaderFutureResult``, etc
140108
that have complex ``__init__`` signatures.
141109
And we don't want to mess with them.
142110

143-
You can also register a custom strategy to be used when running your
144-
container's laws:
111+
Warning::
112+
Checking laws is not compatible with ``pytest-xdist``,
113+
because we use a lot of global mutable state there.
114+
Please, use ``returns_lawful`` marker
115+
to exclude them from ``pytest-xdist`` execution plan.
116+
117+
118+
Registering Custom Strategies when Checking Laws
119+
------------------------------------------------
120+
121+
``hypothesis`` works by looking up strategies for the provided type
122+
annotations. Given that the types provided by ``returns`` are very complicated
123+
and not really native to Python, they may not be understood by ``hypothesis``,
124+
and you may get runtime exceptions such as ``ResolutionFailed``.
125+
126+
In such cases, you may want to register custom strategies for types for which
127+
``hypothesis`` does not find any strategies.
128+
129+
The main use case is registering a custom strategy to generate your container
130+
when running its laws:
145131

146132
.. code:: python
147133
@@ -150,22 +136,63 @@ container's laws:
150136
151137
check_all_laws(Number, container_strategy=st.builds(Number, st.integers()))
152138
153-
The ``container_strategy`` will be used only when running the tests generated
154-
by the ``check_all_laws`` call above. It will have no effect on any other
155-
property tests that involve ``Number``. You cannot use this argument together
156-
with ``use_init``.
139+
You can also register strategies for other types:
140+
141+
.. code:: python
142+
143+
from hypothesis import strategies as st
144+
145+
check_all_laws(
146+
Number,
147+
container_strategy=st.builds(Number, st.integers()),
148+
type_strategies={Foo: st.builds(Foo, st.text())},
149+
)
150+
151+
These custom strategies will be used only when running the tests generated by
152+
the ``check_all_laws`` call above. They will have no effect on any other
153+
property tests that involve the same types. You cannot use this argument
154+
together with ``use_init``.
155+
156+
157+
Registering Custom Strategies outside Law Tests
158+
-----------------------------------------------
159+
160+
We provide a utility function
161+
to create ``hypothesis`` strategy from any container:
162+
``strategy_from_container``.
163+
164+
You can use it to register your own containers.
165+
166+
.. code:: python
167+
168+
from hypothesis import strategies as st
169+
from returns.contrib.hypothesis.containers import strategy_from_container
170+
171+
st.register_type_strategy(
172+
YourContainerClass,
173+
strategy_from_container(YourContainerClass),
174+
)
175+
176+
You can also pass ``use_init`` keyword argument
177+
if you wish to use ``__init__`` method to instantiate your containers.
178+
Turned off by default.
179+
Example:
180+
181+
.. code:: python
182+
183+
st.register_type_strategy(
184+
YourContainerClass,
185+
strategy_from_container(YourContainerClass, use_init=True),
186+
)
187+
188+
Or you can write your own ``hypothesis`` strategy. It is also fine.
157189

158190
Warning::
159191
Avoid directly registering your container's strategy with ``hypothesis``
160192
using ``st.register_type_strategy``. Because of the way we emulate
161-
higher-kinded types, ``hypothesis`` may mistakenly use the strategy
162-
for other incompatible containers and cause spurious test failures.
163-
164-
Warning::
165-
Checking laws is not compatible with ``pytest-xdist``,
166-
because we use a lot of global mutable state there.
167-
Please, use ``returns_lawful`` marker
168-
to exclude them from ``pytest-xdist`` execution plan.
193+
higher-kinded types, ``hypothesis`` may mistakenly use the strategy for
194+
other incompatible containers and cause spurious test failures. We specify
195+
how to do it just in case you need it and you know what you're doing.
169196

170197

171198
Further reading

0 commit comments

Comments
 (0)