Skip to content

Commit

Permalink
Add a Hypothesis plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD committed Nov 7, 2020
1 parent 31bc243 commit dc2624e
Show file tree
Hide file tree
Showing 13 changed files with 551 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dist/
.mypy_cache/
test.py
.coverage
.hypothesis
/htmlcov/
/benchmarks/*.json
/docs/.changelog.md
Expand Down
1 change: 1 addition & 0 deletions changes/2017-Zac-HD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier [property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/) with Pydantic's custom types - [usage details here](https://pydantic-docs.helpmanual.io/hypothesis_plugin/)
26 changes: 26 additions & 0 deletions docs/examples/hypothesis_property_based_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import typing
import pydantic
from hypothesis import given, strategies as st


class Model(pydantic.BaseModel):
redis: pydantic.RedisDsn
users: typing.List[pydantic.EmailStr]
probability: pydantic.confloat(ge=0, lt=1)


@given(st.builds(Model))
def test_property(instance):
# Hypothesis calls this test function many times with varied Models,
# so you can write a test that should pass given *any* instance.
assert instance.redis.startswith('redis://')
assert all('@' in email for email in instance.users)
assert isinstance(instance.probability, float)
assert 0 <= instance.probability < 1


@given(st.builds(Model, probability=st.floats(0, 0.2)))
def test_unlucky_users(instance):
# This test shows how you can override specific fields,
# and let Hypothesis fill in any you don't care about.
assert instance.probability <= 0.2
31 changes: 31 additions & 0 deletions docs/hypothesis_plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[Hypothesis](https://hypothesis.readthedocs.io/) is the Python library for
[property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/).

Hypothesis can infer how to construct type-annotated classes, and supports builtin types,
many standard library types, and generic types from the
[`typing`](https://docs.python.org/3/library/typing.html) and
[`typing_extensions`](https://pypi.org/project/typing-extensions/) modules by default.
Pydantic's [plugin registers](https://hypothesis.readthedocs.io/en/latest/changes.html#v5-29-0)
our [custom types](usage/types.md) like `PaymentCardNumber` and `PositiveFloat`, so that the
[`st.builds()`](https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.builds)
and [`st.from_type()`](https://hypothesis.readthedocs.io/en/latest/data.html#hypothesis.strategies.from_type)
strategies support them without any user configuration.

Note that the strategies for email addresses, URLs, and `PyObject` names are designed
to work in a wide range of circumstances, rather than seek out edge cases which are
especially likely to behave badly.


### Example tests
```py
{!.tmp_examples/hypothesis_property_based_test.py!}
```
_(This script is complete, it should run "as is")_


### Use with JSON Schemas
To test client-side code, you can use [`Model.schema()`](usage/models.md) with the
[`hypothesis-jsonschema` package](https://pypi.org/project/hypothesis-jsonschema/)
to generate arbitrary JSON instances matching the schema.
For web API testing, [Schemathesis](https://schemathesis.readthedocs.io) provides
a higher-level wrapper and can detect both errors and security vulnerabilities.
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ansi2html==1.5.2
flake8==3.8.4
flake8-quotes==3.2.0
hypothesis==5.41.1
mkdocs==1.1.2
mkdocs-exclude==1.0.2
mkdocs-material==6.1.0
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ nav:
- benchmarks.md
- 'Mypy plugin': mypy_plugin.md
- 'PyCharm plugin': pycharm_plugin.md
- 'Hypothesis plugin': hypothesis_plugin.md
- 'Code Generation': datamodel_code_generator.md
- changelog.md

Expand Down

0 comments on commit dc2624e

Please sign in to comment.