Split docs for better RTFD viewing
Simplified README, not sure how wise that is.
This commit is contained in:
parent
5ec896d63f
commit
4c97632c53
187
README.rst
187
README.rst
@ -17,28 +17,17 @@ requests-mock
|
||||
Intro
|
||||
=====
|
||||
|
||||
`requests-mock` provides a simple way to stub out the HTTP portions or your testing code.
|
||||
`requests-mock` provides a building block to stub out the HTTP `requests`_ portions of your testing code.
|
||||
|
||||
|
||||
What is it
|
||||
The Basics
|
||||
==========
|
||||
|
||||
The `requests`_ library has the concept of `pluggable transport adapters`_.
|
||||
These adapters allow you to register your own handlers for different URIs or protocols.
|
||||
Everything in `requests`_ eventually goes through an adapter to do the transport work.
|
||||
`requests-mock` creates a custom `adatper` that allows you to predefine responses when certain URIs are called.
|
||||
|
||||
The *requests-mock* library at its core is simply a transport adapter that can be preloaded with responses that are returned if certain URIs are requested.
|
||||
This is particularly useful in unit tests where you want to return known responses from HTTP requests without making actual calls.
|
||||
There are then a number of methods provided to get the adapter used.
|
||||
|
||||
As the `requests`_ library has very limited options for how to load and use adapters *requests-mock* also provides a number (currently 1) of ways that to make sure the mock adapter is used.
|
||||
These are only loading mechanisms, they do not contain any logic and can be used as a reference to load the adapter in whatever ways works best for your project.
|
||||
|
||||
Adapter Usage
|
||||
=============
|
||||
|
||||
Creating an Adapter
|
||||
-------------------
|
||||
|
||||
The standard `requests`_ means of using an adapter is to mount it on a created session. This is not the only way to load the adapter, however the same interactions will be used.
|
||||
A simple example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@ -46,160 +35,32 @@ The standard `requests`_ means of using an adapter is to mount it on a created s
|
||||
>>> import requests_mock
|
||||
|
||||
>>> session = requests.Session()
|
||||
>>> adapter = requests_mock.Adapter()
|
||||
>>> adapter = requests_mock.Adater()
|
||||
>>> session.mount('mock', adapter)
|
||||
|
||||
At this point any requests made by the session to a URI starting with `mock://` will be sent to our adapter.
|
||||
|
||||
|
||||
Registering Responses
|
||||
---------------------
|
||||
|
||||
Responses are registered with the `register_uri` function on the adapter.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com', text='Success')
|
||||
>>> adapter.register_uri('GET', 'mock://test.com', text='data')
|
||||
>>> resp = session.get('mock://test.com')
|
||||
>>> resp.text
|
||||
'Success'
|
||||
>>> resp.status_code, resp.text
|
||||
(200, 'data')
|
||||
|
||||
`register_uri` takes the HTTP method, the URI and then information that is used to build the response. This information includes:
|
||||
Obviously having all URLs be `mock://` prefixed isn't going to useful, so there are a number of ways to get the adapter into place.
|
||||
|
||||
:status_code: The HTTP status response to return. Defaults to 200.
|
||||
:reason: The reason text that accompanies the Status (e.g. 'OK' in '200 OK')
|
||||
:headers: A dictionary of headers to be included in the response.
|
||||
For more information checkout the `docs`_.
|
||||
|
||||
To specify the body of the response there are a number of options that depend on the format that you wish to return.
|
||||
License
|
||||
=======
|
||||
|
||||
:json: A python object that will be converted to a JSON string.
|
||||
:text: A unicode string. This is typically what you will want to use for regular textual content.
|
||||
:content: A byte string. This should be used for including binary data in responses.
|
||||
:body: A file like object that contains a `.read()` function.
|
||||
:raw: A prepopulated urllib3 response to be returned.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
not use this file except in compliance with the License. You may obtain
|
||||
a copy of the License at
|
||||
|
||||
These options are named to coincide with the parameters on a `requests.Response` object. For example:
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/1', json={'a': 'b'}, status_code=200)
|
||||
>>> resp = session.get('mock://test.com/1')
|
||||
>>> resp.json()
|
||||
{'a': 'b'}
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/2', text='Not Found', status_code=404)
|
||||
>>> resp = session.get('mock://test.com/2')
|
||||
>>> resp.text
|
||||
'Not Found'
|
||||
>>> resp.status_code
|
||||
404
|
||||
|
||||
It only makes sense to provide at most one body element per response.
|
||||
|
||||
Dynamic Response
|
||||
----------------
|
||||
|
||||
A callback can be provided in place of any of the body elements.
|
||||
Callbacks must be a function in the form of
|
||||
|
||||
.. code:: python
|
||||
|
||||
def callback(request, context):
|
||||
|
||||
and return a value suitable to the body element that was specified.
|
||||
The elements provided are:
|
||||
|
||||
:request: The `requests.Request` object that was provided.
|
||||
:context: An object containing the collected known data about this response.
|
||||
|
||||
The available properties on the `context` are:
|
||||
|
||||
:headers: The dictionary of headers that are to be returned in the response.
|
||||
:status_code: The status code that is to be returned in the response.
|
||||
:reason: The string HTTP status code reason that is to be returned in the response.
|
||||
|
||||
These parameters are populated initially from the variables provided to the `register_uri` function and if they are modified on the context object then those changes will be reflected in the response.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def text_callback(request, context):
|
||||
... context.status_code = 200
|
||||
... context.headers['Test1'] = 'value1'
|
||||
... return 'response'
|
||||
...
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/3', text=text_callback, headers={'Test2': 'value2'}, status_code=400)
|
||||
>>> resp = session.get('mock://test.com/3')
|
||||
>>> resp.status_code, resp.headers, resp.text
|
||||
(200, {'Test1': 'value1', 'Test2': 'value2'}, 'response')
|
||||
|
||||
Response Lists
|
||||
--------------
|
||||
|
||||
Multiple responses can be provided to be returned in order by specifying the keyword parameters in a list.
|
||||
If the list is exhausted then the last response will continue to be returned.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/4', [{'text': 'resp1', 'status_code': 300},
|
||||
... {'text': 'resp2', 'status_code': 200}])
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(300, 'resp1')
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(200, 'resp2')
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(200, 'resp2')
|
||||
|
||||
|
||||
Request Matching
|
||||
================
|
||||
|
||||
Whilst it is preferable to provide the whole URI to `register_uri` it is possible to just specify components.
|
||||
|
||||
You can specify a protocol-less path:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '//test.com/5', text='resp')
|
||||
>>> session.get('mock://test.com/5').text
|
||||
'resp'
|
||||
|
||||
or you can specify just a path:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/6', text='resp')
|
||||
>>> session.get('mock://test.com/6').text
|
||||
'resp'
|
||||
>>> session.get('mock://another.com/6').text
|
||||
'resp'
|
||||
|
||||
Query strings provided to a register will match so long as at least those provided form part of the request.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/7?a=1', text='resp')
|
||||
>>> session.get('mock://test.com/7?a=1&b=2').text
|
||||
'resp'
|
||||
|
||||
>>> session.get('mock://test.com/7?a=3')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
requests_mock.exceptions.NoMockAddress: No mock address: GET mock://test.com/7?a=3
|
||||
|
||||
This can be a problem in certain situations, so if you wish to match only the complete query string there is a flag `complete_qs`:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/8?a=1', complete_qs=True, text='resp')
|
||||
>>> session.get('mock://test.com/8?a=1&b=2')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
requests_mock.exceptions.NoMockAddress: No mock address: GET mock://test.com/8?a=1&b=2
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
.. _requests: http://python-requests.org
|
||||
.. _pluggable transport adapters: http://docs.python-requests.org/en/latest/user/advanced/#transport-adapters
|
||||
|
||||
|
||||
.. _docs: http://requests-mock.readthedocs.org
|
||||
|
126
docs/adapter.rst
Normal file
126
docs/adapter.rst
Normal file
@ -0,0 +1,126 @@
|
||||
=============
|
||||
Adapter Usage
|
||||
=============
|
||||
|
||||
Creating an Adapter
|
||||
===================
|
||||
|
||||
The standard `requests`_ means of using an adapter is to :py:meth:`requests.Session.mount` it on a created session. This is not the only way to load the adapter, however the same interactions will be used.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> import requests
|
||||
>>> import requests_mock
|
||||
|
||||
>>> session = requests.Session()
|
||||
>>> adapter = requests_mock.Adapter()
|
||||
>>> session.mount('mock', adapter)
|
||||
|
||||
At this point any requests made by the session to a URI starting with `mock://` will be sent to our adapter.
|
||||
|
||||
|
||||
Registering Responses
|
||||
=====================
|
||||
|
||||
Responses are registered with the :py:meth:`requests_mock.Adapter.register_uri` function on the adapter.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com', text='Success')
|
||||
>>> resp = session.get('mock://test.com')
|
||||
>>> resp.text
|
||||
'Success'
|
||||
|
||||
:py:meth:`requests_mock.Adapter.register_uri` takes the HTTP method, the URI and then information that is used to build the response. This information includes:
|
||||
|
||||
:status_code: The HTTP status response to return. Defaults to 200.
|
||||
:reason: The reason text that accompanies the Status (e.g. 'OK' in '200 OK')
|
||||
:headers: A dictionary of headers to be included in the response.
|
||||
|
||||
To specify the body of the response there are a number of options that depend on the format that you wish to return.
|
||||
|
||||
:json: A python object that will be converted to a JSON string.
|
||||
:text: A unicode string. This is typically what you will want to use for regular textual content.
|
||||
:content: A byte string. This should be used for including binary data in responses.
|
||||
:body: A file like object that contains a `.read()` function.
|
||||
:raw: A prepopulated :py:class:`urllib3.response.HTTPResponse` to be returned.
|
||||
|
||||
These options are named to coincide with the parameters on a :py:class:`requests.Response` object. For example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/1', json={'a': 'b'}, status_code=200)
|
||||
>>> resp = session.get('mock://test.com/1')
|
||||
>>> resp.json()
|
||||
{'a': 'b'}
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/2', text='Not Found', status_code=404)
|
||||
>>> resp = session.get('mock://test.com/2')
|
||||
>>> resp.text
|
||||
'Not Found'
|
||||
>>> resp.status_code
|
||||
404
|
||||
|
||||
It only makes sense to provide at most one body element per response.
|
||||
|
||||
Dynamic Response
|
||||
================
|
||||
|
||||
A callback can be provided in place of any of the body elements.
|
||||
Callbacks must be a function in the form of
|
||||
|
||||
.. code:: python
|
||||
|
||||
def callback(request, context):
|
||||
|
||||
and return a value suitable to the body element that was specified.
|
||||
The elements provided are:
|
||||
|
||||
:request: The :py:class:`requests.Request` object that was provided.
|
||||
:context: An object containing the collected known data about this response.
|
||||
|
||||
The available properties on the `context` are:
|
||||
|
||||
:headers: The dictionary of headers that are to be returned in the response.
|
||||
:status_code: The status code that is to be returned in the response.
|
||||
:reason: The string HTTP status code reason that is to be returned in the response.
|
||||
|
||||
These parameters are populated initially from the variables provided to the :py:meth:`requests_mock.Adapter.register_uri` function and if they are modified on the context object then those changes will be reflected in the response.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> def text_callback(request, context):
|
||||
... context.status_code = 200
|
||||
... context.headers['Test1'] = 'value1'
|
||||
... return 'response'
|
||||
...
|
||||
>>> adapter.register_uri('GET',
|
||||
... 'mock://test.com/3',
|
||||
... text=text_callback,
|
||||
... headers={'Test2': 'value2'},
|
||||
... status_code=400)
|
||||
>>> resp = session.get('mock://test.com/3')
|
||||
>>> resp.status_code, resp.headers, resp.text
|
||||
(200, {'Test1': 'value1', 'Test2': 'value2'}, 'response')
|
||||
|
||||
Response Lists
|
||||
==============
|
||||
|
||||
Multiple responses can be provided to be returned in order by specifying the keyword parameters in a list.
|
||||
If the list is exhausted then the last response will continue to be returned.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', 'mock://test.com/4', [{'text': 'resp1', 'status_code': 300},
|
||||
... {'text': 'resp2', 'status_code': 200}])
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(300, 'resp1')
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(200, 'resp2')
|
||||
>>> resp = session.get('mock://test.com/4')
|
||||
>>> (resp.status_code, resp.text)
|
||||
(200, 'resp2')
|
||||
|
||||
.. _requests: http://python-requests.org
|
@ -38,7 +38,9 @@ import requests_mock # noqa
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
|
||||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.intersphinx']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
@ -261,3 +263,8 @@ texinfo_documents = [
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
requests_uri = 'http://docs.python-requests.org/en/latest/'
|
||||
urllib3_uri = 'http://urllib3.readthedocs.org/en/latest'
|
||||
intersphinx_mapping = {'requests': (requests_uri, None),
|
||||
'urllib3': (urllib3_uri, None)}
|
||||
|
41
docs/fixture.rst
Normal file
41
docs/fixture.rst
Normal file
@ -0,0 +1,41 @@
|
||||
=======
|
||||
Fixture
|
||||
=======
|
||||
|
||||
`Fixtures`_ provide a way to create reusable state and helper methods in test cases.
|
||||
|
||||
To use the *requests-mock* fixture your tests need to have a dependency on the `fixtures`_ library and the `mock`_ library.
|
||||
These are not provided by *requests-mock*.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The fixture mocks the :py:meth:`requests.Session.get_adapter` method so that all requests will be served by the mock adapter.
|
||||
|
||||
The fixture provides the same interfaces as the adapter.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> import requests
|
||||
>>> from requests_mock import fixture
|
||||
>>> import testtools
|
||||
|
||||
>>> class MyTestCase(testtools.TestCase):
|
||||
|
||||
... TEST_URL = 'http://www.google.com'
|
||||
|
||||
... def setUp(self):
|
||||
... super(MyTestCase, self).setUp()
|
||||
... self.requests_mock = self.useFixture(requests_mock.Mock())
|
||||
... self.requests_mock.register_uri('GET', self.TEST_URL, text='respA')
|
||||
...
|
||||
... def test_method(self):
|
||||
... self.requests_mock.register_uri('POST', self.TEST_URL, text='respB')
|
||||
... resp = requests.get(self.TEST_URL)
|
||||
... self.assertEqual('respA', resp.text)
|
||||
... self.assertEqual(self.TEST_URL, self.requests_mock.last_request.url)
|
||||
...
|
||||
|
||||
|
||||
.. _Fixtures: https://pypi.python.org/pypi/fixtures
|
||||
.. _mock: https://pypi.python.org/pypi/mock
|
@ -1,7 +1,3 @@
|
||||
.. complexity documentation master file, created by
|
||||
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to requests-mock's documentation!
|
||||
======================================
|
||||
@ -9,9 +5,13 @@ Welcome to requests-mock's documentation!
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 3
|
||||
|
||||
readme
|
||||
overview
|
||||
adapter
|
||||
matching
|
||||
|
||||
loading
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
9
docs/loading.rst
Normal file
9
docs/loading.rst
Normal file
@ -0,0 +1,9 @@
|
||||
===============
|
||||
Adapter Loading
|
||||
===============
|
||||
|
||||
Loading can be accomplished in a number of ways:
|
||||
|
||||
.. toctree::
|
||||
|
||||
fixture
|
52
docs/matching.rst
Normal file
52
docs/matching.rst
Normal file
@ -0,0 +1,52 @@
|
||||
================
|
||||
Request Matching
|
||||
================
|
||||
|
||||
Whilst it is preferable to provide the whole URI to :py:meth:`requests_mock.Adapter.register_uri` it is possible to just specify components.
|
||||
|
||||
Basic
|
||||
=====
|
||||
|
||||
You can specify a protocol-less path:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '//test.com/5', text='resp')
|
||||
>>> session.get('mock://test.com/5').text
|
||||
'resp'
|
||||
|
||||
or you can specify just a path:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/6', text='resp')
|
||||
>>> session.get('mock://test.com/6').text
|
||||
'resp'
|
||||
>>> session.get('mock://another.com/6').text
|
||||
'resp'
|
||||
|
||||
Query Strings
|
||||
=============
|
||||
|
||||
Query strings provided to a register will match so long as at least those provided form part of the request.
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/7?a=1', text='resp')
|
||||
>>> session.get('mock://test.com/7?a=1&b=2').text
|
||||
'resp'
|
||||
|
||||
>>> session.get('mock://test.com/7?a=3')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
requests_mock.exceptions.NoMockAddress: No mock address: GET mock://test.com/7?a=3
|
||||
|
||||
This can be a problem in certain situations, so if you wish to match only the complete query string there is a flag `complete_qs`:
|
||||
|
||||
.. code:: python
|
||||
|
||||
>>> adapter.register_uri('GET', '/8?a=1', complete_qs=True, text='resp')
|
||||
>>> session.get('mock://test.com/8?a=1&b=2')
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
requests_mock.exceptions.NoMockAddress: No mock address: GET mock://test.com/8?a=1&b=2
|
15
docs/overview.rst
Normal file
15
docs/overview.rst
Normal file
@ -0,0 +1,15 @@
|
||||
========
|
||||
Overview
|
||||
========
|
||||
|
||||
The `requests`_ library has the concept of `pluggable transport adapters`_.
|
||||
These adapters allow you to register your own handlers for different URIs or protocols.
|
||||
|
||||
The *requests-mock* library at its core is simply a transport adapter that can be preloaded with responses that are returned if certain URIs are requested.
|
||||
This is particularly useful in unit tests where you want to return known responses from HTTP requests without making actual calls.
|
||||
|
||||
As the `requests`_ library has very limited options for how to load and use adapters *requests-mock* also provides a number (currently 1) of ways that to make sure the mock adapter is used.
|
||||
These are only loading mechanisms, they do not contain any logic and can be used as a reference to load the adapter in whatever ways works best for your project.
|
||||
|
||||
.. _requests: http://python-requests.org
|
||||
.. _pluggable transport adapters: http://docs.python-requests.org/en/latest/user/advanced/#transport-adapters
|
@ -1 +1 @@
|
||||
.. include:: ../README.rst
|
||||
.. include:: ../README.rst
|
||||
|
Loading…
x
Reference in New Issue
Block a user