Skip to content

Commit

Permalink
docs: Use blacken-docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Stranger6667 committed Jan 6, 2021
1 parent a9cb16e commit b0b6ea6
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 108 deletions.
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Expand Up @@ -40,6 +40,12 @@ repos:
- id: black
types: [python]

- repo: https://github.com/asottile/blacken-docs
rev: v1.9.1
hooks:
- id: blacken-docs
additional_dependencies: [ black==20.8b1 ]

- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.6.4
hooks:
Expand Down
1 change: 1 addition & 0 deletions README.rst
Expand Up @@ -54,6 +54,7 @@ Or in your Python tests:
schema = schemathesis.from_uri("http://0.0.0.0:8081/schema.yaml")
@schema.parametrize()
def test_api(case):
case.call_and_validate()
Expand Down
4 changes: 3 additions & 1 deletion docs/cli.rst
Expand Up @@ -435,6 +435,7 @@ To use your custom checks with Schemathesis CLI, you need to register them via t
import schemathesis
@schemathesis.register_check
def new_check(response, case):
# some awesome assertions!
Expand All @@ -457,10 +458,11 @@ response code is ``200``.
import schemathesis
@schemathesis.register_check
def conditional_check(response, case):
if response.status_code == 200:
# some awesome assertions!
... # some awesome assertions!
else:
# check not relevant to this response, skip test
return True
Expand Down
36 changes: 21 additions & 15 deletions docs/extending.rst
Expand Up @@ -19,19 +19,24 @@ To register a new hook function, you need to use special decorators - ``register
import schemathesis
@schemathesis.hooks.register
def before_generate_query(context, strategy):
return strategy.filter(lambda x: x["id"].isdigit())
schema = schemathesis.from_uri("http://0.0.0.0:8080/swagger.json")
@schema.hooks.register("before_generate_query")
def schema_hook(context, strategy):
return strategy.filter(lambda x: int(x["id"]) % 2 == 0)
def before_generate_headers(context, strategy):
return strategy.filter(lambda x: len(x["id"]) > 5)
@schema.hooks.apply(before_generate_headers)
@schema.parametrize()
def test_api(case):
Expand Down Expand Up @@ -104,9 +109,7 @@ Then, with this hook, you can query the database for some existing order and set
.. code:: python
def before_process_path(
context: schemathesis.hooks.HookContext,
path: str,
methods: Dict[str, Any]
context: schemathesis.hooks.HookContext, path: str, methods: Dict[str, Any]
) -> None:
if path == "/orders/{order_id}":
order_id = database.get_orders().first().id
Expand Down Expand Up @@ -138,9 +141,7 @@ With this hook, you can add additional test cases that will be executed in Hypot
context: schemathesis.hooks.HookContext,
examples: List[Case],
) -> None:
examples.append(
Case(operation=context.operation, query={"foo": "bar"})
)
examples.append(Case(operation=context.operation, query={"foo": "bar"}))
To load CLI hooks, you need to put them into a separate module and pass an importable path in the ``--pre-run`` CLI option.
For example, you have your hooks definition in ``myproject/hooks.py``, and ``myproject`` is importable:
Expand All @@ -161,17 +162,18 @@ This hook allows you to extend or redefine a list of CLI handlers that will be u
from schemathesis.cli.handlers import EventHandler
from schemathesis.runner import events
class SimpleHandler(EventHandler):
class SimpleHandler(EventHandler):
def handle_event(self, context, event):
if isinstance(event, events.Finished):
click.echo("Done!")
@schemathesis.hooks.register
def after_init_cli_run_handlers(
context: HookContext,
handlers: List[EventHandler],
execution_context: ExecutionContext
execution_context: ExecutionContext,
) -> None:
handlers[:] = [SimpleHandler()]
Expand All @@ -191,7 +193,9 @@ behavior in the API by changing the duplicate request's specific details.

.. code:: python
def add_case(context: HookContext, case: Case, response: GenericResponse) -> Optional[Case]:
def add_case(
context: HookContext, case: Case, response: GenericResponse
) -> Optional[Case]:
case.headers["Content-Type"] = "application/json"
return case
Expand All @@ -200,7 +204,9 @@ an additional test case if the original case received a successful response from

