2017-10-19 97 views
0

我正在使用Pytest來測試Flask + SQLAlchemy應用程序。這是tests/contftest.pyRecursionError: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) 

回答

1

擴大羅馬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關鍵字這是沒有必要的。

3

我不認爲你應該叫ctx.pop()在拆卸功能調用pop()內容調用已註冊的拆解回調(因此無限重複AppContext調用Flask.do_teardown_appcontext()其中包含以下內容:

for func in reversed(self.teardown_appcontext_funcs): 
    func(exc) 

當您銷燬夾具時,應該致電ctx.pop()

相關問題