Skip to content

Commit

Permalink
chore: Validate requests kwargs to catch cases when the ASGI integr…
Browse files Browse the repository at this point in the history
…ation is used, but the proper ASGI client is not supplied
  • Loading branch information
Stranger6667 committed Feb 22, 2022
1 parent 2fee032 commit 7ca318e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Changelog
`Unreleased`_ - TBD
-------------------

**Changed**

- Validate ``requests`` kwargs to catch cases when the ASGI integration is used, but the proper ASGI client is not supplied. `#1335`_

`3.13.3`_ - 2022-02-20
----------------------

Expand Down Expand Up @@ -2339,6 +2343,7 @@ Deprecated
.. _#1342: https://github.com/schemathesis/schemathesis/issues/1342
.. _#1340: https://github.com/schemathesis/schemathesis/issues/1340
.. _#1336: https://github.com/schemathesis/schemathesis/issues/1336
.. _#1335: https://github.com/schemathesis/schemathesis/issues/1335
.. _#1331: https://github.com/schemathesis/schemathesis/issues/1331
.. _#1328: https://github.com/schemathesis/schemathesis/issues/1328
.. _#1325: https://github.com/schemathesis/schemathesis/issues/1325
Expand Down
18 changes: 18 additions & 0 deletions docs/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,24 @@ in this case, the test execution will go much faster.
response = case.call_wsgi()
case.validate_response(response)
If you don't supply the ``app`` argument to the loader, make sure you pass your test client when running tests:

.. code-block:: python
@pytest.fixture()
def app_schema(client):
openapi = client.app.openapi()
return schemathesis.from_dict(openapi)
schema = schemathesis.from_pytest_fixture("app_schema")
@schema.parametrize()
def test_api(case, client):
# The `session` argument must be supplied.
case.call_and_validate(session=client)
Unittest support
----------------

Expand Down
24 changes: 20 additions & 4 deletions src/schemathesis/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
Union,
cast,
)
from urllib.parse import quote, unquote, urljoin, urlsplit, urlunsplit
from urllib.parse import quote, unquote, urljoin, urlparse, urlsplit, urlunsplit

import attr
import curlify
Expand Down Expand Up @@ -314,14 +314,15 @@ def call(
**kwargs: Any,
) -> requests.Response:
"""Make a network call with `requests`."""
data = self.as_requests_kwargs(base_url, headers)
data.update(kwargs)
data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT / 1000)
if session is None:
validate_vanilla_requests_kwargs(data)
session = requests.Session()
close_session = True
else:
close_session = False
data = self.as_requests_kwargs(base_url, headers)
data.update(kwargs)
data.setdefault("timeout", DEFAULT_RESPONSE_TIMEOUT / 1000)
try:
response = session.request(**data) # type: ignore
except requests.Timeout as exc:
Expand Down Expand Up @@ -474,6 +475,21 @@ def partial_deepcopy(self) -> "Case":
)


def validate_vanilla_requests_kwargs(data: Dict[str, Any]) -> None:
"""Check arguments for `requests.Session.request`.
Some arguments can be valid for cases like ASGI integration, but at the same time they won't work for the regular
`requests` calls. In such cases we need to avoid an obscure error message, that comes from `requests`.
"""
url = data["url"]
if not urlparse(url).netloc:
raise RuntimeError(
"The URL should be absolute, so Schemathesis knows where to send the data. \n"
f"If you use the ASGI integration, please supply your test client "
f"as the `session` argument to `call`.\nURL: {url}"
)


BACKSLASH = "\\"
SINGLE_QUOTE = "'"
ESCAPED_SINGLE_QUOTE = "\\'"
Expand Down
13 changes: 13 additions & 0 deletions test/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,19 @@ def test(case):
test()


@pytest.mark.operations("success")
def test_call_asgi_and_validate(fastapi_app):
api_schema = schemathesis.from_dict(fastapi_app.openapi())

@given(case=api_schema["/users"]["GET"].as_strategy())
@settings(max_examples=1)
def test(case):
with pytest.raises(RuntimeError, match="The URL should be absolute"):
case.call_and_validate()

test()


def test_case_partial_deepcopy(swagger_20):
operation = APIOperation("/example/path", "GET", {}, swagger_20)
original_case = Case(
Expand Down

0 comments on commit 7ca318e

Please sign in to comment.