我尝试使用pytest
为Flask应用程序编写功能测试,该应用程序通过Neo4j driver与Neo4j图形数据库连接。
下面概述了使用Movie Database的玩具示例,其中使用了从数据库中删除记录的路径。出于测试目的,我想将会话包装在一个事务中,该事务将被回滚而不是提交。
应用程序具有通过session.run(...)
在自动提交事务中运行Cypher语句的路由,但是我可以在测试期间通过在请求之前强制使用事务来规避此逻辑,
session.begin_transaction()
...
session.rollback_transaction()
我的问题是我不确定如何使用pytest
来利用此模式。我是否必须以某种方式将数据库绑定到客户端?还有一个我可以使用的工具,它将确保利用客户端的每个测试都包含在可以回滚的事务中吗?
的myapp / app.py:
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()
测试/ conftest.py:
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
测试/ test_routes.py:
def test_delete(client):
res = client.delete('/Keanu Reeves/acted_in/The Matrix')
assert res.status_code == 204
答案 0 :(得分:0)
是的,您可以使用夹具来实现这一点:在您的 conftest.py 中添加一个具有会话范围的自动使用夹具,它将在测试会话开始时启动一个事务,并在结束时回滚它。
tests/conftest.py:
from neomodel import db
@pytest.fixture(autouse=True, scope="session")
def setup_neo_test_db():
print("Initializing db transaction")
db.begin()
yield
print("Rolling back")
db.rollback()