【问题标题】:When unittesting with Flask, Flask-SQLAlchemy, and SQLAlchemy, how do I isolate test databases between threads?使用 Flask、Flask-SQLAlchemy 和 SQLAlchemy 进行单元测试时,如何在线程之间隔离测试数据库?
【发布时间】:2017-07-10 20:40:18
【问题描述】:

假设我正在关注Flask-SQLAlchemy 快速入门示例,并且我想添加几个单元测试。

我的模型可能类似于:

db = SQLAlchemy(app)
Base = db.Model

class Account(Base):
    id = Column(Integer, primary_key=True)
    name = Column(String(1000))

对于单元测试,我想为每个测试创建和销毁一个数据库。

def _setup_database():
    db_name = 'test_%s' % random.randint(0,999999)

    # (Code that creates database with db_name and setups the schema)

    app.config['DB_NAME'] = db_name
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///{}'.format(db_name)


def _destroy_db():
    db_name = app.config['DB_NAME']

    # Code that destroys the test db


class TestAccounts(unittest.TestCase):
    def setUp(self):
        _setup_database()

    def tearDown(self):
        _destroy_db()

    def test_new_signup(self):
        account = models.Account(...)

    def test_something_else(self):
        account = models.Account(...)

这里的问题是,如果我在单元测试是多线程的环境中运行此代码,则会出现竞争条件。通常同时设置两个数据库,app.config 指向其中一个。

如果我直接使用 SQLAlchemy,我将为每个测试创建一个新会话并使用该会话。但是 Flask-SQLAlchemy 为我创建了会话,因此,似乎依赖于一个全局的 app.config['SQLALCHEMY_DATABASE_URI'] 指向一个数据库。

使用 Flask-SQLAlchemy 创建测试数据库并将测试线程指向它们的正确方法是什么?

【问题讨论】:

  • 没有答案,但很好奇为什么要进行多线程测试?似乎是不必要的复杂层。
  • @Adam 它使测试完成得更快。大多数人不使用多线程进行单元测试吗?
  • 我从来没有做过。我的工作没有健全的 CI/测试方案。

标签: python flask flask-sqlalchemy


【解决方案1】:

使用 unittest TestCase.setUpTestCase.tearDown 为每个 test_ 函数运行。

所以在多线程进程中运行测试确实会创建一个 RC。您需要在单个线程中运行测试。这将修复 RC,但您仍将为每个测试创建和销毁所有数据库,这是不必要且缓慢的。

更好的解决方案是使用setUpclass and tearDownClass 方法,每个测试类只运行一次。

如果您需要为模块中的所有类运行此固定装置,还有 setUpModuletearDownModule

如果您现在需要为整个会话设置固定装置,那么您遇到了问题......恕我直言,现在是切换到 pytest 的时候了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 2013-07-21
    • 2020-05-27
    • 1970-01-01
    • 2014-09-21
    • 2021-12-11
    相关资源
    最近更新 更多