HTTPretty’s - HTTP Client Mocking for Python

HTTP Client mocking tool for Python. Provides a full fake TCP socket module. Inspired by FakeWeb

Looking for the Github Repository ?

Python Support:

  • 2.7.13
  • 3.6.5
  • 3.7.0
https://github.com/gabrielfalcao/HTTPretty/raw/master/docs/source/_static/logo.svg?sanitize=true Documentation Status https://travis-ci.org/gabrielfalcao/HTTPretty.svg?branch=master

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 requests
from sure import expect
import httpretty


@httpretty.activate
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 HTTP client mock library for Python 100% inspired on ruby’s [FakeWeb](http://fakeweb.rubyforge.org/). If you come from ruby 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()  # 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 brings a lot of hassle, you will need to use a generic mocking tool, mess with scope and so on.

The idea behind HTTPretty (how it works)

HTTPretty monkey patches Python’s socket core module, reimplementing the HTTP protocol, by mocking requests and responses.

As for how it works this way, you don’t need to worry what http library you’re gonna use.

HTTPretty will mock the response for you :) (and also give you the latest requests so that you can check them)

Acknowledgements

caveats

forcing_headers + Content-Length

When using the forcing_headers option make sure to add the header Content-Length otherwise calls using requests will try to load the response endlessly.

supported libraries

Because HTTPretty works in the socket level it should work with any HTTP client libraries, although it is battle tested against:

API Reference

register_uri

classmethod httpretty.register_uri(method, uri, body='{"message": "HTTPretty :)"}', adding_headers=None, forcing_headers=None, status=200, responses=None, match_querystring=False, priority=0, **headers)[source]
import httpretty


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)


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

