Вопрос

I've got a Flask application which I'd like to run some unit tests on. To do so, I create a new Flask object, initialise blueprints, SQLA and a few other packages and execute the test case.

However, I've noticed that some endpoints on the test flask object are missing, which made me wonder about the general way of how initialisation is handled in flask.

Taking a minimal example, an endpoint would be created like so:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

If I was to create a new Flask object somewhere in my testcase's setUp method, it would most certainly not contain a route '/' as this route was created from another flask object (the one from the file above). So my question is: How should a test case be written and how is the initialisation meant to work in general? Somewhere I read that one should avoid initialisation at import (i.e. on a module level), but this seems to be impossible if annotations are used.

Это было полезно?

Решение

You don't create a new Flask object in your test cases. You import your existing app instead.

In many project setups you already added all your extensions to that app. In many of mine I have a factory method that'll take a configuration object and returns the fully initialized app object for me; I use this to create a base test case:

import unittest

import project


class Config(object):
    DEBUG = False
    TESTING = True
    CACHE_NO_NULL_WARNING = True  # silence Flask-Cache warning
    SECRET_KEY = 'SECRET_KEY'


class ProjectCoreViewCase(unittest.TestCase):
    """Base test case for the Project core app"""

    def setUp(self, **kwargs):
        config = Config()
        config.__dict__.update(kwargs)
        app = project.create_app(config)
        self.app = app.test_client()

and any tests can then use self.app as the test client in all tests.

This is a base test case, you'd inherit from it; the setUp() method allows for additional configuration to be set, by passing in keyword arguments to a super() call:

class ConcreteTestCase(ProjectCoreViewCase):
    def setUp(self):
        super(ConcreteTestCase, self).setUp(
            SQLALCHEMY_DATABASE_URI='your_test_specific_connection_uri',
        )
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top