Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you set up a Flask application with SQLAlchemy for testing?

It seems common practice in Flask to start like this:

from flask import Flask from flaskext.sqlalchemy import SQLAlchemy app = Flask(__name__) SQLALCHEMY_DATABASE_URI = 'something' app.config.from_object(__name__) db = SQLAlchemy(app) 

And then import and use app and db everywhere. But when you create db like this, it grabs configuration from the app, and it seems that this configuration can't ever be overridden once it happens. There are some pages on Flask's website about making application factories, but it's not clear how I would be able to still use app and db everywhere if I did that.

How do I write a script to test my Flask application with a different database? How should I structure my application to make this possible? Do I have to use modules ?

like image 308
Nick Retallack Avatar asked Feb 17 '11 06:02

Nick Retallack


People also ask

How do you test a Flask application?

If an application has automated tests, you can safely make changes and instantly know if anything breaks. Flask provides a way to test your application by exposing the Werkzeug test Client and handling the context locals for you.

How do I run a Flask in SQLAlchemy?

Step 1 - Install the Flask-SQLAlchemy extension. Step 2 - You need to import the SQLAlchemy class from this module. Step 3 - Now create a Flask application object and set the URI for the database to use. Step 4 - then use the application object as a parameter to create an object of class SQLAlchemy.

How do you run a test case in a Flask?

Running of Unit Tests One thing to keep in mind is to use the top-level folder of the flask application. We might need to import app, db like objects and hence would need to specify a location that is easily discoverable, and python interpreter can locate it easily.


1 Answers

Your instinct to use environment variables is correct. However, there is some danger of running unit tests with the wrong db. Also, you may not want to connect_db with every request and everywhere you want to use db. You can use a config directory and environment variables which you set explicitly. This is the best I've come up with so far.

run.py shell.py  config/__init__.py config/test.py config/postgres.py ...  main/__init__.py main/someapp/__init__.py main/someapp/models.py  ... main/tests/__init__.py main/tests/testutils.py 

so, the config files may be:

# config/test.py SQLALCHEMY_DATABASE_URI = "sqlite://" 

and

# config/postgres.py SQLALCHEMY_DATABASE_URI = 'postgresql://user:pw@localhost/somedb' 

So, I can explicitly set the db in my base TestCase:

import os from flask.ext.testing import TestCase  os.environ["DIAG_CONFIG_MODULE"] = "config.test" from main import app, db   class SQLAlchemyTest(TestCase):      def create_app(self):         return app      def setUp(self):         db.create_all()      def tearDown(self):         db.session.remove()         db.drop_all() 

Then, the main/__init__.py, for me:

import os  from flask import Flask, render_template, g from flask.ext.sqlalchemy import SQLAlchemy  # by default, let's use a DB we don't care about # but, we can override if we want config_obj = os.environ.get("DIAG_CONFIG_MODULE", "config.test") app = Flask(__name__) app.config.from_object(config_obj) db = SQLAlchemy(app)  @app.before_request def before_request():     g.db = db     g.app = app  # ... @app.route('/', methods=['GET']) def get():     return render_template('home.html') # ...     from main.someapp.api import mod as someappmod app.register_blueprint(someappmod) 

Then, in the other files, where I know what config I want to run, potentially:

# run.py import os os.environ["DIAG_CONFIG_MODULE"] = "config.postgres" from main import app app.run(debug=True) 

and

# shell.py import os os.environ["DIAG_CONFIG_MODULE"] = "config.postgres"  from main import app, db from main.symdiag.models import * from main.auth.models import * print sorted(k for k in locals().keys() if not k.startswith("_")) import IPython IPython.embed() 

Maybe .. best so far :P.

like image 113
Skylar Saveland Avatar answered Oct 10 '22 07:10

Skylar Saveland