Skip to content

Commit

Permalink
Add Flask example and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
greyli committed Jun 27, 2021
1 parent c2a1335 commit e270458
Show file tree
Hide file tree
Showing 2 changed files with 241 additions and 0 deletions.
119 changes: 119 additions & 0 deletions examples/flask/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from flask import Flask, request
from werkzeug.exceptions import HTTPException
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

pets = [
{
'name': 'Kitty',
'category': 'cat'
},
{
'name': 'Coco',
'category': 'dog'
},
{
'name': 'Flash',
'category': 'cat'
}
]


class PetModel(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(10))
category = db.Column(db.String(10))


@app.before_first_request
def init_database():
"""Create the table and add some fake data."""
db.create_all()
for pet_data in pets:
pet = PetModel(**pet_data)
db.session.add(pet)
db.session.commit()


@app.errorhandler(HTTPException)
def handle_http_errors(error):
return {'message': error.name}, error.code


def pet_schema(pet):
return {
'id': pet.id,
'name': pet.name,
'category': pet.category
}


@app.get('/')
def say_hello():
return {'message': 'Hello!'}


@app.get('/pets/<int:pet_id>')
def get_pet(pet_id):
pet = PetModel.query.get(pet_id)
if pet is None:
return {'message': 'Pet not found.'}, 404
return pet_schema(pet)


@app.get('/pets')
def get_pets():
pets = PetModel.query.all()
return {'pets': [pet_schema(pet) for pet in pets]}


@app.post('/pets')
def create_pet():
data = request.json
if 'name' not in data or 'category' not in data:
return {'message': 'The name and category field is required.'}, 400
if len(data['name']) > 10:
return {'message': 'The length of the name must be between 0 and 10.'}, 400
if data['category'] not in ['cat', 'dog']:
return {'message': 'The category must be one of: dog, cat.'}, 400

pet = PetModel(name=data['name'], category=data['category'])
db.session.add(pet)
db.session.commit()
return pet_schema(pet), 201


@app.patch('/pets/<int:pet_id>')
def update_pet(pet_id):
pet = PetModel.query.get(pet_id)
if pet is None:
return {'message': 'Pet not found.'}, 404

data = request.json
if 'name' in data:
if len(data['name']) > 10:
return {'message': 'The length of the name must be between 0 and 10.'}, 400
else:
pet.name = data['name']
if 'category' in data:
if data['category'] not in ['cat', 'dog']:
return {'message': 'The category must be one of: dog, cat.'}, 400
else:
pet.category = data['category']
db.session.commit()
return pet_schema(pet)


@app.delete('/pets/<int:pet_id>')
def delete_pet(pet_id):
pet = PetModel.query.get(pet_id)
if pet is None:
return {'message': 'Pet not found.'}, 404
db.session.delete(pet)
db.session.commit()
return '', 204
122 changes: 122 additions & 0 deletions test_examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
from importlib import reload
import sys

import pytest

examples = [
'flask',
]


@pytest.fixture
def client(request):
app_path = f'examples/{request.param}'
sys.path.insert(0, app_path)
import app
app = reload(app)
_app = app.app
_app.testing = True
sys.path.remove(app_path)
return _app.test_client()


@pytest.mark.parametrize('client', examples, indirect=True)
def test_say_hello(client):
rv = client.get('/')
assert rv.status_code == 200
assert rv.json
assert rv.json['message'] == 'Hello!'


@pytest.mark.parametrize('client', examples, indirect=True)
def test_get_pet(client):
rv = client.get('/pets/1')
assert rv.status_code == 200
assert rv.json
assert rv.json['name'] == 'Kitty'
assert rv.json['category'] == 'cat'

rv = client.get('/pets/13')
assert rv.status_code == 404
assert rv.json


@pytest.mark.parametrize('client', examples, indirect=True)
def test_get_pets(client):
rv = client.get('/pets')
assert rv.status_code == 200
assert rv.json
assert len(rv.json['pets']) == 3
assert rv.json['pets'][0]['name'] == 'Kitty'
assert rv.json['pets'][0]['category'] == 'cat'


@pytest.mark.parametrize('client', examples, indirect=True)
def test_create_pet(client):
rv = client.post('/pets', json={
'name': 'Grey',
'category': 'cat'
})
assert rv.status_code == 201
assert rv.json
assert rv.json['name'] == 'Grey'
assert rv.json['category'] == 'cat'


@pytest.mark.parametrize('client', examples, indirect=True)
@pytest.mark.parametrize('data', [
{'name': 'Grey', 'category': 'human'},
{'name': 'Fyodor Mikhailovich Dostoevsky', 'category': 'cat'},
{'category': 'cat'},
{'name': 'Grey'}
])
def test_create_pet_with_bad_data(client, data):
rv = client.post('/pets', json=data)
assert rv.status_code == 400
assert rv.json


@pytest.mark.parametrize('client', examples, indirect=True)
def test_update_pet(client):
new_data = {
'name': 'Ghost',
'category': 'dog'
}

rv = client.patch('/pets/1', json=new_data)
assert rv.status_code == 200
assert rv.json

rv = client.get('/pets/1')
assert rv.status_code == 200
assert rv.json['name'] == new_data['name']
assert rv.json['category'] == new_data['category']

rv = client.patch('/pets/13', json=new_data)
assert rv.status_code == 404
assert rv.json


@pytest.mark.parametrize('client', examples, indirect=True)
@pytest.mark.parametrize('data', [
{'name': 'Fyodor Mikhailovich Dostoevsky'},
{'category': 'human'}
])
def test_update_pet_with_bad_data(client, data):
rv = client.patch('/pets/1', json=data)
assert rv.status_code == 400
assert rv.json


@pytest.mark.parametrize('client', examples, indirect=True)
def test_delete_pet(client):
rv = client.delete('/pets/1')
assert rv.status_code == 204

rv = client.get('/pets/1')
assert rv.status_code == 404
assert rv.json

rv = client.delete('/pets/13')
assert rv.status_code == 404
assert rv.json

0 comments on commit e270458

Please sign in to comment.