Permalink
Browse files

Updated tests to test Flask-SQLAlchemy models, if that package is ins…

…talled.
  • Loading branch information...
1 parent 70fa31b commit c3489c58141bb29145cd25043c810538013a71bc @jfinkels committed Apr 16, 2012
Showing with 118 additions and 10 deletions.
  1. +21 −10 tests/helpers.py
  2. +97 −0 tests/test_manager.py
View
@@ -65,7 +65,25 @@ def tearDownModule():
DB['filename'] = None
-class TestSupport(TestCase):
+class FlaskTestBase(TestCase):
+ """Base class for tests which use a Flask application."""
+
+ def setUp(self):
+ """Creates the Flask application and the APIManager."""
+ super(FlaskTestBase, self).setUp()
+
+ # create the Flask application
+ app = Flask(__name__)
+ app.config['DEBUG'] = True
+ app.config['TESTING'] = True
+ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///%s' % DB['filename']
+ self.flaskapp = app
+
+ # create the test client
+ self.app = app.test_client()
+
+
+class TestSupport(FlaskTestBase):
"""Base class for tests which use a database and have an
:class:`flask_restless.APIManager` with a :class:`flask.Flask` app object.
@@ -77,14 +95,10 @@ class TestSupport(TestCase):
def setUp(self):
"""Creates the Flask application and the APIManager."""
- # create the Flask application
- app = Flask(__name__)
- app.config['DEBUG'] = True
- app.config['TESTING'] = True
- app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///%s' % DB['filename']
- self.flaskapp = app
+ super(TestSupport, self).setUp()
# initialize SQLAlchemy and Flask-Restless
+ app = self.flaskapp
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'],
convert_unicode=True)
self.session = scoped_session(sessionmaker(autocommit=False,
@@ -119,9 +133,6 @@ class Person(self.Base):
# create all the tables required for the models
self.Base.metadata.create_all()
- # create the test client
- self.app = app.test_client()
-
def tearDown(self):
"""Drops all tables from the temporary database."""
#self.session.remove()
View
@@ -9,14 +9,23 @@
"""
import datetime
+from unittest2 import skipUnless
+from unittest2 import TestCase
from unittest2 import TestSuite
from flask import Flask
from flask import json
+try:
+ from flask.ext.sqlalchemy import SQLAlchemy
+except:
+ has_flask_sqlalchemy = False
+else:
+ has_flask_sqlalchemy = True
from flask.ext.restless import APIManager
from flask.ext.restless.views import _get_columns
+from .helpers import FlaskTestBase
from .helpers import setUpModule
from .helpers import tearDownModule
from .helpers import TestSupport
@@ -260,8 +269,96 @@ def test_different_urls(self):
self.assertEqual(response.status_code, 404)
+class FSATest(FlaskTestBase):
+ """Tests which use models defined using Flask-SQLAlchemy instead of pure
+ SQLAlchemy.
+
+ """
+
+ def setUp(self):
+ """Creates the Flask application, the APIManager, the database, and the
+ Flask-SQLAlchemy models.
+
+ """
+ super(FSATest, self).setUp()
+
+ # initialize SQLAlchemy and Flask-Restless
+ self.db = SQLAlchemy(self.flaskapp)
+ self.manager = APIManager(self.flaskapp, flask_sqlalchemy_db=self.db)
+
+ # for the sake of brevity...
+ db = self.db
+
+ # declare the models
+ class Computer(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.Unicode, unique=True)
+ vendor = db.Column(db.Unicode)
+ buy_date = db.Column(db.DateTime)
+ owner_id = db.Column(db.Integer, db.ForeignKey('person.id'))
+
+ class Person(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.Unicode, unique=True)
+ age = db.Column(db.Float)
+ other = db.Column(db.Float)
+ birth_date = db.Column(db.Date)
+ computers = db.relationship('Computer',
+ backref=db.backref('owner',
+ lazy='dynamic'))
+ self.Person = Person
+ self.Computer = Computer
+
+ # create all the tables required for the models
+ self.db.create_all()
+
+ def tearDown(self):
+ """Drops all tables from the temporary database."""
+ self.db.drop_all()
+
+ def test_flask_sqlalchemy(self):
+ """Tests that :class:`flask.ext.restless.APIManager` correctly exposes
+ models defined using Flask-SQLAlchemy.
+
+ """
+ # create three different APIs for the same model
+ self.manager.create_api(self.Person, methods=['GET', 'POST'])
+ self.manager.create_api(self.Person, methods=['PATCH'],
+ url_prefix='/api2')
+ self.manager.create_api(self.Person, methods=['GET'],
+ url_prefix='/readonly')
+
+ # test that specified endpoints exist
+ response = self.app.post('/api/person', data=dumps(dict(name='foo')))
+ self.assertEqual(response.status_code, 201)
+ self.assertEqual(loads(response.data)['id'], 1)
+ response = self.app.get('/api/person')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(loads(response.data)['objects']), 1)
+ self.assertEqual(loads(response.data)['objects'][0]['id'], 1)
+ response = self.app.patch('/api2/person/1',
+ data=dumps(dict(name='bar')))
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(loads(response.data)['id'], 1)
+ self.assertEqual(loads(response.data)['name'], 'bar')
+
+ # test that the model is the same as before
+ response = self.app.get('/readonly/person')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(loads(response.data)['objects']), 1)
+ self.assertEqual(loads(response.data)['objects'][0]['id'], 1)
+ self.assertEqual(loads(response.data)['objects'][0]['name'], 'bar')
+
+
+# skipUnless should be used as a decorator, but Python 2.5 doesn't have
+# decorators.
+FSATest = skipUnless(has_flask_sqlalchemy,
+ 'Flask-SQLAlchemy not found.')(FSATest)
+
+
def load_tests(loader, standard_tests, pattern):
"""Returns the test suite for this module."""
suite = TestSuite()
suite.addTest(loader.loadTestsFromTestCase(APIManagerTest))
+ suite.addTest(loader.loadTestsFromTestCase(FSATest))
return suite

0 comments on commit c3489c5

Please sign in to comment.