Files
sigl/tests/conftest.py
2022-07-12 07:20:54 -07:00

138 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
import sigl
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