Chaker Benhamed
Home | |
Build a REST API in Pyramid with TDD - Part One
over 5 years ago.
I will be going through a series of posts on how to create a REST API with Pyramid. The code source will be available in github.
We are going to create a TODO app. In this post, I will be talking about the application requirement, the project structure and how to setup the development environment.
The application will have 2 endpoints
This resource contain all todo lists. It will support 3 action GET, POST, and DELETE.
GET /todo will return all lists POST /todo will create an empty new todo list GET /todo/:list_id will return the content of the list that have list_id as id. DELETE /todo/:list_id will delete the list.
This resource contain the items of a list. It will support 3 action GET, POST, and DELETE.
GET /todo/:list_id:/items will return the list items POST /todo/:list_id/items will add a new item to the list DELETE /todo/:list_id:/items/:item_id mark the item as completed. GET /todo/:list_id:/items/:item_id return the item's text.
There will be two folders todo and tests. For the todo it will contain three sub folders one for the database models one for views api and the last one will contain script that will seed data into the database.
We will go through every folder in details in the next posts.
For the tests I will be following the conventions of pytest by putting the test directory outside the package.
todo/ ├── __init__.py <- main file that will configure and return WSGI application ├── models <- model definitions aka data sources (often RDBMS or noSQL) │ ├── __init__.py │ ├── meta.py │ ├── list.py │ ├── meta.py │ └── list.py ├── scripts/ <- util Python scripts │ ├── __init__.py │ └── initializedb.py └── api <- views aka business logic ├── __init__.py ├── default.py └── notfound.py tests/ <- seperate folder that contains the tests for the application └── tests.py
Any way to get the dependencies will works. The official documentation suggests to work with virtualenv. I advice you to use that. My setup is different, I am using Nix package manager for downloading packages and setting up a shell session. You can check my previous post on how to package a web app using Nix.
To test the application setup, let's write our first test. It will reside in tests.py file in tests directory.
import unittest from pyramid.paster import get_appsettings settings = get_appsettings('test.ini', name='main') class FunctionalTests(unittest.TestCase): def setUp(self): from todo import main app = main({}, **settings) from webtest import TestApp self.testapp = TestApp(app) def test_root(self): res = self.testapp.get('/') self.assertTrue(b'Hello World' in res.body)
As you can see we are getting the settings from test.ini file were the definition of database uri (see below) and passing them to the main function from todo package, that will return a WSGI which we can use to create a testapp using TestApp class from the webtest package.
In the test_root function we are issuing a GET requests to the home route. and check if 'Hello World' exist in the response.
test.ini
[app:main] use = egg:todo sqlalchemy.url = sqlite://
When you run the tests they must fail. Since we didn't implement the home route yet.
Views in pyramid are callable (function or classes) that take a request object apply the logic and return a response object.
We use the view_config decorator to create our first view. And map it to the '/' route using config.add_route
.
@view_config(route_name='home') def home(request): return Response('Hello World') def includeme(config): config.add_route('home', '/')
After doing this our test will pass.
And that will be all for the first post.