assert httpretty.latest_requests[-1].url == 'https://httpbin.org/ip'
Parameters:
  • method – one of httpretty.GET, httpretty.PUT, httpretty.POST, httpretty.DELETE, httpretty.HEAD, httpretty.PATCH, httpretty.OPTIONS, httpretty.CONNECT
  • uri – a string (e.g.: “https://httpbin.org/ip”)
  • body – a string, defaults to {"message": "HTTPretty :)"}
  • adding_headers – dict - headers to be added to the response
  • forcing_headers – dict - headers to be forcefully set in the response
  • status – an integer, defaults to 200
  • responses – a list of entries, ideally each created with Response()
  • priority – an integer, useful for setting higher priority over previously registered urls. defaults to zero
  • match_querystring – bool - whether to take the querystring into account when matching an URL
  • headers – headers to be added to the response

enable

classmethod httpretty.enable(allow_net_connect=True)[source]

Enables HTTPretty. When allow_net_connect is False any connection to an unregistered uri will throw httpretty.errors.UnmockedError.

import re, json
import httpretty

httpretty.enable()

httpretty.register_uri(
    httpretty.GET,
    re.compile(r'http://.*'),
    body=json.dumps({'man': 'in', 'the': 'middle'})
)

response = requests.get('https://foo.bar/foo/bar')

response.json().should.equal({
    "man": "in",
    "the": "middle",
})

Warning

after calling this method the original socket is replaced with httpretty.core.fakesock. Make sure to call disable() after done with your tests or use the httpretty.enabled as decorator or context-manager

disable

classmethod httpretty.disable()[source]

Disables HTTPretty entirely, putting the original socket module back in its place.

import re, json
import httpretty

httpretty.enable()
# request passes through fake socket
response = requests.get('https://httpbin.org')

httpretty.disable()
# request uses real python socket module
response = requests.get('https://httpbin.org')

Note

This method does not call httpretty.core.reset() automatically.

is_enabled

classmethod httpretty.is_enabled()[source]

Check if HTTPretty is enabled

Returns:bool
import httpretty

httpretty.enable()
assert httpretty.is_enabled() == True

httpretty.disable()
assert httpretty.is_enabled() == False

last_request

httpretty.last_request()[source]
Returns:the last HTTPrettyRequest

latest_requests

httpretty.latest_requests()[source]

returns the history of made requests

activate

httpretty.activate

alias of httpretty.core.httprettified

httprettified

class httpretty.core.httprettified[source]

decorator for test functions

Tip

Also available under the alias httpretty.activate()

Parameters:test – a callable

example usage with nosetests

import sure
from httpretty import httprettified

@httprettified
def test_using_nosetests():
    httpretty.register_uri(
        httpretty.GET,
        'https://httpbin.org/ip'
    )

    response = requests.get('https://httpbin.org/ip')

    response.json().should.equal({
        "message": "HTTPretty :)"
    })

example usage with unittest module

import unittest
from sure import expect
from httpretty import httprettified

@httprettified
class TestWithPyUnit(unittest.TestCase):
    def test_httpbin(self):
        httpretty.register_uri(httpretty.GET, 'https://httpbin.org/ip')
        response = requests.get('https://httpbin.org/ip')
        expect(response.json()).to.equal({
            "message": "HTTPretty :)"
        })

httprettized

class httpretty.core.httprettized(allow_net_connect=True)[source]

context-manager for enabling HTTPretty.

import json
import httpretty

httpretty.register_uri(httpretty.GET, 'https://httpbin.org/ip', body=json.dumps({'origin': '42.42.42.42'}))
with httpretty.enabled():
    response = requests.get('https://httpbin.org/ip')

assert httpretty.latest_requests[-1].url == 'https://httpbin.org/ip'
assert response.json() == {'origin': '42.42.42.42'}

HTTPrettyRequest

class httpretty.core.HTTPrettyRequest(headers, body='')[source]

Represents a HTTP request. It takes a valid multi-line, \r\n separated string with HTTP headers and parse them out using the internal parse_request method.

It also replaces the rfile and wfile attributes with StringIO instances so that we guarantee that it won’t make any I/O, neighter for writing nor reading.

It has some convenience attributes:

headers -> a mimetype object that can be cast into a dictionary, contains all the request headers

method -> the HTTP method used in this request

querystring -> a dictionary containing lists with the attributes. Please notice that if you need a single value from a query string you will need to get it manually like:

body -> the request body as a string

parsed_body -> the request body parsed by parse_request_body

>>> request.querystring
{'name': ['Gabriel Falcao']}
>>> print request.querystring['name'][0]
parse_querystring(qs)[source]

parses an UTF-8 encoded query string into a dict of string lists

Parameters:qs – a querystring
Returns:a dict of lists
parse_request_body(body)[source]

Attempt to parse the post based on the content-type passed. Return the regular body if not

Parameters:body – string
Returns:a python object such as dict or list in case the deserialization suceeded. Else returns the given param body
querystring = None

a dictionary containing parsed request body or None if HTTPrettyRequest doesn’t know how to parse it. It currently supports parsing body data that was sent under the content`-type` headers values: ``application/json or application/x-www-form-urlencoded

HTTPrettyRequestEmpty

class httpretty.core.HTTPrettyRequestEmpty[source]

Represents an empty HTTPrettyRequest where all its properties are somehow empty or None

FakeSockFile

class httpretty.core.FakeSockFile[source]

Fake socket file descriptor. Under the hood all data is written in a temporary file, giving it a real file descriptor number.

FakeSSLSocket

class httpretty.core.FakeSSLSocket(sock, *args, **kw)[source]

Shorthand for fakesock

URIInfo

class httpretty.URIInfo(username='', password='', hostname='', port=80, path='/', query='', fragment='', scheme='', last_request=None)[source]

Internal representation of URIs

Tip

all arguments are optional

Parameters:
  • username
  • password
  • hostname
  • port
  • path
  • query
  • fragment
  • scheme
  • last_request
classmethod from_uri(uri, entry)[source]
Parameters:
  • uri – string
  • entry – an instance of Entry
full_url(use_querystring=True)[source]
Parameters:use_querystring – bool
Returns:a string with the full url with the format {scheme}://{credentials}{domain}{path}{query}
get_full_domain()[source]
Returns:a string in the form {domain}:{port} or just the domain if the port is 80 or 443

URIMatcher

class httpretty.URIMatcher(uri, entries, match_querystring=False, priority=0)[source]
get_next_entry(method, info, request)[source]

Cycle through available responses, but only once. Any subsequent requests will receive the last response

Entry

class httpretty.Entry(method, uri, body, adding_headers=None, forcing_headers=None, status=200, streaming=False, **headers)[source]

Created by register_uri() and stored in memory as internal representation of a HTTP request/response definition.

Parameters:
  • method – string
  • uri – string
  • body – string
  • adding_headers – dict - headers to be added to the response
  • forcing_headers – dict - headers to be forcefully set in the response
  • status – an integer (e.g.: status=200)
  • streaming – bool - whether to stream the response
  • headers – keyword-args with headers to be added to the response

Warning

When using the forcing_headers option make sure to add the header Content-Length otherwise calls using requests will try to load the response endlessly.

fill_filekind(fk)[source]

writes HTTP Response data to a file descriptor

Parm fk:a file-like object

Warning

side-effect: this method moves the cursor of the given file object to zero

normalize_headers(headers)[source]

Normalize keys in header names so that COntent-tyPe becomes content-type

Parameters:headers – dict
Returns:dict
validate()[source]

validates the body size with the value of the Content-Length header

Modules

Core

class httpretty.core.EmptyRequestHeaders[source]

A dict subclass used as internal representation of empty request headers

class httpretty.core.Entry(method, uri, body, adding_headers=None, forcing_headers=None, status=200, streaming=False, **headers)[source]

Created by register_uri() and stored in memory as internal representation of a HTTP request/response definition.

Parameters:
  • method – string
  • uri – string
  • body – string
  • adding_headers – dict - headers to be added to the response
  • forcing_headers – dict - headers to be forcefully set in the response
  • status – an integer (e.g.: status=200)
  • streaming – bool - whether to stream the response
  • headers – keyword-args with headers to be added to the response

Warning

When using the forcing_headers option make sure to add the header Content-Length otherwise calls using requests will try to load the response endlessly.

fill_filekind(fk)[source]

writes HTTP Response data to a file descriptor

Parm fk:a file-like object

Warning

side-effect: this method moves the cursor of the given file object to zero

normalize_headers(headers)[source]

Normalize keys in header names so that COntent-tyPe becomes content-type

Parameters:headers – dict
Returns:dict
validate()[source]

validates the body size with the value of the Content-Length header

class httpretty.core.FakeSSLSocket(sock, *args, **kw)[source]

Shorthand for fakesock

class httpretty.core.FakeSockFile[source]

Fake socket file descriptor. Under the hood all data is written in a temporary file, giving it a real file descriptor number.

class httpretty.core.HTTPrettyRequest(headers, body='')[source]

Represents a HTTP request. It takes a valid multi-line, \r\n separated string with HTTP headers and parse them out using the internal parse_request method.

It also replaces the rfile and wfile attributes with StringIO instances so that we guarantee that it won’t make any I/O, neighter for writing nor reading.

It has some convenience attributes:

headers -> a mimetype object that can be cast into a dictionary, contains all the request headers

method -> the HTTP method used in this request

querystring -> a dictionary containing lists with the attributes. Please notice that if you need a single value from a query string you will need to get it manually like:

body -> the request body as a string

parsed_body -> the request body parsed by parse_request_body

>>> request.querystring
{'name': ['Gabriel Falcao']}
>>> print request.querystring['name'][0]
parse_querystring(qs)[source]

parses an UTF-8 encoded query string into a dict of string lists

Parameters:qs – a querystring
Returns:a dict of lists
parse_request_body(body)[source]

Attempt to parse the post based on the content-type passed. Return the regular body if not

Parameters:body – string
Returns:a python object such as dict or list in case the deserialization suceeded. Else returns the given param body
querystring = None

a dictionary containing parsed request body or None if HTTPrettyRequest doesn’t know how to parse it. It currently supports parsing body data that was sent under the content`-type` headers values: ``application/json or application/x-www-form-urlencoded

class httpretty.core.HTTPrettyRequestEmpty[source]

Represents an empty HTTPrettyRequest where all its properties are somehow empty or None

class httpretty.core.URIInfo(username='', password='', hostname='', port=80, path='/', query='', fragment='', scheme='', last_request=None)[source]

Internal representation of URIs

Tip

all arguments are optional

Parameters:
  • username
  • password
  • hostname
  • port
  • path
  • query
  • fragment
  • scheme
  • last_request
classmethod from_uri(uri, entry)[source]
Parameters:
  • uri – string
  • entry – an instance of Entry
full_url(use_querystring=True)[source]
Parameters:use_querystring – bool
Returns:a string with the full url with the format {scheme}://{credentials}{domain}{path}{query}
get_full_domain()[source]
Returns:a string in the form {domain}:{port} or just the domain if the port is 80 or 443
httpretty.core.create_fake_connection(address, timeout=<object object>, source_address=None)[source]

drop-in replacement for socket.create_connection()

httpretty.core.fake_getaddrinfo(host, port, family=None, socktype=None, proto=None, flags=None)[source]

drop-in replacement for socket.getaddrinfo()

httpretty.core.fake_gethostbyname(host)[source]

drop-in replacement for socket.gethostbyname()

httpretty.core.fake_gethostname()[source]

drop-in replacement for socket.gethostname()

httpretty.core.fake_wrap_socket(orig_wrap_socket_fn, *args, **kw)[source]

drop-in replacement for py:func:ssl.wrap_socket

class httpretty.core.fakesock[source]

fake socket

class socket(family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, protocol=0, _sock=None)[source]

drop-in replacement for socket.socket

makefile(mode='r', bufsize=-1)[source]

Returns this fake socket’s own tempfile buffer.

If there is an entry associated with the socket, the file descriptor gets filled in with the entry data before being returned.

real_sendall(data, *args, **kw)[source]

Sends data to the remote server. This method is called when HTTPretty identifies that someone is trying to send non-http data.

The received bytes are written in this socket’s tempfile buffer so that HTTPretty can return it accordingly when necessary.

httpretty.core.httprettified(test=None, allow_net_connect=True)[source]

decorator for test functions

Tip

Also available under the alias httpretty.activate()

Parameters:test – a callable

example usage with nosetests

import sure
from httpretty import httprettified

@httprettified
def test_using_nosetests():
    httpretty.register_uri(
        httpretty.GET,
        'https://httpbin.org/ip'
    )

    response = requests.get('https://httpbin.org/ip')

    response.json().should.equal({
        "message": "HTTPretty :)"
    })

example usage with unittest module

import unittest
from sure import expect
from httpretty import httprettified

@httprettified
class TestWithPyUnit(unittest.TestCase):
    def test_httpbin(self):
        httpretty.register_uri(httpretty.GET, 'https://httpbin.org/ip')
        response = requests.get('https://httpbin.org/ip')
        expect(response.json()).to.equal({
            "message": "HTTPretty :)"
        })
class httpretty.core.httprettized(allow_net_connect=True)[source]

context-manager for enabling HTTPretty.

import json
import httpretty

httpretty.register_uri(httpretty.GET, 'https://httpbin.org/ip', body=json.dumps({'origin': '42.42.42.42'}))
with httpretty.enabled():
    response = requests.get('https://httpbin.org/ip')

assert httpretty.latest_requests[-1].url == 'https://httpbin.org/ip'
assert response.json() == {'origin': '42.42.42.42'}
class httpretty.core.httpretty[source]

manages HTTPretty’s internal request/response registry and request matching.

classmethod Response(body, method=None, uri=None, adding_headers=None, forcing_headers=None, status=200, streaming=False, **kw)[source]

shortcut to create an Entry that takes the body as first positional argument

See also

the parameters of this function match those of the Entry constructor

Parameters:
  • body
  • method – one of httpretty.GET, httpretty.PUT, httpretty.POST, httpretty.DELETE, httpretty.HEAD, httpretty.PATCH, httpretty.OPTIONS, httpretty.CONNECT
  • uri
  • adding_headers
  • forcing_headers
  • status – defaults to 200
  • streaming – defaults to False
  • kw – keyword-arguments passed onto the Entry
Returns:

an Entry

classmethod disable()[source]

Disables HTTPretty entirely, putting the original socket module back in its place.

import re, json
import httpretty

httpretty.enable()
# request passes through fake socket
response = requests.get('https://httpbin.org')

httpretty.disable()
# request uses real python socket module
response = requests.get('https://httpbin.org')

Note

This method does not call httpretty.core.reset() automatically.

classmethod enable(allow_net_connect=True)[source]

Enables HTTPretty. When allow_net_connect is False any connection to an unregistered uri will throw httpretty.errors.UnmockedError.

import re, json
import httpretty

httpretty.enable()

httpretty.register_uri(
    httpretty.GET,
    re.compile(r'http://.*'),
    body=json.dumps({'man': 'in', 'the': 'middle'})
)

response = requests.get('https://foo.bar/foo/bar')

response.json().should.equal({
    "man": "in",
    "the": "middle",
})

Warning

after calling this method the original socket is replaced with httpretty.core.fakesock. Make sure to call disable() after done with your tests or use the httpretty.enabled as decorator or context-manager

classmethod historify_request(headers, body='', append=True)[source]

appends request to a list for later retrieval

import httpretty

httpretty.register_uri(httpretty.GET, 'https://httpbin.org/ip', body='')
with httpretty.enabled():
    requests.get('https://httpbin.org/ip')

assert httpretty.latest_requests[-1].url == 'https://httpbin.org/ip'
classmethod is_enabled()[source]

Check if HTTPretty is enabled

Returns:bool
import httpretty

httpretty.enable()
assert httpretty.is_enabled() == True

httpretty.disable()
assert httpretty.is_enabled() == False
classmethod match_http_address(hostname, port)[source]
Parameters:
  • hostname – a string
  • port – an integer
Returns:

an URLMatcher or None

classmethod match_https_hostname(hostname)[source]
Parameters:hostname – a string
Returns:an URLMatcher or None
classmethod match_uriinfo(info)[source]
Parameters:info – an URIInfo
Returns:a 2-item tuple: (URLMatcher, URIInfo) or (None, [])
classmethod playback(filename)[source]
import io
import json
import requests
import httpretty

with httpretty.record('/tmp/ip.json'):
    data = requests.get('https://httpbin.org/ip').json()

with io.open('/tmp/ip.json') as fd:
    assert data == json.load(fd)
Parameters:filename – a string
Returns:a context-manager
classmethod record(filename, indentation=4, encoding='utf-8')[source]
import io
import json
import requests
import httpretty

with httpretty.record('/tmp/ip.json'):
    data = requests.get('https://httpbin.org/ip').json()

with io.open('/tmp/ip.json') as fd:
    assert data == json.load(fd)
Parameters:
  • filename – a string
  • indentation – an integer, defaults to 4
  • encoding – a string, defaults to “utf-8”
Returns:

a context-manager

classmethod register_uri(method, uri, body='{"message": "HTTPretty :)"}', adding_headers=None, forcing_headers=None, status=200, responses=None, match_querystring=False, priority=0, **headers)[source]
import httpretty


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)


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

