Python 带数据库回滚的路由功能测试

Python 带数据库回滚的路由功能测试,python,flask,neo4j,pytest,Python,Flask,Neo4j,Pytest,我试图使用pytest为Flask应用程序编写功能测试,该应用程序通过 下面介绍了使用从数据库中删除记录的路由的玩具示例。出于测试目的,我希望将会话包装在一个事务中,该事务将回滚而不是提交 该应用程序具有通过,session.run(…)在自动提交事务中运行Cypher语句的路由,但是我可以在测试期间通过在请求之前强制使用事务来绕过此逻辑 session.begin\u事务() ... 会话.回滚\u事务() 我的问题是,我不确定如何使用pytest利用此模式。我是否必须以某种方式将数据库绑定

我试图使用
pytest
为Flask应用程序编写功能测试,该应用程序通过

下面介绍了使用从数据库中删除记录的路由的玩具示例。出于测试目的,我希望将会话包装在一个事务中,该事务将回滚而不是提交

该应用程序具有通过,
session.run(…)
在自动提交事务中运行Cypher语句的路由,但是我可以在测试期间通过在请求之前强制使用事务来绕过此逻辑

session.begin\u事务()
...
会话.回滚\u事务()
我的问题是,我不确定如何使用
pytest
利用此模式。我是否必须以某种方式将数据库绑定到客户端?还有一个我可以使用的夹具,它可以确保利用客户机的每个测试都包装在一个可以回滚的事务中吗

myapp/app.py:

测试/测试路径.py:


是的,您可以使用一个fixture来实现这一点:在conftest.py中添加一个具有会话范围的autouse fixture,它将在测试会话开始时启动事务,并在结束时回滚

tests/conftest.py:

从neomodel导入数据库
@fixture(autouse=True,scope=“session”)
def设置测试数据库():
打印(“初始化数据库事务”)
db.begin()
产量
打印(“回滚”)
db.rollback()
from flask import _app_ctx_stack, Flask, Response
from flask_restplus import Api, Resource
from neo4j.v1 import GraphDatabase


class FlaskGraphDatabase(object):
    def __init__(self, app=None):
        self.app = app

        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        @app.teardown_appcontext
        def teardown(exception):
            ctx = _app_ctx_stack.top

            if hasattr(ctx, 'neo4j_session'):
                ctx.neo4j_session.close()

            if hasattr(ctx, 'neo4j_driver'):
                ctx.neo4j_driver.close()

    @property
    def driver(self):
        ctx = _app_ctx_stack.top

        if ctx is not None:
            if not hasattr(ctx, 'neo4j_driver'):
                ctx.neo4j_driver = GraphDatabase.driver('bolt://localhost:7687')

            return ctx.neo4j_driver

    @property
    def session(self):
        ctx = _app_ctx_stack.top

        if ctx is not None:
            if not hasattr(ctx, 'neo4j_session'):
                ctx.neo4j_session = self.driver.session()

            return ctx.neo4j_session


api = Api()
gdb = FlaskGraphDatabase()


@api.route('/<source>/acted_in/<target>')
class Friend(Resource):
    def delete(self, source, target):
        statement = """
            MATCH (s:Person)-[r:ACTED_IN]->(t:Movie)
            WHERE s.name = {source} AND t.title = {target}
            DELETE r
        """

        cursor = gdb.session.run(statement, source=source, target=target)
        status = 204 if cursor.summary().counters.contains_updates else 404
        return Response(status=status)


def create_app():
    app = Flask(__name__)
    gdb.init_app(app)
    api.init_app(app)
    return app


if __name__ == '__main__':
    app = create_app()
    app.run()
import pytest

from myapp.app import create_app


@pytest.yield_fixture(scope='session')
def app():
    yield create_app()

@pytest.yield_fixture(scope='session')
def client(app):
    with app.test_client() as client:
        yield client
def test_delete(client):
    res = client.delete('/Keanu Reeves/acted_in/The Matrix')
    assert res.status_code == 204