Files
sigl/tests/conftest.py
2022-07-14 14:18:25 -07:00

137 lines
3.7 KiB
Python

"""Sigl Test Fixtures.
Simple Grocery List (Sigl) | sigl.app
Copyright (c) 2022 Asymworks, LLC. All Rights Reserved.
"""
import os
from alembic.command import upgrade
from alembic.config import Config
import flask
import pytest
from sigl.database import db as _db
from sigl.factory import create_app
DATA_DIR = '.pytest-data'
@pytest.fixture(scope='session')
def app_config(request):
"""Application Configuration for the Test Session.
Loads configuration from config/test.py, patches the database file with
a session-global temporary file, and returns the new configuration data
to pass to create_app().
"""
test_dir = os.path.dirname(__file__)
test_cfg = os.path.join(test_dir, '../config/test.py')
cfg_file = os.environ.get('SIGL_TEST_CONFIG', test_cfg)
cfg_data = flask.Config(test_dir)
cfg_data.from_pyfile(cfg_file)
# Patch Test Configuration
cfg_data['TESTING'] = True
cfg_data['DB_DRIVER'] = 'sqlite'
cfg_data['DB_FILE'] = os.path.join(test_dir, DATA_DIR, 'test.db')
# Ensure Database Path exists
db_dir = os.path.dirname(cfg_data['DB_FILE'])
if not os.path.isdir(db_dir):
os.mkdir(db_dir)
if not os.path.isdir(db_dir):
raise Exception('Database path "%s" does not exist' % (db_dir))
db_file = cfg_data['DB_FILE']
if os.path.exists(db_file):
os.unlink(db_file)
def teardown():
if os.path.exists(db_file):
os.unlink(db_file)
if os.path.exists(db_dir) and len(os.listdir(db_dir)) == 0:
os.rmdir(db_dir)
request.addfinalizer(teardown)
return cfg_data
@pytest.fixture(scope='module')
def app(request, app_config):
"""Module-Wide Sigl Flask Application with Database.
Loads configuration from config/test.py, patches the database file with
a session-global temporary file, and initializes the application.
"""
# Apply Database Migrations
_db.clear_mappers()
_app = create_app(app_config, __name__)
with _app.app_context():
alembic_config = Config('migrations/alembic.ini')
alembic_config.set_main_option('script_location', 'migrations')
upgrade(alembic_config, 'head')
_db.clear_mappers()
# Initialize Application and Context
app = create_app(app_config, __name__)
ctx = app.app_context()
ctx.push()
# Add Finalizers
def teardown():
_db.drop_all()
_db.clear_mappers()
if os.path.exists(app.config['DB_FILE']):
os.unlink(app.config['DB_FILE'])
ctx.pop()
request.addfinalizer(teardown)
return app
@pytest.fixture(scope='module')
def app_without_database(request, app_config):
"""Module-Wide Sigl Flask Application without Database.
Loads configuration from config/test.py and initializes the application,
but does not create the database.
"""
_db.clear_mappers()
# Initialize Application and Context
app = create_app(app_config, __name__)
ctx = app.app_context()
ctx.push()
# Add Finalizers
def teardown():
_db.clear_mappers()
_db.drop_all()
ctx.pop()
request.addfinalizer(teardown)
return app
@pytest.fixture(scope='function')
def session(request, monkeypatch, app):
"""Create a new Database Session for the Request."""
with app.app_context():
connection = _db.engine.connect()
transaction = connection.begin()
options = dict(bind=connection, binds={})
session = _db.create_scoped_session(options=options)
# Patch sigl.db with the current session
monkeypatch.setattr(_db, 'session', session)
def teardown():
transaction.rollback()
connection.close()
session.remove()
request.addfinalizer(teardown)
return session