diff --git a/docs/changelog.rst b/docs/changelog.rst index c0ae4854b9..35dd702ace 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,12 @@ Changelog `Unreleased`_ ------------- +Changed +~~~~~~~ + +- Schemas with GET endpoints accepting body are allowed now if schema validation is disabled (via ``--validate-schema=false`` for example). + The usecase is for tools like ElasticSearch that use GET requests with non empty bodies. `#383`_ + `0.23.7`_ - 2020-01-30 ---------------------- @@ -656,6 +662,7 @@ Fixed .. _0.3.0: https://github.com/kiwicom/schemathesis/compare/v0.2.0...v0.3.0 .. _0.2.0: https://github.com/kiwicom/schemathesis/compare/v0.1.0...v0.2.0 +.. _#383: https://github.com/kiwicom/schemathesis/issues/383 .. _#381: https://github.com/kiwicom/schemathesis/issues/381 .. _#378: https://github.com/kiwicom/schemathesis/issues/378 .. _#376: https://github.com/kiwicom/schemathesis/issues/376 diff --git a/src/schemathesis/_hypothesis.py b/src/schemathesis/_hypothesis.py index 2f7788822a..2629969b58 100644 --- a/src/schemathesis/_hypothesis.py +++ b/src/schemathesis/_hypothesis.py @@ -184,7 +184,7 @@ def _get_case_strategy( endpoint: Endpoint, extra_static_parameters: Dict[str, Any], strategies: Dict[str, st.SearchStrategy] ) -> st.SearchStrategy: static_parameters: Dict[str, Any] = {"endpoint": endpoint, **extra_static_parameters} - if endpoint.method == "GET": + if endpoint.schema.validate_schema and endpoint.method == "GET": if endpoint.body is not None: raise InvalidSchema("Body parameters are defined for GET request.") static_parameters["body"] = None diff --git a/src/schemathesis/loaders.py b/src/schemathesis/loaders.py index 5b327f6a00..52c1fafde4 100644 --- a/src/schemathesis/loaders.py +++ b/src/schemathesis/loaders.py @@ -117,13 +117,27 @@ def from_dict( if "swagger" in raw_schema: _maybe_validate_schema(raw_schema, spec_schemas.SWAGGER_20, validate_schema) return SwaggerV20( - raw_schema, location=location, base_url=base_url, method=method, endpoint=endpoint, tag=tag, app=app + raw_schema, + location=location, + base_url=base_url, + method=method, + endpoint=endpoint, + tag=tag, + app=app, + validate_schema=validate_schema, ) if "openapi" in raw_schema: _maybe_validate_schema(raw_schema, spec_schemas.OPENAPI_30, validate_schema) return OpenApi30( - raw_schema, location=location, base_url=base_url, method=method, endpoint=endpoint, tag=tag, app=app + raw_schema, + location=location, + base_url=base_url, + method=method, + endpoint=endpoint, + tag=tag, + app=app, + validate_schema=validate_schema, ) raise ValueError("Unsupported schema type") diff --git a/src/schemathesis/schemas.py b/src/schemathesis/schemas.py index bc14264f83..30bfdb622b 100644 --- a/src/schemathesis/schemas.py +++ b/src/schemathesis/schemas.py @@ -47,6 +47,7 @@ class BaseSchema(Mapping): tag: Optional[Filter] = attr.ib(default=None) # pragma: no mutate app: Any = attr.ib(default=None) # pragma: no mutate hooks: Dict[HookLocation, Hook] = attr.ib(factory=dict) # pragma: no mutate + validate_schema: bool = attr.ib(default=True) # pragma: no mutate def __iter__(self) -> Iterator[str]: return iter(self.endpoints) diff --git a/test/test_hypothesis.py b/test/test_hypothesis.py index f156740b59..a836dcd98a 100644 --- a/test/test_hypothesis.py +++ b/test/test_hypothesis.py @@ -3,6 +3,7 @@ import pytest from hypothesis import HealthCheck, given, settings, strategies +import schemathesis from schemathesis import Case, register_string_format from schemathesis._hypothesis import PARAMETERS, get_case_strategy, get_examples, is_valid_query from schemathesis.exceptions import InvalidSchema @@ -60,6 +61,25 @@ def test_invalid_body_in_get(swagger_20): get_case_strategy(endpoint) +def test_invalid_body_in_get_disable_validation(simple_schema): + schema = schemathesis.from_dict(simple_schema, validate_schema=False) + endpoint = Endpoint( + path="/foo", + method="GET", + definition={}, + schema=schema, + body={"required": ["foo"], "type": "object", "properties": {"foo": {"type": "string"}}}, + ) + strategy = get_case_strategy(endpoint) + + @given(strategy) + @settings(max_examples=1) + def test(case): + assert case.body is not None + + test() + + def test_warning(swagger_20): example = {"name": "John"} endpoint = make_endpoint(swagger_20, query={"example": example})