.. code:: python
def add_case(context: HookContext, case: Case, response: GenericResponse) -> Optional[Case]:
def add_case(
context: HookContext, case: Case, response: GenericResponse
) -> Optional[Case]:
if 200 <= response.status_code < 300:
# if the original case was successful, see if an invalid content type header produces a failure
case.headers["Content-Type"] = "invalid/content/type"
Expand All @@ -225,9 +231,7 @@ You can teach Schemathesis to generate values that fit this format by registerin

.. code-block:: python
strategy = strategies.from_regex(
r"\A4[0-9]{15}\Z"
).filter(luhn_validator)
strategy = strategies.from_regex(r"\A4[0-9]{15}\Z").filter(luhn_validator)
schemathesis.register_string_format("visa_cards", strategy)
Schemathesis test runner
Expand All @@ -242,7 +246,7 @@ It can run tests against the given schema URI and will do some simple checks for
events = runner.prepare("http://127.0.0.1:8080/swagger.json")
for event in events:
# do something with event
... # do something with event
``runner.prepare`` creates a generator that yields events of different kinds - ``BeforeExecution``, ``AfterExecution``, etc.
They provide a lot of useful information about what happens during tests, but your responsibility is handling these events.
Expand All @@ -256,9 +260,11 @@ You can provide your custom checks to the execute function; the check is a calla
from datetime import timedelta
from schemathesis import runner, models
def not_too_long(response, case: models.Case):
assert response.elapsed < timedelta(milliseconds=300)
events = runner.prepare("http://127.0.0.1:8080/swagger.json", checks=[not_too_long])
for event in events:
# do something with event
... # do something with event
5 changes: 2 additions & 3 deletions docs/graphql.rst
Expand Up @@ -11,9 +11,8 @@ Usage
import schemathesis
schema = schemathesis.graphql.from_url(
"https://bahnql.herokuapp.com/graphql"
)
schema = schemathesis.graphql.from_url("https://bahnql.herokuapp.com/graphql")
@schema.parametrize()
@settings(deadline=None)
Expand Down
5 changes: 4 additions & 1 deletion docs/how.rst
Expand Up @@ -101,6 +101,7 @@ First, let's define a function that will transform lists of dictionaries to CSV
import csv
from io import StringIO
def to_csv(data):
if not data:
# Empty CSV file
Expand All @@ -124,6 +125,7 @@ Second, register a serializer class via the ``schemathesis.serializers.register`
import schemathesis
@schemathesis.serializers.register("text/csv")
class CSVSerializer:
...
Expand All @@ -135,8 +137,9 @@ Third, the serializer should have two methods - ``as_requests`` and ``as_werkzeu
.. code-block:: python
...
class CSVSerializer:
class CSVSerializer:
def as_requests(self, context, value):
return {"data": to_csv(value)}
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Expand Up @@ -23,6 +23,7 @@ Or in your Python tests:
schema = schemathesis.from_uri("http://example.com/swagger.json")
@schema.parametrize()
def test_api(case):
case.call_and_validate()
Expand Down
73 changes: 40 additions & 33 deletions docs/python.rst
Expand Up @@ -15,6 +15,7 @@ The following test will load the API schema from ``http://0.0.0.0:8080/swagger.j
schema = schemathesis.from_uri("http://example.com/swagger.json")
@schema.parametrize()
def test_api(case):
case.call_and_validate()
Expand Down Expand Up @@ -71,8 +72,7 @@ then you can skip them by passing ``skip_deprecated_operations=True`` to loaders
.. code:: python
schema = schemathesis.from_uri(
"http://example.com/swagger.json",
skip_deprecated_operations=True
"http://example.com/swagger.json", skip_deprecated_operations=True
)
Tests configuration
Expand All @@ -86,9 +86,12 @@ For example, in the following test, Schemathesis will test each API operation wi
from hypothesis import settings, Phase
...
@schema.parametrize()
@settings(max_examples=1000)
def test_api(case):
...
See the whole list of available options in the `Hypothesis documentation <https://hypothesis.readthedocs.io/en/latest/settings.html#available-settings>`_.

Expand All @@ -114,10 +117,7 @@ then you can use the ``port`` argument:

.. code:: python
schema = schemathesis.from_uri(
"http://app.com/api/openapi.json",
port=8081
)
schema = schemathesis.from_uri("http://app.com/api/openapi.json", port=8081)
This code will run tests against ``http://app.com:8081/api/openapi.json``.