assert httpretty.latest_requests[-1].url == 'https://httpbin.org/ip'
Parameters:
  • method – one of httpretty.GET, httpretty.PUT, httpretty.POST, httpretty.DELETE, httpretty.HEAD, httpretty.PATCH, httpretty.OPTIONS, httpretty.CONNECT
  • uri – a string (e.g.: “https://httpbin.org/ip”)
  • body – a string, defaults to {"message": "HTTPretty :)"}
  • adding_headers – dict - headers to be added to the response
  • forcing_headers – dict - headers to be forcefully set in the response
  • status – an integer, defaults to 200
  • responses – a list of entries, ideally each created with Response()
  • priority – an integer, useful for setting higher priority over previously registered urls. defaults to zero
  • match_querystring – bool - whether to take the querystring into account when matching an URL
  • headers – headers to be added to the response
classmethod reset()[source]

resets the internal state of HTTPretty, unregistering all URLs

httpretty.core.url_fix(s, charset=None)[source]

escapes special characters

Http

httpretty.http.last_requestline(sent_data)[source]

Find the last line in sent_data that can be parsed with parse_requestline

httpretty.http.parse_requestline(s)[source]

http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5

>>> parse_requestline('GET / HTTP/1.0')
('GET', '/', '1.0')
>>> parse_requestline('post /testurl htTP/1.1')
('POST', '/testurl', '1.1')
>>> parse_requestline('Im not a RequestLine')
Traceback (most recent call last):
    ...
ValueError: Not a Request-Line

Utils

Exceptions

exception httpretty.errors.HTTPrettyError[source]
exception httpretty.errors.UnmockedError[source]

Hacking on HTTPretty

install development dependencies

Tip

Make sure to have pipenv installed before working on HTTPretty. This works with Python 2.7.13 and 3.6.5.

pipenv install --dev

next steps

  1. run the tests with make:
make lint unit functional
  1. hack at will
  2. commit, push etc
  3. send a pull request

License

<HTTPretty - HTTP client mock for Python>
Copyright (C) <2011-2018>  Gabriel Falcão <gabriel@nacaolivre.org>

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Main contributors

HTTPretty has received many contributions but some folks made remarkable contributions and deserve extra credit:

Release Notes

0.9.4

Improvements:

  • Official Python 3.6 support
  • Normalized coding style to comform with PEP8 (partially)
  • Add more API reference coverage in docstrings of members such as httpretty.core.Entry
  • Continuous Integration building python 2.7 and 3.6
  • Migrate from pip to pipenv

0.8.4

Improvements:

  • Refactored core.py and increased its unit test coverage to 80%. HTTPretty is slightly more robust now.

Bug fixes:

  • POST requests being called twice #100

0.6.5

Applied pull requests:

  • continue on EAGAIN socket errors: #102 by kouk.
  • Fix fake_gethostbyname for requests 2.0: #101 by mgood
  • Add a way to match the querystrings: #98 by ametaireau
  • Use common string case for URIInfo hostname comparison: #95 by mikewaters
  • Expose httpretty.reset() to public API: #91 by imankulov
  • Don’t duplicate http ports number: #89 by mardiros
  • Adding parsed_body parameter to simplify checks: #88 by toumorokoshi
  • Use the real socket if it’s not HTTP: #87 by mardiros

0.6.2

  • Fixing bug of lack of trailing slashes #73
  • Applied pull requests #71 and #72 by @andresriancho
  • Keyword arg coercion fix by @dupuy
  • @papaeye fixed content-length calculation.

0.6.1

  • New API, no more camel case and everything is available through a simple import:
import httpretty

@httpretty.activate
def test_function():
    # httpretty.register_uri(...)
    # make request...
    pass
  • Re-organized module into submodules

0.5.14

0.5.12

  • HTTPretty doesn’t hang when using other application protocols under a @httprettified decorated test.

0.5.11

  • Ability to know whether HTTPretty is or not enabled through httpretty.is_enabled()

0.5.10

  • Support to multiple methods per registered URL. Thanks @hughsaunders

0.5.9

  • Fixed python 3 support. Thanks @spulec

0.5.8

Indices and tables