Already-defined configuration variables not being automatically loaded when creating app in pytest fixture

Issue

This Content is from Stack Overflow. Question asked by Oyugo Obonyo

I am building a flask application and I have used a ‘create_app’ factory function to create an instance of the application. The factory function is as follows:

from config import Config
from flask import Flask
from dotenv import load_dotenv
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate(render_as_batch=True)

def create_app(config_class: Config):
    load_dotenv()
    app = Flask(__name__)
    app.config.from_object(config_class)

    db.init_app(app)
    migrate.init_app(app, db)
    
    from app.auth import bp as auth_bp
    app.register_blueprint(auth_bp)

    return app

I am using this pattern because I intend to use different configurations across different instances of my application i.e development, testing and production instances. This functionality is implemented by creating a configuration class within a config.py file, storing the configurations as attributes within the configuration class and passing this class as an argument to the create_app() function. For example, an app to be used during development can be created as follows:

from app import create_app
from config import DevelopmentConfig

app = create_app(config_class=DevelopmentConfig)

app.run(port=5500)

The following config classes exist within config.py:

import os


class Config(object):
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    TESTING = False

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")

class TestingConfig(Config):
    SQLALCHEMY_DATABASE_URI = os.environ.get("TEST_DATABASE_URL")
    TESTING = True

While building my app’s test_suite, I have created a different app instance for testing as follows:

from app import create_app
from config import TestingConfig
import pytest


@pytest.fixture(scope="session")
def app():
    app = create_app(config_class=TestingConfig)
    return app

I have created a different testing instance because I intend to separate resources I use for testing from those I use for development, most notably the database.
To confirm that the resources are indeed separated, I have written a test to confirm my testing instance’s configurations:

import os


def test_app_configurations(app):
    assert app.config["TESTING"] is True
    assert app.config["SQLALCHEMY_DATABASE_URI"] == os.environ.get("TEST_DATABASE_URL")

This test however fails and I am hit with the following assertion error:

 def test_app_configurations(app):
        assert app.config["TESTING"] is True
>       assert app.config["SQLALCHEMY_DATABASE_URI"] == os.environ.get("TEST_DATABASE_URL")
E       AssertionError: assert None == 'postgresql://test_user:password@localhost:5432/test_db'

To make this test pass, I have to explicitly declare my database URL in my app fixture after the create_app() function as follows:

@pytest.fixture(scope="session")
def app():
    app = create_app(config_class=TestingConfig)
    app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("TEST_DATABASE_URL")
    return app

I am however a bit confused. When running a development instance of the application, the attributes declared in the DevelopmentConfig class are automatically attached to the development instance. Why is that not the case for the testing instance. Why do I have to explicitly re-declare what I have already declared in the TestConfig class attributes? Is there something else I can do to make the test pass without having to reassign instances during testing when I already assigned the as class attributes in the TestConfig?



Solution

This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.

This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?