1Testing Helpers 2=============== 3 4The :mod:`treq.testing` module provides some tools for testing both HTTP clients which use the treq API and implementations of the `Twisted Web resource model <https://twistedmatrix.com/documents/current/api/twisted.web.resource.IResource.html>`_. 5 6Writing tests for HTTP clients 7------------------------------ 8 9The :class:`~treq.testing.StubTreq` class implements the :mod:`treq` module interface (:func:`treq.get()`, :func:`treq.post()`, etc.) but runs all I/O via a :class:`~twisted.internet.testing.MemoryReactor`. 10It wraps a :class:`twisted.web.resource.IResource` provider which handles each request. 11 12You can wrap a pre-existing `IResource` provider, or write your own. 13For example, the :class:`twisted.web.resource.ErrorPage` resource can produce an arbitrary HTTP status code. 14:class:`twisted.web.static.File` can serve files or directories. 15And you can easily achieve custom responses by writing trivial resources yourself: 16 17.. literalinclude:: examples/iresource.py 18 :linenos: 19 :pyobject: JsonResource 20 21However, those resources don't assert anything about the request. 22The :class:`~treq.testing.RequestSequence` and :class:`~treq.testing.StringStubbingResource` classes make it easy to construct a resource which encodes the expected request and response pairs. 23Do note that most parameters to these functions must be bytes—it's safest to use the ``b''`` string syntax, which works on both Python 2 and 3. 24 25For example: 26 27.. literalinclude:: examples/testing_seq.py 28 :linenos: 29 30This may be run with ``trial testing_seq.py``. 31Download: :download:`testing_seq.py <examples/testing_seq.py>`. 32 33Loosely matching the request 34~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 36If you don't care about certain parts of the request, you can pass :data:`mock.ANY`, which compares equal to anything. 37This sequence matches a single GET request with any parameters or headers: 38 39.. code-block:: python 40 41 RequestSequence([ 42 ((b'get', mock.ANY, mock.ANY, b''), (200, {}, b'ok')) 43 ]) 44 45 46If you care about headers, use :class:`~treq.testing.HasHeaders` to make assertions about the headers present in the request. 47It compares equal to a superset of the headers specified, which helps make your test robust to changes in treq or Agent. 48Right now treq adds the ``Accept-Encoding: gzip`` header, but as support for additional compression methods is added, this may change. 49 50Writing tests for Twisted Web resources 51--------------------------------------- 52 53Since :class:`~treq.testing.StubTreq` wraps any resource, you can use it to test your server-side code as well. 54This is superior to calling your resource's methods directly or passing mock objects, since it uses a real :class:`~twisted.web.client.Agent` to generate the request and a real :class:`~twisted.web.server.Site` to process the response. 55Thus, the ``request`` object your code interacts with is a *real* :class:`twisted.web.server.Request` and behaves the same as it would in production. 56 57Note that if your resource returns :data:`~twisted.web.server.NOT_DONE_YET` you must keep a reference to the :class:`~treq.testing.RequestTraversalAgent` and call its :meth:`~treq.testing.RequestTraversalAgent.flush()` method to spin the memory reactor once the server writes additional data before the client will receive it. 58