Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a python app that uses the requests library

I am writing an application that performs REST operations using Kenneth Reitz's requests library and I'm struggling to find a nice way to unit test these applications, because requests provides its methods via module-level methods.

What I want is the ability to synthesize the conversation between the two sides; provide a series of request assertions and responses.

like image 272
Chris R Avatar asked Mar 04 '12 23:03

Chris R


People also ask

What is the use of request library in Python?

The requests module allows you to send HTTP requests using Python. The HTTP request returns a Response Object with all the response data (content, encoding, status, etc).


2 Answers

It is in fact a little strange that the library has a blank page about end-user unit testing, while targeting user-friendliness and ease of use. There's however an easy-to-use library by Dropbox, unsurprisingly called responses. Here is its intro post. It says they've failed to employ httpretty, while stating no reason of the fail, and written a library with similar API.

import unittest  import requests import responses   class TestCase(unittest.TestCase):    @responses.activate     def testExample(self):     responses.add(**{       'method'         : responses.GET,       'url'            : 'http://example.com/api/123',       'body'           : '{"error": "reason"}',       'status'         : 404,       'content_type'   : 'application/json',       'adding_headers' : {'X-Foo': 'Bar'}     })      response = requests.get('http://example.com/api/123')      self.assertEqual({'error': 'reason'}, response.json())     self.assertEqual(404, response.status_code) 
like image 98
saaj Avatar answered Oct 05 '22 13:10

saaj


If you use specifically requests try httmock. It's wonderfully simple and elegant:

from httmock import urlmatch, HTTMock import requests  # define matcher: @urlmatch(netloc=r'(.*\.)?google\.com$') def google_mock(url, request):     return 'Feeling lucky, punk?'  # open context to patch with HTTMock(google_mock):     # call requests     r = requests.get('http://google.com/') print r.content  # 'Feeling lucky, punk?' 

If you want something more generic (e.g. to mock any library making http calls) go for httpretty.

Almost as elegant:

import requests import httpretty  @httpretty.activate def test_one():     # define your patch:     httpretty.register_uri(httpretty.GET, "http://yipit.com/",                         body="Find the best daily deals")     # use!     response = requests.get('http://yipit.com')     assert response.text == "Find the best daily deals" 

HTTPretty is far more feature-rich - it offers also mocking status code, streaming responses, rotating responses, dynamic responses (with a callback).

like image 20
Marek Brzóska Avatar answered Oct 05 '22 14:10

Marek Brzóska