Skip to content

Instantly share code, notes, and snippets.

@nimbus154
Created April 21, 2013 23:54
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nimbus154/5431618 to your computer and use it in GitHub Desktop.
Save nimbus154/5431618 to your computer and use it in GitHub Desktop.
An example of how to write functional tests for a RESTful API using the Bottle microframework.
from bottle import get, run, request, post, Bottle, abort, error, response, debug, redirect
# This is a dictionary endpoint. It retrieves definitions for words.
# You can also add words to the dictionary.
# this allows our bottle application to be accessible outside this file
app = Bottle()
dictionary = {
"lugubrious": "extremely sad",
"kinetic": "relating to motion",
"august": "awesome; also a month"
}
# Retrieve the definition of a word
@app.get('/dictionary/:word')
def define(word=""):
global dictionary # needed to make the dictionary accessible
if word in dictionary:
return {word: dictionary[word]}
else:
abort(404, "Word not in dictionary. Maybe you should add it?")
# Add a word to the dictionary
# If word is in dictionary, redirect
@app.post('/dictionary')
def add():
global dictionary # needed to make the dictionary accessible
word = request.json['word']
if word in dictionary:
# word already exists, redirect
redirect('/dictionary/%s' % word)
else:
dictionary[word] = request.json['definition']
response.status = '201 Created'
return response
debug(True)
if __name__ == '__main__':
run(reloader=True, debug=True)
# import the unit testing module
import unittest
# for HTTP tests
# you must pip install webtest
from webtest import TestApp
# import our bottle app
import dictionary
test_app = TestApp(dictionary.app)
# extend the class unittest.TestCase
class TestGetJSON(unittest.TestCase):
# name any method you want to run as a test "test_"
def test_word_found(self):
# look up a word that should be in the dictionary
response = test_app.get('/dictionary/lugubrious')
# Response status should be HTTP 200 OK
self.assertEqual(response.status_int, 200)
self.assertEqual(response.status, '200 OK')
# Response body should be JSON {"number": 0}
self.assertEqual(response.json['lugubrious'], 'extremely sad')
def test_not_found(self):
# look up a word not in the dictionary
# should return 404
# need to tell WebTest to expect a status of 404
# otherwise it will throw an exception
response = test_app.get('/dictionary/ghostbuster', status=404)
self.assertEqual(response.status_int, 404)
class TestPostJSON(unittest.TestCase):
def test_add(self):
response = test_app.post_json('/dictionary', {
'word': 'hacker',
'definition': 'a computer genius'
})
# Expect a new resource to be created
self.assertEqual(response.status, '201 Created')
# to be really thorough, let's get the resource to ensure it was created
response = test_app.get('/dictionary/hacker')
self.assertEqual(response.status_int, 200)
self.assertEqual(response.json['hacker'], 'a computer genius')
def test_already_in_dictionary(self):
# try to add a word that's already in the dictionary
# server respond with a redirect
response = test_app.post_json('/dictionary', {
'word': 'lugubrious',
'definition': 'extremely sad'
})
# 302 is "Found" redirect, indicating resource was found
self.assertEqual(response.status_int, 302)
# the 'Location' header should end with the path /dictionary/lugubrious
self.assertRegexpMatches(response.location, '/dictionary/lugubrious$')
# If running this file, run the tests
# invoke with `python -m unittest discover`
if __name__ == '__main__':
unittest.main()
@marcoziti
Copy link

nice example to create unit testing with WebTest for Bottle! Well done.

@yegor256
Copy link

yegor256 commented Mar 8, 2014

many thanks!

@varmas
Copy link

varmas commented Oct 31, 2016

nice, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment