Flask 脚本在 运行 单元测试之前加载应用程序

Flask-Script loads app before running unittests

我正在使用 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'])

或者如果我设置了环境变量,我会收到有关缺少数据库表的错误。

当然,应用程序应该只在测试 运行ning 并且配置变量已在 test() 函数中设置后才初始化。

您需要做一些事情才能使其正常工作。

  1. 设置缺少的环境变量(如您所说)。

  2. 为您的测试创建一个测试数据库,并让您的测试包含一个 setup 和一个 teardown 函数来分别创建和删除它们。

为了解决第一步,我建议使用 Flask application factory pattern,它允许您将应用程序创建封装在一个函数中。这将允许您在测试环境下传递运行您的应用程序所需的任何变量等,即

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 或 nose 或任何使用固定装置的测试框架,您可以轻松地将 setupteardown 函数添加到 add/drop数据库表。此外,如果您使用像 sqlalchemy 这样的 ORM,您可以很容易地创建一个 SQLite in memory database 来 运行 您的测试。

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

# create all your tables
db.create_all()

# drop all your tables
db.drop_all()