pytest`AssertionError:视图函数映射正在覆盖现有的终结点函数:`在记录字符串蓝图时发生烧瓶不稳定

问题描述 投票:0回答:1

问题如下,我创建了一个虚拟示例。文件夹结构在哪里:

.
├── api_bp
│   └── __init__.py
├── app.py
├── pytest.ini
└── tests
    ├── conftest.py
    ├── __init__.py
    ├── test_todo1.py
    └── test_todo2.py

api_bp__init__.py文件夹中的代码:

# __init__.py

from flask import Blueprint

api_bp = Blueprint('api', __name__)

Flask应用程序:

# app.py

from flask import Flask, Blueprint
from flask_restful import Api, Resource


class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}


def create_app():
    """Initialize the app. """
    app = Flask(__name__)
    from api_bp import api_bp
    # api_bp = Blueprint('api', __name__)
    api = Api(api_bp)

    api.add_resource(TodoItem, '/todos/<int:id>')
    app.register_blueprint(api_bp, url_prefix='/api')

    return app


if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)

出于测试目的,我有客户端夹具和两个测试(有意放入不同的模块中):

# conftest.py

import pytest

from app_factory import create_app

@pytest.fixture(scope='module')
def client():
    flask_app = create_app()

    testing_client = flask_app.test_client()

    context = flask_app.app_context()
    context.push()

    yield testing_client

    context.pop()
# test_todo1.py

import pytest

def test_todo2(client):
    """Test"""
    response = client.get('/api/todos/1')
    print(response)
    assert response.status_code == 200
# test_todo2.py

import pytest

def test_todo2(client):
    """Test"""
    response = client.get('/api/todos/2')
    print(response)
    assert response.status_code == 200

因此,当我运行$ pytest -v进行测试时,出现以下错误:

AssertionError: View function mapping is overwriting an existing endpoint function: api.todoitem

发生这种情况是因为重新设计了蓝图。我想了解结合pytest在烧瓶(烧瓶安逸)的引擎盖下发生的魔术。因为如果我要像这样定义我的app.py模块,它将成功通过测试:

# app.py

from flask import Flask, Blueprint
from flask_restful import Api, Resource


class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}


def create_app():
    """Initialize the app. """
    app = Flask(__name__)
    # note: I commented the line below and defined the blueprint in-place
    # from api_bp import api_bp  
    api_bp = Blueprint('api', __name__)
    api = Api(api_bp)

    api.add_resource(TodoItem, '/todos/<int:id>')
    app.register_blueprint(api_bp, url_prefix='/api')

    return app


if __name__ == '__main__':
    app = create_app()
    app.run(debug=True)
$ pytest -v
tests/test_api1.py::test_todo2 PASSED    [ 50%]
tests/test_api2.py::test_todo2 PASSED    [100%]

或者如果我不使用应用程序工厂,它也可以正常工作:

# app.py

from flask import Flask, Blueprint
from flask_restful import Api, Resource

app = Flask(__name__)
api_bp = Blueprint('api', __name__)
api = Api(api_bp)


class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}


api.add_resource(TodoItem, '/todos/<int:id>')
app.register_blueprint(api_bp, url_prefix='/api')

如果我将所有测试放在一个模块中,或者如果我先注册了蓝图,然后添加了如下资源,也可以解决:

# app.py

...

def create_app():
    """Initialize the app. """
    app = Flask(__name__)

    from api_bp import api_bp

    api = Api(api_bp)

    app.register_blueprint(api_bp, url_prefix='/api')
    api.add_resource(TodoItem, '/todos/<int:id>')


    return app

...

谁知道这里发生了什么并且可以解释magic?预先感谢。

python flask pytest flask-restful
1个回答
0
投票
所以问题的解释是,当pytest设置并在测试中使用客户端时,它将运行create_app()并在未在app.py中定义蓝图时尝试重用蓝图:

tests/test_api1.py::test_todo2 <flask.blueprints.Blueprint object at 0x7f04a8c9c610> SETUP M client tests/test_api1.py::test_todo2 (fixtures used: client)<Response streamed [200 OK]> PASSED TEARDOWN M client tests/test_api2.py::test_todo2 <flask.blueprints.Blueprint object at 0x7f04a8c9c610> SETUP M clientERROR TEARDOWN M client

可以通过以下方法解决:

# api_bp/__init__.py from flask import Blueprint get_blueprint = lambda: Blueprint('api', __name__)

并使用:

def create_app(): """Initialize the app. """ app = Flask(__name__) from api_bp import get_blueprint api_bp = get_blueprint() api = Api(api_bp) api.add_resource(TodoItem, '/todos/<int:id>') app.register_blueprint(api_bp, url_prefix='/api') return app

但是尚不清楚是否还有其他解决方案,如何对其进行适当的测试?
© www.soinside.com 2019 - 2024. All rights reserved.