flaskflask-sqlalchemysqlite3-python

Make unittest in flask use in-memory sqlite db


The complete code is hosted here The intention is to use an in-memory sqlite db for testing. However my dev instance db is being used. As I can find my data being deleted in the dev db.

My tests\BaseCase.py is as follows:

import sys
sys.path.append('..')
from app import create_app
from app.exts import db

import unittest

class BaseCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app()
        self.app.config.from_object('config.TestConfig')
        self.client = self.app.test_client(self)

        self.app_ctxt = self.app.app_context()
        self.app_ctxt.push()        
        db.create_all() # < --- update

    def tearDown(self):
        db.session.remove()
        db.drop_all() # < --- update        
        self.app_ctxt.pop()        
        self.app = None        
        self.app_ctxt = None 

if __name__ == '__main__':
    unittest.main()

My config.py is as follows:

import os

class BaseConfig(object):
    SECRET_KEY = 'o\xadlT\x97\x82\x1e[\xc6aeFv\x90\xdc\xcc'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class TestConfig(BaseConfig):
    TESTING = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'

class DevelopmentConfig(BaseConfig):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///dev.db'

class ProductionConfig(BaseConfig):
    DEBUG = False

app\exts.py is as follows:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

app\__init__.py is as follows:

from flask import Flask

from flask_restx import Api
from flask_migrate import Migrate

from flask_jwt_extended import JWTManager
from flask_cors import CORS

from app.models import User
from app.exts import db
from flask_marshmallow import Marshmallow

from app.resources.auth import auth_namespace
from app.resources.reset_password import reset_password_namespace
from app.resources.task import task_namespace

def create_app():
    app = Flask(__name__)
    # Configuration
    ma = Marshmallow(app)
    app.config.from_object('config.DevelopmentConfig')

    db.init_app(app)

    Migrate(app, db)

    JWTManager(app)
    CORS(app)

    api = Api(app, title='Authentication API', doc='/')
    api.add_namespace(auth_namespace, path='/api/auth')
    api.add_namespace(reset_password_namespace, path='/api/')
    api.add_namespace(task_namespace, path='/api/task')

    @app.shell_context_processor
    def make_shell_context():
        return { 'db': db, 'User': User }

    return app

I have looked for different configs to get my test cases to use an in memory db without touching my dev instance.


Solution

  • You're very nearly there. Instead of

    def create_app():
        ...
        app.config.from_object('config.DevelopmentConfig')
    

    do

    def create_app(config_class):
        ...
        app.config.from_object(config_class)
    

    Then pass either config.DevelopmentConfig or config.TestConfig when creating the app.