Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flask create_app and setUp unittest

So I have setted up my flask in this way:

def create_app(config_name):
    app = Flask(__name__, static_folder='../designs/UI', template_folder='../designs/UI', instance_relative_config=True)

    app.config.from_object(app_config[config_name])
    app.config.from_pyfile('config.py')

    db.init_app(app)

    login_manager.init_app(app)
    login_manager.login_message = "You must be logged in to access this page."
    login_manager.login_view = "auth.login_page"

    migrate = Migrate(app, db)

    from app import models

    from .api import blueprint as api_blueprint
    app.register_blueprint(api_blueprint, url_prefix='/api/v1.0')

    @app.route('/')
    def homepage():
        return redirect('/api/v1.0')

    return app

And my unittest setup:

def setUp(self):
    """setup test variables"""
    self.app = create_app(config_name="testing")
    self.client = self.app.test_client

    # binds the app with the current context
    with self.app.app_context():
        #create all tables
        db.session.close()
        db.drop_all()
        db.create_all()

When I import my models into the test file and try to access anything from the database I get the following error:

RuntimeError: application not registered on db instance and no applicationbound to current context

Is there any better way to set up the entire thing so that it may work?

like image 986
Harith Avatar asked Jan 20 '18 08:01

Harith


People also ask

Where do I put tests in the Flask app?

Tests are typically located in the tests folder. Tests are functions that start with test_ , in Python modules that start with test_ . Tests can also be further grouped in classes that start with Test .


1 Answers

I decided to explain the problem(and solution) in detail.

1) Why your way doesn't work? Because you trying to push app context using Context Manager. What does it mean? current context will be available only inside with block. You bind context and he available only in setUp, but not in tests. app will works without context when setUp() is finished. Let's look at this example:

app = Flask(__name__)

class TestCase(TestCase):

    def setUp(self):
        with app.app_context():
            # current_app is available(you will see <Flask 'app'> in terminal)
            print current_app
        # out of context manager - RuntimeError: Working outside of application context.
        print current_app

    def test_example(self):
        pass

Run test. You'll be see Flask 'app' + exception. The error will disappear if you remove last print(out of with block).

2) How to fix the problem? You can bind app context without Context Manager.

class TestCase(TestCase):

    def setUp(self):
        ctx = app.app_context()
        ctx.push()
        # after this you can use current_app
        print current_app

    def test_example(self):
        # available because we pushed context in setUp()
        print current_app

Run test:

<Flask 'app'> # from setUp()
<Flask 'app'> # from test_example

So, let's sum up. current_app is available ONLY 'inside' Context Manager. But you can bind context without Context Manager.

I hope that I have explained the details and answered your questions.

like image 78
Danila Ganchar Avatar answered Oct 22 '22 04:10

Danila Ganchar