Flask-Script загружает приложение перед запуском юнит-тестов

Я использую Flask-Script для запуска тестов в моем приложении, важный фрагмент моего файла manage.py выглядит так:

import unittest

from flask.ext.script import Manager
from project import app

manager = Manager(app)

@manager.command
def test():
    """Run unit tests."""
    app.config.from_object('config.Test')
    tests = unittest.TestLoader().discover('tests', pattern='*.py')
    unittest.TextTestRunner(verbosity=1).run(tests)

Но когда я запускаю python manage.py test, он пытается инициализировать все приложение, поэтому, если, например, я не установил переменные среды, он выдает KeyError из файла __init__.py моего проекта следующим образом:

File "project/__init__.py", line 19, in <module> app.config.from_object(os.environ['PROJECT_SETTINGS'])

Или, если я установил переменную среды, я получаю сообщение об ошибке об отсутствующих таблицах базы данных.

Конечно, приложение должно инициализироваться только после запуска тестов и установки переменных конфигурации в функции test().


person hammygoonan    schedule 08.02.2016    source источник
comment
Вы импортируете app в верхней части модуля. Когда вы это сделаете, все внутри project/__init__.py запустится.   -  person dirn    schedule 08.02.2016
comment
Спасибо @dim. Проблема в том, что Manager требует этого, поэтому я не понимаю, как это обойти.   -  person hammygoonan    schedule 08.02.2016


Ответы (1)


Есть несколько вещей, которые вам нужно сделать, чтобы заставить это работать.

  1. Установите отсутствующие переменные среды (как вы уже сказали).

  2. Создайте тестовую базу данных для своих тестов и включите в тесты функции setup и teardown, которые создают таблицы и удаляют их соответственно.

Чтобы обойти первый шаг, я предлагаю использовать шаблон фабрики приложений Flask, который позволяет вам чтобы инкапсулировать создание вашего приложения внутри функции. Это позволит вам передавать любые переменные и т. д., необходимые для запуска вашего приложения в тестовой среде, т.е.

def create_application(is_test=False):
    app = Flask(__name__)
    if not is_test:
       setup_app_not_for_test(app)
    else:
       setup_test_for_app(app)

    return app

Что касается шага номер 2, если вы используете pytest, нос или любую другую среду тестирования, которая использует фикстуры, вы можете легко добавить функции setup и teardown для добавления/удаления таблиц базы данных. Кроме того, если вы используете ORM, например sqlalchemy, вы можете создать SQLite в памяти. база данных очень легко запускать ваши тесты.

# create db instance
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://:memory:"

# create all your tables
db.create_all()

# drop all your tables
db.drop_all()
person pech0rin    schedule 08.02.2016
comment
Отлично, @pech0rin - мне придется немного реорганизовать это приложение и покончить с Flask-Script, но теперь я вижу, как все это работает. Благодаря вашему ответу я также нашел это - person hammygoonan; 09.02.2016