【问题标题】:Flask-Script loads app before running unittestsFlask-Script 在运行单元测试之前加载应用程序
【发布时间】:2016-02-08 18:04:18
【问题描述】:

我正在使用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 时,它会尝试初始化整个应用程序,因此,例如,如果我没有设置环境变量,它会从我的项目的 __init__.py 文件中抛出一个 KeyError,如下所示:

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

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

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

【问题讨论】:

  • 您在模块顶部导入app。当您这样做时,project/__init__.py 中的任何内容都会运行。
  • 谢谢@dim。问题是 Manager 需要它,所以我不知道如何解决这个问题。

标签: python flask python-unittest flask-script


【解决方案1】:

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

  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 函数来添加/删除数据库表。此外,如果您使用像 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()

【讨论】:

  • 不错的@pech0rin - 我将不得不稍微重构这个应用程序并取消 Flask-Script 但我现在可以看到它是如何工作的。感谢您的回答,我还找到了this
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
相关资源
最近更新 更多