How To Build a Simple API with Flask and Unit Test it

Bob, Fri 03 March 2017, Flask

APIs, curl, Flask, inventory, REST, testing, unittest

REST has gained lot of popularity and is virtually the default architectural style for designing and implementing RESTful web services. Wikipedia states:

Representational state transfer (REST) or RESTful Web services are one way of providing interoperability between computer systems on the Internet. REST-compliant Web services allow requesting systems to access and manipulate textual representations of Web resources using a uniform and predefined set of stateless operations.

Implementing REST APIs in Flask is relatively easy. As this week's challenge is a House Inventory Tracker, lets do CRUD on room items.

Note this post uses the simplest possible example, and focuses on the testing. I use an in-memory list for storage. In real life you probably want a DB, although you could also use a Google Spreadsheet and Python. Security / authentication is critical too, see Miguel Grinberg's excellent Designing a RESTful API with Python and Flask how to implement that.

Get ready

First create a virtualenv and do pip install flask

API code and endpoints

To create a simple API you implement one or more HTTP methods, in this case the following endpoints:

@app.route('/api/v1.0/items', methods=['GET'])
@app.route('/api/v1.0/items/<int:id>', methods=['GET'])
@app.route('/api/v1.0/items', methods=['POST'])
@app.route('/api/v1.0/items/<int:id>', methods=['PUT'])
@app.route('/api/v1.0/items/<int:id>', methods=['DELETE'])

Full code here.

Testing part I) - manually with curl

I first put some curl commands in a test script, isn't it cool you can just use curl to test your new shiny API?

$ python

# get items

curl -i
HTTP/1.0 200 OK

"items": [
    "id": 1,
    "name": "laptop",
    "value": 1000


# add item with proper values

curl -i -H "Content-Type: application/json" -X POST -d  '{"name":"monitor", "value": 200}'

    "item": {
        "id": 4,
        "name": "monitor",
        "value": 200

It surely is! However you have to read the output every time you test. Not cool :(

Testing part II) - automation with unittest

Here the whole exercise became pretty interesting, how to unit test an API?!

Flask facilitates a nice method you can use in your setUp (= repeats for each unit test):

test_client(use_cookies=True, **kwargs)

Creates a test client for this application. For information about unit testing head over to Testing Flask Applications.

You can test response codes and of course see how the data (list of items in this case) changes after each request.

The only challenge was the isolation of each unit test: I had to do copy the app.items to a backup variable in setUp (a deepcopy to not leave references around) and pass it back in tearDown. Similarly for a DB back-end you would probably construct and drop a test table to have a clean slate for every test.

The full unit tests are here, summary:

def test_get_all(self): ...
def test_get_one(self): ...
def test_item_not_exist(self): ...
def test_post(self): ...
def test_update(self): ...
def test_update_error(self): ...
def test_delete(self): ...

This whole exercise took me some time but it was great learning, not something you get from just reading about it! And this can serve as a template when testing other APIs.


Since listening to Soft Skills I want to do some time logging to increase my productivity.

What if I can have a simple API where I can send log entries of 'deep work time x spent on activity y' via a Slack Webhook to a DB or earlier mentioned Google Spreadsheet?

At the time of writing this article I stumbled upon Flask-RESTful which should make this even easier (more elegant). So stay tuned for a part II ...

Keep Calm and Code in Python!

-- Bob

PyBites Python Tips

Do you want to get 250+ concise and applicable Python tips in an ebook that will cost you less than 10 bucks (future updates included), check it out here.

Get our Python Tips Book

"The discussions are succinct yet thorough enough to give you a solid grasp of the particular problem. I just wish I would have had this book when I started learning Python." - Daniel H

"Bob and Julian are the masters at aggregating these small snippets of code that can really make certain aspects of coding easier." - Jesse B

"This is now my favourite first Python go-to reference." - Anthony L

"Do you ever go on one of those cooking websites for a recipe and have to scroll for what feels like an eternity to get to the ingredients and the 4 steps the recipe actually takes? This is the opposite of that." - Sergio S

Get the book