gpt4 book ai didi

python - 如何正确运行查询 Flask-SQLAlchemy 数据库的连续测试?

转载 作者:行者123 更新时间:2023-12-01 07:55:32 28 4
gpt4 key购买 nike

我正在使用 SQLAlchemy 作为 ORM 为 Flask 项目设置单元测试。对于我的测试,每次运行单个单元测试时,我都需要设置一个新的测试数据库。不知何故,我似乎无法运行查询数据库的连续测试,即使我单独运行这些测试它们也会成功。

我使用flask-testing包,并遵循他们的文档here

这是一个说明问题的工作示例:

app.py:

from flask import Flask


def create_app():
app = Flask(__name__)
return app


if __name__ == '__main__':
app = create_app()
app.run(port=8080)

数据库.py:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

models.py:

from database import db


class TestModel(db.Model):
"""Model for testing."""

__tablename__ = 'test_models'
id = db.Column(db.Integer,
primary_key=True
)

测试/__init__.py:

from flask_testing import TestCase

from app import create_app
from database import db


class BaseTestCase(TestCase):
def create_app(self):
app = create_app()
app.config.update({
'SQLALCHEMY_DATABASE_URI': 'sqlite:///:memory:',
'SQLALCHEMY_TRACK_MODIFICATIONS': False,
'TESTING': True
})
db.init_app(app)
return app

def setUp(self):
db.create_all()

def tearDown(self):
db.session.remove()
db.drop_all()

test/test_app.py:

from models import TestModel
from test import BaseTestCase
from database import db


test_model = TestModel()


class TestApp(BaseTestCase):
"""WebpageEnricherController integration test stubs"""

def _add_to_db(self, record):
db.session.add(record)
db.session.commit()
self.assertTrue(record in db.session)

def test_first(self):
"""
This test runs perfectly fine
"""
self._add_to_db(test_model)
result = db.session.query(TestModel).first()
self.assertIsNotNone(result, 'Nothing in the database')

def test_second(self):
"""
This test runs fine in isolation, but fails if run consecutively
after the first test
"""
self._add_to_db(test_model)
result = db.session.query(TestModel).first()
self.assertIsNotNone(result, 'Nothing in the database')


if __name__ == '__main__':
import unittest
unittest.main()

因此,如果单独运行,我可以很好地运行 TestApp.test_firstTestApp.test_second 。如果我连续运行它们,第一个测试会通过,但第二个测试会失败:

=================================== FAILURES ===================================
_____________________________ TestApp.test_second ______________________________

self = <test.test_app.TestApp testMethod=test_second>

def test_second(self):
"""
This test runs fine in isolation, but fails if run consecutively
after the first test
"""
self._add_to_db(test_model)
result = db.session.query(TestModel).first()
> self.assertIsNotNone(result, 'Nothing in the database')
E AssertionError: unexpectedly None : Nothing in the database

数据库设置和拆卸过程中出现问题,但我不知道是什么问题。我该如何正确设置?

最佳答案

答案是,通过重用在模块范围内定义的单个 TestModel 实例 (test_model = TestModel()),您会在一个测试和下一个测试之间泄漏状态.

第一次测试开始时该实例的状态是 transient :

an instance that’s not in a session, and is not saved to the database; i.e. it has no database identity. The only relationship such an object has to the ORM is that its class has a mapper() associated with it.

第二次测试开始时对象的状态是分离:

Detached - an instance which corresponds, or previously corresponded, to a record in the database, but is not currently in any session. The detached object will contain a database identity marker, however because it is not associated with a session, it is unknown whether or not this database identity actually exists in a target database. Detached objects are safe to use normally, except that they have no ability to load unloaded attributes or attributes that were previously marked as “expired”.

测试之间的这种相互依赖几乎总是一个坏主意。您可以使用 make_transient()在每次测试结束时的对象上:

class BaseTestCase(TestCase):
...
def tearDown(self):
db.session.remove()
db.drop_all()
make_transient(test_model)

或者您应该为每个测试构建一个新的 TestModel 实例:

class BaseTestCase(TestCase):
...
def setUp(self):
db.create_all()
self.test_model = TestModel()


class TestApp(BaseTestCase):
...
def test_xxxxx(self):
self._add_to_db(self.test_model)

我认为后者是更好的选择,因为在测试之间不存在任何其他泄漏状态的危险。

关于python - 如何正确运行查询 Flask-SQLAlchemy 数据库的连续测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56001939/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com