【发布时间】:2018-04-10 12:27:35
【问题描述】:
在 pytest 中运行测试时,数据库被修改。撤消对数据库的更改的最佳方法是什么?
DBSession 回滚
对于那些我可以直接访问后端的测试,我目前使用 pytest 夹具为每个测试函数启动一个新的 DBSession,并在它结束时回滚会话
@pytest.fixture(scope='session')
def db(app, request):
"""Session-wide test database."""
def teardown():
pass
_db = SQLAlchemy(app)
return _db
@pytest.fixture(scope='function')
def db_session(db, request):
"""Creates a new database session for a test."""
engine = create_engine(
TestConfig.SQLALCHEMY_DATABASE_URI,
connect_args={"options": "-c timezone=utc"})
DbSession = sessionmaker(bind=engine)
session = DbSession()
connection = engine.connect()
transaction = connection.begin()
options = dict(bind=connection, binds={})
session = db.create_scoped_session(options=options)
db.session = session
yield session
transaction.rollback()
connection.close()
session.remove()
在测试代码中,我只是简单的使用了fixture
def test_create_project(db_session): 项目 = _create_test_project(db_session) 断言 project.project_id > 0
Flask / HTTP 测试
但是为了通过 Flask/HTTP 测试 API,我不能使用 db_session。即使我创建一个夹具来显式地DROP 测试数据库并从生产中恢复,它也不会工作,因为没有直接的数据库代码
@pytest.fixture(scope='function')
def db_session_refresh(db, request):
"""Refresh the test database from production after running the test"""
engine = create_engine(
TestConfig.SQLALCHEMY_DATABASE_URI,
connect_args={"options": "-c timezone=utc"})
DbSession = sessionmaker(bind=engine)
session = DbSession()
connection = engine.connect()
transaction = connection.begin()
options = dict(bind=connection, binds={})
session = db.create_scoped_session(options=options)
db.session = session
yield session
transaction.rollback()
connection.close()
session.remove()
refresh_test_db_sql = """
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'appdb_test';
DROP DATABASE appdb_test;
CREATE DATABASE appdb_test TEMPLATE appdb;
"""
engine.execute(refresh_test_db_sql)
即使这样可行,为每个函数刷新数据库也是低效的。
运行修改数据库的测试的正确/更好的方法是什么?
【问题讨论】:
-
当然,您应该使用单独的数据库进行测试,而不是回滚主数据库。您在
setUp方法中建立一个数据库并在tearDown中销毁。 -
我确实有
dbapp和dbapp_test。运行 Flask HTTP 测试代码时如何回滚对数据库的更改?
标签: python flask sqlalchemy flask-sqlalchemy pytest