I have this code:
my_app.py:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["BASE_DIR"] = os.path.abspath(os.path.dirname(__file__))
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + os.path.abspath(os.path.join(app.config["BASE_DIR"], "app.db"))
db = SQLAlchemy(app)
from user import User
# create all tables
db.create_all()
if not User.query.filter_by(username="test").first():
dummy_user = User(username="test", password="", email="")
db.session.add(dummy_user)
db.session.commit()
user.py:
from flask.ext.login import UserMixin
from my_app import db
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(255), nullable=False, unique=True)
email = db.Column(db.String(255), nullable=False, unique=True)
password = db.Column(db.String(255), nullable=False)
tests.py:
from flask.ext.testing import TestCase
from my_app import app, db
from user import User
import os
import unittest
class MyTestCase(TestCase):
def create_app(self):
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:"
app.config["TESTING"] = True
return app
def setUp(self):
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
def test_dummy(self):
assert User.query.count() == 0
if __name__ == '__main__':
unittest.main()
How can I make the unit test work?
I want my unit tests to use an in-memory database separate from the main application, but apparently I can not do it the way I'm trying to (by just changing the SQLALCHEMY_DATABASE_URI value)
Thanks in advance!
Sounds like the perfect case for inherited configurations!
Have you tried using the template found here ? The Config base class contains settings that are common to all your different environments. But you can have a development environment that uses an in-memory database. For example:
class Config:
# pass
class DevConfig(Config):
SQLALCHEMY_DATABASE_URI = 'sqlite://path_to_in_memory_db'
class ProductionConfig(Config):
SQLALCHEMY_DATABASE_URI = 'postgresql://path_to_production_db'
It's also worth looking into using a factory pattern to create your app.
Okay, so I found a solution or rather a workaround:
I used an environment variable to specify an additional config file to be loaded before initializing the db instance.
So I ended up doing this:
app.config.from_object("app.config.production")
additional_config = os.environ.get("ADDITIONAL_CONFIG")
if additional_config:
app.config.from_object(additional_config)
in my my_app.py and this in my tests.py:
os.environ["ADDITIONAL_CONFIG"] = "app.config.testing"
from my_app import app, db
(it is of course important to define the environment variable before importing the app object)
Thanks anyway.
I used environment variables to choose the db with pytest. This works well when using docker-compose to specify a production DB instead of sqllite for dev.
# app.py
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
DATABASE = os.environ.get("DB_URI", f"sqlite:///{os.path.join(BASE_DIR, 'app.db')}")
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = DATABASE
And then in test.py inject the DB_URI environment variable to specify a memory db before you import the app or db:
import pytest
import os
os.environ['DB_URI'] = "sqlite:///:memory:"
from app import app, db
from models import Model1, Model2
@pytest.fixture
def client():
client = app.test_client()
with app.app_context():
db.create_all()
prepare_data()
yield client
db.drop_all()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.