简体   繁体   English

使用Flask,Flask-SQLAlchemy和SQLAlchemy进行单元测试时,如何在线程之间隔离测试数据库?

[英]When unittesting with Flask, Flask-SQLAlchemy, and SQLAlchemy, how do I isolate test databases between threads?

Suppose I'm following the Flask-SQLAlchemy quickstart example, and I want to add a couple of unittests. 假设我正在关注Flask-SQLAlchemy快速入门示例,并且我想添加几个单元测试。

My model might look something like: 我的模型可能看起来像:

db = SQLAlchemy(app)
Base = db.Model

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

For unittesting, I'll want to create and destroy a database for each test. 对于单元测试,我想为每个测试创建和销毁数据库。

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(...)

The problem here is that, if I run this code in an environment where unittests are multi-threaded, there is a race condition. 这里的问题是,如果我在单元测试是多线程的环境中运行此代码,则存在竞争条件。 Two databases are usually setup simultaneously and app.config is pointed to one of them. 通常同时设置两个数据库,并将app.config指向其中一个。

If I were using SQLAlchemy directly, I would create a new session for each test and use that session. 如果我直接使用SQLAlchemy,我会为每个测试创建一个新会话并使用该会话。 But Flask-SQLAlchemy creates sessions for me, and as such, seems to depend on having one global app.config['SQLALCHEMY_DATABASE_URI'] to point to a database. 但Flask-SQLAlchemy为我创建了会话,因此,似乎依赖于有一个全局app.config['SQLALCHEMY_DATABASE_URI']指向数据库。

What's the right way to create test databases and point a test thread to them with Flask-SQLAlchemy? 使用Flask-SQLAlchemy创建测试数据库并将测试线程指向它们的正确方法是什么?

With unittest TestCase.setUp and TestCase.tearDown are run for each test_ functions. 使用unittest TestCase.setUpTestCase.tearDown为每个test_函数运行。

So running your test in multithreaded process will indeed create a RC. 因此,在多线程进程中运行测试确实会创建一个RC。 You need to either run your test in a single thread. 您需要在单个线程中运行测试。 Which will fix the RC, but you'll still create and destroy the all database for each test which is unnecessary and slow. 这将修复RC,但你仍然会为每个测试创建和销毁所有数据库,这是不必要的和缓慢的。

A better solution is to use the setUpclass and tearDownClass methods, which only run once per test class. 更好的解决方案是使用setUpclasstearDownClass方法,每个测试类只运行一次。

If you need to run this fixtures for all classes in a module there is also setUpModule and tearDownModule . 如果需要为模块中的所有类运行此fixture,还有setUpModuletearDownModule

If you need to set fixtures for the full session now you have a problem... IMHO that is the time to switch to pytest. 如果你现在需要为整个会话设置灯具你有问题...恕我直言,是时候切换到pytest。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM