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