Expand Down Expand Up @@ -146,8 +146,7 @@ But want to send requests to a local test server which is running at ``http://12
.. code:: python
schema = schemathesis.from_path(
"/tmp/openapi.json",
base_url="http://127.0.0.1:8000/v2"
"/tmp/openapi.json", base_url="http://127.0.0.1:8000/v2"
)
Note that you need to provide the full base URL, which includes the ``basePath`` part.
Expand Down Expand Up @@ -221,6 +220,7 @@ This approach requires an initialized application instance to generate the API s
import schemathesis
@pytest.fixture
def web_app(db):
# some dynamically built application
Expand All @@ -237,8 +237,10 @@ This approach requires an initialized application instance to generate the API s
return schemathesis.from_dict(app.openapi())
schema = schemathesis.from_pytest_fixture("web_app")
@schema.parametrize()
def test_api(case):
...
Expand Down Expand Up @@ -269,6 +271,7 @@ If you don't use Schemathesis for data generation, you can still utilize respons
schema = schemathesis.from_uri("http://0.0.0.0/openapi.json")
def test_api():
response = requests.get("http://0.0.0.0/api/users")
# Raises a validation error
Expand Down Expand Up @@ -300,10 +303,7 @@ In the following example we test a hypothetical ``/api/auth/password/reset/`` op
def test_password_reset(data, case, user):
if data.draw(st.booleans()):
case.body["token"] = data.draw(
(
st.emails() |
st.just(user.email)
).map(create_reset_password_token)
(st.emails() | st.just(user.email)).map(create_reset_password_token)
)
response = case.call_asgi(app=app)
case.validate_response(response)
Expand All @@ -329,16 +329,20 @@ in this case, the test execution will go much faster.
app = Flask("test_app")
@app.route("/schema.json")
def schema():
return {...} # Your API schema
@app.route("/v1/users", methods=["GET"])
def users():
return jsonify([{"name": "Robin"}])
schema = schemathesis.from_wsgi("/schema.json", app)
@schema.parametrize()
def test_api(case):
response = case.call_wsgi()
Expand All @@ -359,8 +363,8 @@ You only need to specify strategies for ``hypothesis.given``:
schema = schemathesis.from_uri("http://0.0.0.0:8080/schema.json")
new_pet_strategy = schema["/v2/pet"]["POST"].as_strategy()
class TestAPI(TestCase):
class TestAPI(TestCase):
@given(case=new_pet_strategy)
def test_pets(self, case):
case.call_and_validate()
Expand All @@ -377,6 +381,7 @@ seamlessly combines your API schema with ``pytest``-style parametrization and pr
schema = schemathesis.from_uri("http://example.com/swagger.json")
@schema.parametrize()
def test_api(case):
case.call_and_validate()
Expand Down Expand Up @@ -404,24 +409,26 @@ For convenience, you can explore the schemas and strategies manually:

.. code:: python
>>> import schemathesis
>>> schema = schemathesis.from_uri("http://api.com/schema.json")
>>> operation = schema["/pet"]["POST"]
>>> strategy = operation.as_strategy()
>>> strategy.example()
Case(
path='/pet',
method='POST',
path_parameters={},
headers={},
cookies={},
query={},
body={
'name': '\x15.\x13\U0008f42a',
'photoUrls': ['\x08\U0009f29a', '']
},
form_data={}
)
import schemathesis
schema = schemathesis.from_uri("http://api.com/schema.json")
operation = schema["/pet"]["POST"]
strategy = operation.as_strategy()
print(strategy.example())
# Case(
# path='/pet',
# method='POST',
# path_parameters={},
# headers={},
# cookies={},
# query={},
# body={
# 'name': '\x15.\x13\U0008f42a',
# 'photoUrls': ['\x08\U0009f29a', '']
# },
# form_data={}
# )
Schema instances implement the ``Mapping`` protocol.

Expand All @@ -430,5 +437,5 @@ Schema instances implement the ``Mapping`` protocol.
.. code:: python
# your ``basePath`` is ``/api/v1``
>>> schema["/pet"]["POST"] # VALID
>>> schema["/api/v1/pet"]["POST"] # INVALID
schema["/pet"]["POST"] # VALID
schema["/api/v1/pet"]["POST"] # INVALID

0 comments on commit b0b6ea6

Please sign in to comment.