Search code examples
pythonsqliteflaskflask-sqlalchemyflask-testing

How to setup testing script in Flask with SQLite?


I'm trying to do unit testing of my Flask web app. I'm use a pattern I saw in a Udemy class on Flask and a pattern similar to the Flask Mega-Tutorial online (http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-unit-testing). The problem I'm having is that the test does not actual create it's own database -- rather it uses the production database and messes it up.

Here's what tests.py script looks like:

import os,sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
basedir = os.path.abspath(os.path.dirname(__file__))

import unittest
from myapp import app, db
from user.models import User

class UserTest(unittest.TestCase):

    def setUp(self):
        self.db_uri = 'sqlite:///' + os.path.join(basedir, 'test.db')
        app.config['TESTING'] = True
        app.config['WTF_CSRF_ENABLED'] = False
        app.config['SQL_ALCHEMY_DATABASE_URI'] = self.db_uri
        self.app = app.test_client()
        db.create_all()

    def tearDown(self):
        db.session.remove()
        db.drop_all()

    def test_models(self):
        #Create a customer user
        user = User("John Doe", "[email protected]", "jdoe", "password", is_consultant=False)
        db.session.add(user)
        db.session.commit()

        #Create 2 consultant users
        user1 = User("Jane Doe", "[email protected]", "janedoe", "password", is_consultant=True)
        db.session.add(user1)
        user2 = User("Nikola Tesla", "[email protected]", "nikola", "password", is_consultant=True)
        db.session.add(user2)
        db.session.commit()

        #Check that all users exist
        assert len(User.query.all()) is 3

My app init is in the same folder and looks like so:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.migrate import Migrate
from flask.ext.login import LoginManager

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)

# flask-login extension setup
login_manager = LoginManager()
login_manager.init_app(app)

# migration setup
migrate = Migrate(app, db)

from user import views

I don't understand what is going on. It never creates the test.db SQLite database. It always creates the app.db production database. And if it's there, it totally messes up the database is there. Afterwards if I do python manage.py runserver -- it doesn't work anymore. It says table not found. Because the teardown dropped all the tables. What is going on? And how do I fix it?


Solution

  • Omigod I figured it out. I was setting the wrong key for the database URI. It should be: app.config['SQLALCHEMY_DATABASE_URI'] = self.db_uri.

    So everything is fine. Just do:

    class UserTest(unittest.TestCase):
    
        def setUp(self):
            self.db_uri = 'sqlite:///' + os.path.join(basedir, 'test.db')
            app.config['TESTING'] = True
            app.config['WTF_CSRF_ENABLED'] = False
            app.config['SQLALCHEMY_DATABASE_URI'] = self.db_uri
            self.app = app.test_client()
            db.create_all()
    

    and everything works as intended.

    I checked what was going on by putting a break-point in the tests and seeing what app.config was -- and I saw that there was both a SQL_ALCHEMY_DATABASE_URI key (which doesn't do anything and I was setting) and a SQLALCHEMY_DATABASE_URI key (this is the one that matters).