I am using alembic for database revisions pretty much as intended probably. Instead of defining the database string in alembic.ini
, I am using the env.py
file to dynamically get the database credentials from the config module, pretty much as follows:
SQLALCHEMY_DATABASE_URL = "%s://%s:%s@%s:%d/%s" % (settings.db_type, settings.db_username, settings.db_password, settings.db_host, settings.db_port, settings.db_database)
def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
connectable = create_engine(SQLALCHEMY_DATABASE_URL)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
The problem now is that I am adding pytest tests, which are using a separate database connection. Essentially what I am doing is creating a database, applying migrations, add test data, run tests, delete the database.
From within pytest I am using it as follows:
@pytest.fixture(scope="session")
def initialize_database(create_database):
"""
Executes all alembic versions against the empty database to get the general structure up and running.
No need to yield / delete as the entire database is deleted anyway as part of the `create_database` yield fixture
"""
# retrieves the directory that *this* file is in
root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
# this assumes the alembic.ini is also contained in this same directory
config_file = os.path.join(root_dir, "alembic.ini")
migrations_dir = os.path.join(root_dir, "alembic")
config = Config(file_=config_file)
config.set_main_option("script_location", migrations_dir)
command.upgrade(config, 'head')
I tried to specify different database credentials here, but the values in the env.py
overrides it. How can I specify different database credentials in such a setup?
I found a solution myself, its actually quite simple. When calling the upgrade
command from the test fixture, I set two additional config values as follows:
config.set_main_option("is_testing", "True")
config.set_main_option('sqlalchemy.url', SQLALCHEMY_DATABASE_URL)
Within the env.py
file, I can use this testing option to dynamically change the SQLAlchemy url as follows:
SQLALCHEMY_DATABASE_URL = "%s://%s:%s@%s:%d/%s" % (settings.db_type, settings.db_username, settings.db_password, settings.db_host, settings.db_port, settings.db_database)
if config.get_main_option("is_testing", "False") == "True":
url = config.get_main_option("sqlalchemy.url")
else:
url = SQLALCHEMY_DATABASE_URL
It works well like that.