Skip to content

Commit

Permalink
First pass at including some deliberate errors for people to find and…
Browse files Browse the repository at this point in the history
… updating instructions and requirements
  • Loading branch information
amaccormack-lumira committed Jun 5, 2020
1 parent 1660892 commit f89354e
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 9 deletions.
65 changes: 62 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,66 @@
rest_api_demo
=============

This repository contains boilerplate code for a RESTful API based on Flask and Flask-RESTPlus.
This is a sample RESTful API technical test.

The code of this demo app is described in an article on my blog:
http://michal.karzynski.pl/blog/2016/06/19/building-beautiful-restful-apis-using-flask-swagger-ui-flask-restplus/
## Software Test Engineer - Tech Test

### Instructions

Your team has been tasked with building a simple back-end for a blog. They have built a RESTful API to implement CRUD operations on this data. The endpoints are:

* GET /blog/categories/ - Returns list of blog categories
* POST /blog/categories/ - Creates a new blog category
* DELETE /blog/categories/{id} - Deletes blog category
* GET /blog/categories/{id} - Returns a category with a list of posts
* PUT /blog/categories/{id} - Updates a blog category
* GET /blog/posts/ - Returns list of blog posts
* POST /blog/posts/ - Creates a new blog post
* GET /blog/posts/archive/{year}/ - Returns list of blog posts from a specified year
* GET /blog/posts/archive/{year}/{month}/ - Returns list of blog posts from a specified month
* GET /blog/posts/archive/{year}/{month}/{day}/ - Returns list of blog posts from a specified day
* DELETE /blog/posts/{id} - Deletes blog post
* GET /blog/posts/{id} - Returns a blog post
* PUT /blog/posts/{id} - Updates a blog post

There is also a Swagger document which describes the API.

The software engineers have now finished their initial development and the application is ready to be tested. Your task is to take the project, run it and test it. Use any testing tools that you think are appropriate for validating this black-box system. You will be evaluated on test coverage, readability and organisation of tests, and suggesting any improvements which could be made to the API.

So that the team can review any bugs found in their application, a simple bug report should be produced as a result of the testing process. This can be in any format you feel is appropriate.

In order to run the application, you need a copy of Python. This can be downloaded from:

https://www.python.org/downloads/

##### It is recommended that you select the "Add python to path" option in the python installer

A download for the project can be found at:

https://onedrive-link?

Once downloaded, extract the zip file, and use a Command Prompt to open the extracted directory. Navigate into the appropriate folder. The API can then be run using the following command:

```
cd path_to_workspace
unzip rest_api_demo.zip
cd rest_api_demo
pip install virtualenv
virtualenv venv
```
* On Windows: `venv\Scripts\activate`
* On Linux/MacOS: `source venv/bin/activate`

```
(venv) pip install -r requirements.txt
(venv) python setup.py develop
(venv) python rest_api_demo/app.py
```

You will then be able to open the swagger endpoints:

* http://localhost:8888/api/
* https://localhost:8889/api/

Bonus points for:
- Automating the running of the tests.
5 changes: 4 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Werkzeug==0.16.1
flask-restplus==0.9.2
Flask-SQLAlchemy==2.1
Flask-SQLAlchemy==2.4.3
pip~=20.1.1
setuptools~=47.1.1
2 changes: 1 addition & 1 deletion rest_api_demo/api/blog/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def delete_post(post_id):


def create_category(data):
name = data.get('name')
name = data.get('name')[1:]
category_id = data.get('id')

category = Category(name)
Expand Down
10 changes: 10 additions & 0 deletions rest_api_demo/api/blog/endpoints/categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ def get(self):
def post(self):
"""
Creates a new blog category.
* Send a JSON object with the new category's name in the request body.
```
{
"name": "New Category Name"
}
```
"""
data = request.json
create_category(data)
Expand Down Expand Up @@ -68,6 +77,7 @@ def put(self, id):
return None, 204

@api.response(204, 'Category successfully deleted.')
@api.response(409, 'Category not deleted, is in use')
def delete(self, id):
"""
Deletes blog category.
Expand Down
3 changes: 2 additions & 1 deletion rest_api_demo/api/blog/endpoints/posts.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get(self):
per_page = args.get('per_page', 10)

posts_query = Post.query
posts_page = posts_query.paginate(page, per_page, error_out=False)
posts_page = posts_query.paginate(1, per_page, error_out=False)

return posts_page

Expand All @@ -49,6 +49,7 @@ def get(self, id):
"""
Returns a blog post.
"""
id+=int(id/5)
return Post.query.filter(Post.id == id).one()

@api.expect(blog_post)
Expand Down
4 changes: 2 additions & 2 deletions rest_api_demo/api/restplus.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

log = logging.getLogger(__name__)

api = Api(version='1.0', title='My Blog API',
description='A simple demonstration of a Flask RestPlus powered API')
api = Api(version='1.0', title='LumiraDX Blog API',
description='Prototype Blog API v0.2\n\n[swagger.json](/api/swagger.json)', )


@api.errorhandler
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@

packages=find_packages(),

install_requires=['flask-restplus==0.9.2', 'Flask-SQLAlchemy==2.1'],
install_requires=['werkzeug==0.16.1', 'flask-restplus==0.9.2', 'Flask-SQLAlchemy==2.1'],
)

0 comments on commit f89354e

Please sign in to comment.