Python RecursionError:测试中超过了最大递归深度
我正在使用Pytest测试一个Flask+SQLAlchemy应用程序。这是Python RecursionError:测试中超过了最大递归深度,python,flask,sqlalchemy,flask-sqlalchemy,pytest,Python,Flask,Sqlalchemy,Flask Sqlalchemy,Pytest,我正在使用Pytest测试一个Flask+SQLAlchemy应用程序。这是tests/contftest.py 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, BaseQuer
tests/contftest.py
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)
我认为您不应该在teardown函数中调用
ctx.pop()
,因为调用pop()
调用已注册的teardown回调(因此无限重复调用Flask.do_teardown\u appcontext()
,其中包含以下内容:
for func in reversed(self.teardown_appcontext_funcs):
func(exc)
销毁设备时,应该调用
ctx.pop()
。我不认为应该在teardown函数中调用ctx.pop()
,因为调用pop()
调用已注册的teardown回调(因此无限重复调用Flask.do\teardown\appcontext()
其中包含以下内容:
for func in reversed(self.teardown_appcontext_funcs):
func(exc)
销毁设备时,应调用
ctx.pop()
。扩展Roman Kutlak的答案,下面是我将如何重写您的应用程序
设备:
@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
关键字,除非您希望从内部范围内为全局变量赋值。扩展Roman Kutlak的答案,下面是我将如何重写您的应用程序
夹具:
@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
关键字,除非您希望从内部范围内为全局变量赋值