Github

What is HTTPretty ?

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 socket and ssl with fake implementations that intercept HTTP requests at the level of a TCP connection.

It is inspired on Ruby’s FakeWeb.

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

Installing

Installing httpretty is as easy as:

pip install httpretty

Demo

expecting a simple response body

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

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"})

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 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 Python’s socket core module with a fake version of the module.

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