Doctest fixups

This commit is contained in:
Jamie Lennox 2014-06-23 22:37:36 +10:00
parent 4040a190d6
commit 97fb2bce39
6 changed files with 114 additions and 50 deletions

View File

@ -5,9 +5,9 @@ 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.
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
.. doctest::
>>> import requests
>>> import requests_mock
@ -24,14 +24,14 @@ Registering Responses
Responses are registered with the :py:meth:`requests_mock.Adapter.register_uri` function on the adapter.
.. code:: python
.. doctest::
>>> 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:
: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')
@ -47,7 +47,7 @@ To specify the body of the response there are a number of options that depend on
These options are named to coincide with the parameters on a :py:class:`requests.Response` object. For example:
.. code:: python
.. doctest::
>>> adapter.register_uri('GET', 'mock://test.com/1', json={'a': 'b'}, status_code=200)
>>> resp = session.get('mock://test.com/1')
@ -85,9 +85,9 @@ The available properties on the `context` are:
: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.
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
.. doctest::
>>> def text_callback(request, context):
... context.status_code = 200
@ -109,7 +109,7 @@ 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
.. doctest::
>>> adapter.register_uri('GET', 'mock://test.com/4', [{'text': 'resp1', 'status_code': 300},
... {'text': 'resp2', 'status_code': 200}])

View File

@ -39,6 +39,7 @@ 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.doctest',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx']

View File

@ -14,16 +14,16 @@ The fixture mocks the :py:meth:`requests.Session.get_adapter` method so that all
The fixture provides the same interfaces as the adapter.
.. code:: python
.. doctest::
>>> import requests
>>> from requests_mock.contrib 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())

View File

@ -4,39 +4,70 @@ 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.
The examples in this file are loaded with:
.. doctest::
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
Basic
=====
.. doctest::
:hide:
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
You can specify a protocol-less path:
.. code:: python
.. doctest::
>>> adapter.register_uri('GET', '//test.com/5', text='resp')
>>> session.get('mock://test.com/5').text
'resp'
.. >>> adapter.register_uri('GET', '//test.com/', text='resp')
.. >>> session.get('mock://test.com/').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'
.. doctest::
.. >>> adapter.register_uri('GET', '/path', text='resp')
.. >>> session.get('mock://test.com/path').text
.. 'resp'
.. >>> session.get('mock://another.com/path').text
.. 'resp'
Query Strings
=============
.. doctest::
:hide:
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
Query strings provided to a register will match so long as at least those provided form part of the request.
.. code:: python
.. doctest::
>>> adapter.register_uri('GET', '/7?a=1', text='resp')
>>> session.get('mock://test.com/7?a=1&b=2').text
'resp'
If any part of the query string is wrong then it will not match.
.. doctest::
>>> session.get('mock://test.com/7?a=3')
Traceback (most recent call last):
...
@ -44,7 +75,7 @@ Query strings provided to a register will match so long as at least those provid
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
.. doctest::
>>> adapter.register_uri('GET', '/8?a=1', complete_qs=True, text='resp')
>>> session.get('mock://test.com/8?a=1&b=2')
@ -59,7 +90,16 @@ Matching ANY
There is a special symbol at `requests_mock.ANY` which acts as the wildcard to match anything.
It can be used as a replace for the method and/or the URL.
.. code:: python
.. doctest::
:hide:
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
.. doctest::
>>> adapter.register_uri(requests_mock.ANY, 'mock://test.com/8', text='resp')
>>> session.get('mock://test.com/8').text
@ -67,15 +107,14 @@ It can be used as a replace for the method and/or the URL.
>>> session.post('mock://test.com/8').text
'resp'
.. code:: python
.. doctest::
>>> adapter.register_uri(requests_mock.ANY, requests_mock.ANY, text='resp')
>>> session.get('mock://whatever/you/like')
>>> session.get('mock://whatever/you/like').text
'resp'
>>> session.post('mock://whatever/you/like')
>>> session.post('mock://whatever/you/like').text
'resp'
Regular Expressions
===================
@ -84,13 +123,22 @@ To use this you should pass an object created by :py:func:`re.compile`.
The URL is then matched using :py:meth:`re.regex.search` which means that it will match any component of the url, so if you want to match the start of a URL you will have to anchor it.
.. code:: python
.. doctest::
:hide:
>>> import re
>>> matcher = re.compile('tester.com/a')
>>> adapter.register_uri('GET', matcher, text='resp')
>>> session.get('mock://www.tester.com/a/b').text
'resp'
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
.. doctest::
.. >>> import re
.. >>> matcher = re.compile('tester.com/a')
.. >>> adapter.register_uri('GET', matcher, text='resp')
.. >>> session.get('mock://www.tester.com/a/b').text
.. 'resp'
If you use regular expression matching then *requests-mock* can't do it's normal query string or path only matching, that will need to be part of the expression.
@ -101,12 +149,21 @@ Request Headers
A dictionary of headers can be supplied such that the request will only match if the available headers also match.
Only the headers that are provided need match, any additional headers will be ignored.
.. code:: python
.. doctest::
:hide:
>>> adapter.register_uri('POST', 'mock://test.com', request_headers={'key', 'val'}, text='resp')
>>> session.post('mock://test.com', headers={'key': 'val', 'another': 'header'}).text
>>> import requests
>>> import requests_mock
>>> adapter = requests_mock.Adapter()
>>> session = requests.Session()
>>> session.mount('mock', adapter)
.. doctest::
>>> adapter.register_uri('POST', 'mock://test.com/headers', request_headers={'key': 'val'}, text='resp')
>>> session.post('mock://test.com/headers', headers={'key': 'val', 'another': 'header'}).text
'resp'
>>> session.post('mock://test.com')
>>> resp = session.post('mock://test.com/headers')
Traceback (most recent call last):
...
requests_mock.exceptions.NoMockAddress: No mock address: POST mock://test.com/
requests_mock.exceptions.NoMockAddress: No mock address: POST mock://test.com/headers

