关于堆栈溢出有几个类似的问题,如果我通过询问另一个礼节来打破礼仪,我会提前道歉,但我似乎无法想出适当的咒语来使这项工作。< / p>
我尝试使用Flask + Flask-SQLAlchemy然后使用pytest来管理会话,这样当功能范围的pytest fixture被拆除时,当前的转换将被回滚。
其他一些问题似乎主张使用db&#34; drop all并创建所有&#34;函数范围内的pytest fixture,但我尝试使用连接会话,并使用回滚,因为我有很多测试。这会大大加快速度。
http://alexmic.net/flask-sqlalchemy-pytest/是我找到原始想法的地方,Isolating py.test DB sessions in Flask-SQLAlchemy是推荐使用功能级数据库重新创建的问题之一。
我也看过https://github.com/mitsuhiko/flask-sqlalchemy/pull/249,但似乎已经发布了flask-sqlalchemy 2.1(我正在使用)。
我现在的(非常小的,希望可以立即理解的)回购在这里: https://github.com/hoopes/flask-pytest-example
有两个打印语句 - 第一个(在示例/ __ init__.py中)应该有一个Account对象,第二个(在test / conftest.py中)是我希望在事务发生后清除db的地方回滚。
如果您pip install -r requirements.txt
并从测试目录运行py.test -s
,您应该会看到两个打印语句。
我在这里的绳子尽头 - 我必须有一些我想念的东西,但对于我的生活,我似乎无法找到它。
帮助我,所以,你是我唯一的希望!
答案 0 :(得分:2)
您可能想尝试pytest-flask-sqlalchemy-transactions。它是一个插件,它公开了一个db_session
固定装置,可以实现您所需要的功能:允许您运行数据库更新,这些更新将在测试退出时回滚。该插件基于Alex Michael的博客文章,并为嵌套事务提供了一些其他支持,涵盖了更多的用户案例。还有一些配置选项可用于在应用程序中模拟可连接对象,因此您也可以从代码库中运行任意方法。
对于test_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
该插件需要通过_db
固定装置访问数据库,但是由于您已经在db
中定义了conftest.py
固定装置,因此可以轻松设置数据库访问权限:
@pytest.fixture(scope='session')
def _db(db):
return db
您可以在the docs中找到有关如何设置和安装的详细信息。希望这会有所帮助!
答案 1 :(得分:0)
我也遇到了回滚问题,我的代码可以找到here
阅读完一些文档后,似乎应该在会话中调用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'
答案 2 :(得分:0)
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()