File: introduction.rst

package info (click to toggle)
python-httpretty 1.1.4-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 712 kB
  • sloc: python: 4,233; makefile: 72
file content (182 lines) | stat: -rw-r--r-- 5,402 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
.. _introduction:

`Github <https://github.com/gabrielfalcao/HTTPretty>`_


What is HTTPretty ?
###################

.. highlight:: python

Once upon a time a python developer wanted to use a RESTful api,
everything was fine but until the day he needed to test the code that
hits the RESTful API: what if the API server is down? What if its
content has changed ?

Don't worry, HTTPretty is here for you:

::

  import logging
  import requests
  import httpretty

  from sure import expect

  logging.getLogger('httpretty.core').setLevel(logging.DEBUG)

  @httpretty.activate(allow_net_connect=False)
  def test_yipit_api_returning_deals():
      httpretty.register_uri(httpretty.GET, "http://api.yipit.com/v1/deals/",
                             body='[{"title": "Test Deal"}]',
                             content_type="application/json")

      response = requests.get('http://api.yipit.com/v1/deals/')

      expect(response.json()).to.equal([{"title": "Test Deal"}])


A more technical description
============================

HTTPretty is a python library that swaps the modules :py:mod:`socket`
and :py:mod:`ssl` with fake implementations that intercept HTTP
requests at the level of a TCP connection.

It is inspired on Ruby's `FakeWeb <http://fakeweb.rubyforge.org/>`_.

If you come from the Ruby programming language this would probably sound familiar :smiley:

Installing
==========

Installing httpretty is as easy as:

.. highlight:: bash

::

   pip install httpretty


Demo
####

expecting a simple response body
================================


.. code:: python

   import requests
   import httpretty

   def test_one():
       httpretty.enable(verbose=True, allow_net_connect=False)  # enable HTTPretty so that it will monkey patch the socket module
       httpretty.register_uri(httpretty.GET, "http://yipit.com/",
                              body="Find the best daily deals")

       response = requests.get('http://yipit.com')

       assert response.text == "Find the best daily deals"

       httpretty.disable()  # disable afterwards, so that you will have no problems in code that uses that socket module
       httpretty.reset()    # reset HTTPretty state (clean up registered urls and request history)


making assertions in a callback that generates the response body
================================================================

.. code:: python

   import requests
   import json
   import httpretty

   @httpretty.activate
   def test_with_callback_response():
     def request_callback(request, uri, response_headers):
         content_type = request.headers.get('Content-Type')
         assert request.body == '{"nothing": "here"}', 'unexpected body: {}'.format(request.body)
         assert content_type == 'application/json', 'expected application/json but received Content-Type: {}'.format(content_type)
         return [200, response_headers, json.dumps({"hello": "world"})]

     httpretty.register_uri(
         httpretty.POST, "https://httpretty.example.com/api",
         body=request_callback)

     response = requests.post('https://httpretty.example.com/api', headers={'Content-Type': 'application/json'}, data='{"nothing": "here"}')

     expect(response.json()).to.equal({"hello": "world"})


Link headers
============


 Tests link headers by using the `adding_headers` parameter.


 .. code:: python

    import requests
    from sure import expect
    import httpretty


    @httpretty.activate
    def test_link_response():
        first_url = "http://foo-api.com/data"
        second_url = "http://foo-api.com/data?page=2"
        link_str = "<%s>; rel='next'" % second_url

        httpretty.register_uri(
            httpretty.GET,
            first_url,
            body='{"success": true}',
            status=200,
            content_type="text/json",
            adding_headers={"Link": link_str},
        )
        httpretty.register_uri(
            httpretty.GET,
            second_url,
            body='{"success": false}',
            status=500,
            content_type="text/json",
        )
        # Performs a request to `first_url` followed by some testing
        response = requests.get(first_url)
        expect(response.json()).to.equal({"success": True})
        expect(response.status_code).to.equal(200)
        next_url = response.links["next"]["url"]
        expect(next_url).to.equal(second_url)

        # Follow the next URL and perform some testing.
        response2 = requests.get(next_url)
        expect(response2.json()).to.equal({"success": False})
        expect(response2.status_code).to.equal(500)


Motivation
##########

When building systems that access external resources such as RESTful
webservices, XMLRPC or even simple HTTP requests, we stumble in the
problem:

    *"I'm gonna need to mock all those requests"*

It can be a bit of a hassle to use something like
:py:class:`mock.Mock` to stub the requests, this can work well for
low-level unit tests but when writing functional or integration tests
we should be able to allow the http calls to go through the TCP socket
module.

HTTPretty `monkey patches
<http://en.wikipedia.org/wiki/Monkey_patch>`_ Python's
:py:mod:`socket` core module with a fake version of the module.

Because HTTPretty implements a fake the modules :py:mod:`socket` and
:py:mod:`ssl` you can use write tests to code against any HTTP library
that use those modules.