Often you need to modify certain aspects of Schemathesis behavior, adjust data generation, modify requests before sending, and so on. Schemathesis offers a hook mechanism which is similar to the pytest's one.
Basing on the scope of the changes there are three levels of hooks:
- Global. These hooks applied to all schemas in the test run;
- Schema-local. Applied only for specific schema instance;
- Test function specific. Applied only for a specific test function;
To register a new hook function you need to use special decorators - register
for global and schema-local hooks and apply
for test-specific ones:
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 function_hook(context, strategy):
return strategy.filter(lambda x: len(x["id"]) > 5)
@schema.hooks.apply("before_generate_query", function_hook)
@schema.parametrize()
def test_api(case):
...
By default register
functions will check the registered hook name to determine when to run it (see all hook specifications in the section below), but to avoid name collisions you can provide a hook name as an argument to register
.
Also, these decorators will check the signature of your hook function to match the specification. Each hook should accept context
as the first argument, that provides additional context for hook execution.
Hooks registered on the same level will be applied in the order of registration. When there are multiple hooks in the same hook location, then the global ones will be applied first.
These hooks can be applied both in CLI and in-code use cases.
This is a group of six hooks that share the same purpose - adjust data generation for specific request's part.
before_generate_path_parameters
before_generate_headers
before_generate_cookies
before_generate_query
before_generate_body
before_generate_form_data
They have the same signature that looks like this:
def before_generate_query(
context: schemathesis.hooks.HookContext,
strategy: hypothesis.strategies.SearchStrategy,
) -> hypothesis.strategies.SearchStrategy:
pass
strategy
is a Hypothesis strategy that will generate a certain request part. For example, your endpoint under test expects id
query parameter that is a number and you'd like to have only values that have at least three occurrences of "1". Then your hook might look like this:
def before_generate_query(context, strategy):
return strategy.filter(lambda x: str(x["id"]).count("1") >= 3)