Skip to content

Commit

Permalink
mbelaiev/matchers_docs (#466)
Browse files Browse the repository at this point in the history
Improve matchers docs.

Co-authored-by: Mark Story <[email protected]>
  • Loading branch information
beliaev-maksim and markstory authored Jan 12, 2022
1 parent 776ada5 commit 69b7df7
Showing 1 changed file with 78 additions and 14 deletions.
92 changes: 78 additions & 14 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,16 @@ match (``list``)
Matching Requests
-----------------

Matching Request Body Contents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When adding responses for endpoints that are sent request data you can add
matchers to ensure your code is sending the right parameters and provide
different responses based on the request body contents. Responses provides
matchers for JSON and URL-encoded request bodies and you can supply your own for
other formats.
different responses based on the request body contents. ``responses`` provides
matchers for JSON and URL-encoded request bodies.

URL-encoded data
""""""""""""""""

.. code-block:: python
Expand All @@ -181,14 +186,46 @@ other formats.
)
requests.post("http://calc.com/sum", data={"left": 1, "right": 3})
JSON encoded data
"""""""""""""""""

Matching JSON encoded data can be done with ``matchers.json_params_matcher()``.
If your application uses other encodings you can build your own matcher that
returns ``True`` or ``False`` if the request parameters match. Your matcher can
expect a ``request`` parameter to be provided by responses.

Similarly, you can use the ``matchers.query_param_matcher`` function to match
against the ``params`` request parameter.
Note, you must set ``match_querystring=False``
.. code-block:: python
import responses
import requests
from responses import matchers
@responses.activate
def test_calc_api():
responses.add(
method=responses.POST,
url="http://example.com/",
body="one",
match=[matchers.json_params_matcher({"page": {"name": "first", "type": "json"}})],
)
resp = requests.request(
"POST",
"http://example.com/",
headers={"Content-Type": "application/json"},
json={"page": {"name": "first", "type": "json"}},
)
Query Parameters Matcher
^^^^^^^^^^^^^^^^^^^^^^^^

Query Parameters as a Dictionary
""""""""""""""""""""""""""""""""

You can use the ``matchers.query_param_matcher`` function to match
against the ``params`` request parameter. Just use the same dictionary as you
will use in ``params`` argument in ``request``.

Note, do not use query parameters as part of the URL. Avoid using ``match_querystring``
deprecated argument.

.. code-block:: python
Expand Down Expand Up @@ -216,7 +253,11 @@ Note, you must set ``match_querystring=False``
assert resp.request.params == params
As alternative, you can use query string value in ``matchers.query_string_matcher``
Query Parameters as a String
""""""""""""""""""""""""""""

As alternative, you can use query string value in ``matchers.query_string_matcher`` to match
query parameters in your request

.. code-block:: python
Expand All @@ -235,9 +276,14 @@ As alternative, you can use query string value in ``matchers.query_string_matche
my_func()
Request Keyword Arguments Matcher
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To validate request arguments use the ``matchers.request_kwargs_matcher`` function to match
against the request kwargs.
Note, only arguments provided to ``matchers.request_kwargs_matcher`` will be validated

Note, only arguments provided to ``matchers.request_kwargs_matcher`` will be validated.

.. code-block:: python
Expand All @@ -260,6 +306,10 @@ Note, only arguments provided to ``matchers.request_kwargs_matcher`` will be val
# >>> Arguments don't match: {stream: True, verify: True} doesn't match {stream: True, verify: False}
Request multipart/form-data Data Validation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To validate request body and headers for ``multipart/form-data`` data you can use
``matchers.multipart_matcher``. The ``data``, and ``files`` parameters provided will be compared
to the request:
Expand All @@ -283,6 +333,8 @@ to the request:
my_func()
# >>> raises ConnectionError: multipart/form-data doesn't match. Request body differs.
Request Fragment Identifier Validation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To validate request URL fragment identifier you can use ``matchers.fragment_identifier_matcher``.
The matcher takes fragment string (everything after ``#`` sign) as input for comparison:
Expand Down Expand Up @@ -310,8 +362,8 @@ The matcher takes fragment string (everything after ``#`` sign) as input for com
run()
Matching Request Headers
------------------------
Request Headers Validation
^^^^^^^^^^^^^^^^^^^^^^^^^^

When adding responses you can specify matchers to ensure that your code is
sending the right headers and provide different responses based on the request
Expand Down Expand Up @@ -393,6 +445,18 @@ include any additional headers.
resp = session.send(prepped)
assert resp.text == "hello world"
Creating Custom Matcher
^^^^^^^^^^^^^^^^^^^^^^^

If your application requires other encodings or different data validation you can build
your own matcher that returns ``Tuple[matches: bool, reason: str]``.
Where boolean represents ``True`` or ``False`` if the request parameters match and
the string is a reason in case of match failure. Your matcher can
expect a ``PreparedRequest`` parameter to be provided by ``responses``.

Note, ``PreparedRequest`` is customized and has additional attributes ``params`` and ``req_kwargs``.

Response Registry
---------------------------

Expand Down Expand Up @@ -853,7 +917,7 @@ your code against:
Alternatively, you can always run a single test. See documentation below.

Unit tests
"""""""""
""""""""""

Responses uses `Pytest <https://docs.pytest.org/en/latest/>`_ for
testing. You can run all tests by:
Expand Down

0 comments on commit 69b7df7

Please sign in to comment.