RecursionError:Flask Pytest中超出最大递归深度
问题描述:
我正在使用Pytest来测试Flask + SQLAlchemy应用程序。这是tests/contftest.py
RecursionError:Flask Pytest中超出最大递归深度
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from flask import _app_ctx_stack
from flask.ext.sqlalchemy import SQLAlchemy, BaseQuery
from package.myapp import create_app
from package.config import DefaultConfig
DbSession = scoped_session(
sessionmaker(),
scopefunc=_app_ctx_stack.__ident_func__
)
@pytest.fixture(scope='session')
def app(request):
_app = create_app()
_app.debug = False
_app.engine = create_engine(_app.config['SQLALCHEMY_DATABASE_URI'], connect_args={"options": "-c timezone=utc"})
global DbSession
DbSession.configure(bind=_app.engine, query_cls=BaseQuery)
# Establish an application context before running the tests.
ctx = _app.app_context()
ctx.push()
@_app.teardown_appcontext
def teardown(exception=None):
ctx.pop()
global DbSession
if DbSession:
DbSession.remove()
request.addfinalizer(teardown)
return _app
当我运行pytest
,我得到这个错误信息
___________________ ERROR at teardown of test_create_project ___________________
exception = None
@_app.teardown_appcontext
def teardown(exception=None):
> ctx.pop()
tests/conftest.py:31:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../.virtualenvs/quest-backend/lib/python3.6/site-packages/flask/ctx.py:189: in pop
self.app.do_teardown_appcontext(exc)
../../.virtualenvs/quest-backend/lib/python3.6/site-packages/flask/app.py:1892: in do_teardown_appcontext
func(exc)
tests/conftest.py:31: in teardown
ctx.pop()
E RecursionError: maximum recursion depth exceeded
!!! Recursion detected (same locals & position)
答
扩大罗马Kutlak的答案,这里是我怎么会重写你app
夹具:
@pytest.fixture(scope='session')
def app():
_app = create_app()
_app.debug = False
_app.engine = create_engine(_app.config['SQLALCHEMY_DATABASE_URI'], connect_args={"options": "-c timezone=utc"})
# session should probably not be global?..
DbSession = scoped_session(
sessionmaker(),
scopefunc=_app_ctx_stack.__ident_func__
)
DbSession.configure(bind=_app.engine, query_cls=BaseQuery)
# Establish an application context before running the tests.
ctx = _app.app_context()
ctx.push()
# this function is specifically for app's teardown, don't call it again for fixture teardown
@_app.teardown_appcontext
def teardown(exception=None):
if DbSession:
DbSession.remove()
# here is where tests will be executed
yield _app
# now tear-down our fixture (as apposed to flask app's teardown)
ctx.pop()
,除非你想从内部范围内的值分配给全局变量来使用global
关键字这是没有必要的。
答
我不认为你应该叫ctx.pop()
在拆卸功能调用pop()
内容调用已注册的拆解回调(因此无限重复AppContext调用Flask.do_teardown_appcontext()
其中包含以下内容:
for func in reversed(self.teardown_appcontext_funcs):
func(exc)
当您销毁夹具时,应该致电ctx.pop()
。