Flask sqlalchemy 烧瓶+;SQLAlchemy+;pytest-不回滚我的会话
关于堆栈溢出有几个类似的问题,如果我问另一个问题违反了礼仪,我会提前道歉,但我似乎无法想出一套合适的咒语来实现这一点 我尝试使用Flask+Flask SQLAlchemy,然后使用pytest来管理会话,这样当函数范围的pytest夹具被拆除时,当前的事务被回滚 其他一些问题似乎主张在函数范围内使用db“drop all and create all”pytest fixture,但我尝试使用联接会话,并使用回滚,因为我有很多测试。这将大大加快速度 这是我发现原始想法的地方,也是建议使用函数级db重新创建的问题之一 我也看到了,但这似乎是由Alchemy 2.1(我正在使用)发布的 我目前(非常小,希望可以立即理解)的回购协议如下: 有两个print语句-第一个(在example/_init__.py中)应该有一个Account对象,第二个(在test/conftest.py中)是在回滚事务后清除db的地方 如果您Flask sqlalchemy 烧瓶+;SQLAlchemy+;pytest-不回滚我的会话,flask-sqlalchemy,pytest,Flask Sqlalchemy,Pytest,关于堆栈溢出有几个类似的问题,如果我问另一个问题违反了礼仪,我会提前道歉,但我似乎无法想出一套合适的咒语来实现这一点 我尝试使用Flask+Flask SQLAlchemy,然后使用pytest来管理会话,这样当函数范围的pytest夹具被拆除时,当前的事务被回滚 其他一些问题似乎主张在函数范围内使用db“drop all and create all”pytest fixture,但我尝试使用联接会话,并使用回滚,因为我有很多测试。这将大大加快速度 这是我发现原始想法的地方,也是建议使用函数级
pip install-r requirements.txt
并从测试目录运行py.test-s
,您应该会看到两条打印语句
我在这里快要走到尽头了——一定有什么东西我错过了,但就我的一生而言,我就是找不到
帮帮我,所以,你是我唯一的希望 我的回滚也有问题,可以找到我的代码 在阅读了一些文档之后,似乎应该在会话中调用
begin()
函数
因此,在您的情况下,我会将会话夹具更新为:
@pytest.yield_fixture(scope='function', autouse=True)
def session(db, request):
"""Creates a new database session for a test."""
db.session.begin()
yield db.session
db.session.rollback()
db.session.remove()
我没有测试这段代码,但在我的代码上尝试时,出现以下错误:
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR> File "./venv/lib/python2.7/site-packages/_pytest/main.py", line 90, in wrap_session
INTERNALERROR> session.exitstatus = doit(config, session) or 0
...
INTERNALERROR> File "./venv/lib/python2.7/site-packages/_pytest/python.py", line 59, in filter_traceback
INTERNALERROR> return entry.path != cutdir1 and not entry.path.relto(cutdir2)
INTERNALERROR> AttributeError: 'str' object has no attribute 'relto'
你可能想试一试。它是一个插件,它公开了一个db\u会话
fixture,它完成了您所寻找的内容:允许您运行数据库更新,当测试退出时将回滚。该插件基于Alex Michael的博客文章,对嵌套事务提供了一些额外的支持,涵盖了更广泛的用户案例。还有一些用于模拟应用程序中的连接文件的配置选项,这样您也可以从代码库中运行任意方法
对于test\u accounts.py
,您可以执行以下操作:
from example import db, Account
class TestAccounts(object):
def test_update_view(self, db_session):
test_acct = Account(username='abc')
db_session.add(test_acct)
db_session.commit()
resp = self.client.post('/update',
data={'a':1},
content_type='application/json')
assert resp.status_code == 200
插件需要通过\u db
装置访问您的数据库,但由于您已经在conftest.py
中定义了db
装置,因此您可以轻松设置数据库访问:
@pytest.fixture(scope='session')
def _db(db):
return db
您可以在中找到有关如何设置和安装的详细信息。希望这有帮助
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from unittest import TestCase
# global application scope. create Session class, engine
Session = sessionmaker()
engine = create_engine('postgresql://...')
class SomeTest(TestCase):
def setUp(self):
# connect to the database
self.connection = engine.connect()
# begin a non-ORM transaction
self.trans = self.connection.begin()
# bind an individual Session to the connection
self.session = Session(bind=self.connection)
def test_something(self):
# use the session in tests.
self.session.add(Foo())
self.session.commit()
def tearDown(self):
self.session.close()
# rollback - everything that happened with the
# Session above (including calls to commit())
# is rolled back.
self.trans.rollback()
# return connection to the Engine
self.connection.close()
当我用上述代码替换会话装置时,它甚至不允许我启动事务:
InvalidRequestError:事务已经开始。使用subtransactions=True来允许子事务。
我认为\u db.engine.connect()
应该以某种方式将会话“连接”在一起-请看,在这两个github对话的帮助下,我能够在我的示例上实现回滚:对,但这些问题/公关似乎表明249被合并到了Alchemy 2.1中,这就是为什么我认为它会“开箱即用”的原因。我想我会尝试这些补丁,如果它有效,我会回复。