Flask TodoMVC: Configuration
This is the fourth article in the Flask TodoMVC tutorial, a series that creates a Backbone.js backend with Flask for the TodoMVC app. In this article, we will setup unit testing and demonstrate custom configuration used during testing. We do this in preparation for the next article, where we will create unit tests against the todo api.
Previous articles in this series:
# Optional, use your own code if you followed the previous article $ git clone https://github.com/kevinbeaty/flask-todomvc $ cd flask-todomvc $ git checkout -b config dataset
Let's get started.
We would like to create tests that run against a test database without
affecting our actual todo list. If you lookup
you may notice that we have a problem. The database connects before we
have a chance to change the database URL.
db = dataset.connect('sqlite:///todos.db') todos = db['todos'] app = Flask(__name__, static_url_path='') app.debug = True
We need to allow changing the database URL to a temporary file during testing.
To do this, we are going to use default configuration within
but allow overriding the settings by loading from a file specified by an
Change the above code to the following:
app = Flask(__name__, static_url_path='') app.config.from_object('config.default') app.config.from_envvar('TODO_SETTINGS', silent=True) db = dataset.connect(app.config['DATABASE']) todos = db['todos']
After we create the app, we load the configuration with default parameters
We then call
from_envvar to allow overriding the default configuration
with custom values (more later). We pass
silent=True so it will not complain
if we don't use an environment variable, such as when we run
Finally, we lookup the database URL from the configuration.
Let's add our default configuration file. First, create a
$ mkdir config $ touch config/__init__.py
config/default.py and add the default database URL and debug flag.
# config/default.py DATABASE = 'sqlite:///todos.db' DEBUG = True
With these changes, we added the ability to override the database URL during testing by passing custom settings using an environment variable. We are now ready to create our first test.
Remember, we wanted to use a custom database URL during testing. Let's create
a testing configuration file in
# config/testing.py DATABASE = 'sqlite:///test.db' TESTING = True
This overrides the default database URL to
test.db. It also sets the testing flag,
which enables better error reporting when using the test client.
Since our app is still small, we are going to simply include all our tests in
and import the app after configuring the correct configuration file.
# tests.py import os import unittest from os import path base_path = path.dirname(path.realpath(__file__)) cfg_path = path.join(base_path, 'config', 'testing.py') os.environ['TODO_SETTINGS'] = cfg_path import server
We programmatically created the path to
testing.py relative to the tests script
and set the
TODO_SETTINGS environment variable. Note that you pass the full
path to the settings. This would allow creating a custom production configuration
external from your app and simply providing the path when you start the server.
Also notice that the environment variable was set before
import server. This ensures
the correct settings are loading at import time.
We are finally ready to create our first test. We are going to write a test to
ensure that the custom database URL is set when importing
class TodoTestCase(unittest.TestCase): def test_config_settings(self): config = server.app.config assert config['DATABASE'] == 'sqlite:///test.db' assert config['TESTING'] assert config['DEBUG'] if __name__ == '__main__': unittest.main()
This is mostly boilerplate code using the
unittest module. We create a
test case by and run main if loaded as a script. This will run any method
on our test case that begins with "test".
In the test, we assert that the test database was configured correctly and the testing and debug flags are set. Note that the debug flag was inherited from the default settings since the testing configuration did not override it.
In this article, we setup boilerplate for unit testing our app. To do this, we had to allow custom configuration of the database URL to test against a temporary database. In the next article, we will put this to good use and create unit tests against the todo api.
For further information, please visit the Flask Configuration Handling documentation.