View File

@ -9,7 +9,7 @@ Context Manager
The Mocker object can work as a context manager.
.. code:: python
.. doctest::
>>> import requests
>>> import requests_mock
@ -25,7 +25,7 @@ Decorator
Mocker can also be used as a decorator. The created object will then be passed as the last positional argument.
.. code:: python
.. doctest::
>>> @requests_mock.Mocker()
... def test_function(m):
@ -37,14 +37,14 @@ Mocker can also be used as a decorator. The created object will then be passed a
If the position of the mock is likely to conflict with other arguments you can pass the `kw` argument to the Mocker to have the mocker object passed as that keyword argument instead.
.. code:: python
.. doctest::
>>> @requests_mock.Mocker(kw='mock')
... def test_function(**kwargs):
... kwargs['mock'].register_uri('GET', 'http://test.com', test='resp')
... def test_kw_function(**kwargs):
... kwargs['mock'].register_uri('GET', 'http://test.com', text='resp')
... return requests.get('http://test.com').text
...
>>> test_function()
>>> test_kw_function()
'resp'
Real HTTP Requests
@ -54,12 +54,12 @@ The Mocker object takes the following parameters:
:real_http (bool): If True then any requests that are not handled by the mocking adapter will be forwarded to the real server. Defaults to False.
.. code:: python
.. doctest::
>>> with requests_mock.Mocker(real_http=True) as m:
... m.register_uri('GET', 'http://test.com', text='resp')
... print requests.get('http:/test.com').text
... print requests.get('http://www.google.com').status_code
... print(requests.get('http://test.com').text)
... print(requests.get('http://www.google.com').status_code) # doctest: +SKIP
...
'resp'
200

View File

@ -28,6 +28,12 @@ deps =
# note this only works under python 3 because of unicode literals
commands =
python -m doctest README.rst
[testenv:sphinx-doctest]
# note this only works under python 3 because of unicode literals
commands =
mkdir build/sphinx/doctest
sphinx-build -b doctest docs build/sphinx/doctest
deps =
ipdb
pbr
{[testenv]deps}