使用 PostgreSQL 在 SQLAlchemy 测试中创建数据库
Posted
技术标签:
【中文标题】使用 PostgreSQL 在 SQLAlchemy 测试中创建数据库【英文标题】:Creating databases in SQLAlchemy tests with PostgreSQL 【发布时间】:2015-06-13 00:09:07 【问题描述】:我正在构建一个 Pyramid Web 应用程序,它构建在 SQLAlchemy 之上,并且仅依赖 PostgreSQL 作为其数据库后端。
有什么方法可以让单元测试结构如此
每次测试运行都会构建一次数据库 - 不是每次测试都构建一次 setUp()
,因为这对于复杂的应用程序来说太慢了
(重新)创建数据库表,就像在生产中创建它们一样(例如,从 Alembic 运行迁移)。任何不干净的数据库都会在测试运行开始时销毁。
如果标准库 unittest 框架之外的特定功能可以更轻松地编写测试用例,则可以选择自定义测试运行程序 á la py.test
。
【问题讨论】:
相关:***.com/questions/29507883/… 相关:gist.github.com/inklesspen/4504383 【参考方案1】:Nose 测试运行器支持setup_package()
和teardown_package()
方法。以下是文档的摘录:
Test Packages
nose 允许将测试分组到测试包中。这允许 包级设置;例如,如果您需要创建一个测试 用于测试的数据库或其他数据夹具,您可以在 包设置并在每次测试运行时在包拆解中将其删除, 而不必为每个测试模块创建和拆除一次,或者 测试用例。
要创建包级设置和拆卸方法,请定义 setup 和/或测试包的 init.py 中的拆卸功能。设置 方法可以命名为 setup、setup_package、setUp 或 setUpPackage; teardown 可以命名为 teardown、teardown_package、tearDown 或 拆解包。测试包中测试的执行尽快开始 因为第一个测试模块是从测试包中加载的。
在我的应用程序中,setup_package()
大致如下所示:
def _create_database():
template_engine = sa.create_engine("postgres://postgres@/postgres", echo=False)
conn = template_engine.connect()
conn = conn.execution_options(autocommit=False)
conn.execute("ROLLBACK")
try:
conn.execute("DROP DATABASE %s" % DB_NAME)
except sa.exc.ProgrammingError as e:
# Could not drop the database, probably does not exist
conn.execute("ROLLBACK")
except sa.exc.OperationalError as e:
# Could not drop database because it's being accessed by other users (psql prompt open?)
conn.execute("ROLLBACK")
conn.execute("CREATE DATABASE %s" % DB_NAME)
conn.close()
template_engine.dispose()
def setup_package():
_create_database()
engine = sa.create_engine("postgres://postgres@/%s" % DB_NAME, echo=False)
session = sa.orm.scoped_session(sa.orm.sessionmaker())
session.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all()
def teardown_package():
# no need to do anything as the old database is dropped at the start of every run
此外,所有测试用例类都是从一个基类继承而来的,重要的是,它定义了一个通用的tearDown
方法:
class BaseTest(unittest.TestCase):
def setUp(self):
# This makes things nicer if the previous test fails
# - without this all subsequent tests fail
self.tearDown()
self.config = testing.setUp()
def tearDown(self):
testing.tearDown()
session.expunge_all()
session.rollback()
子类通常会覆盖基类setUp
,但通常不需要覆盖tearDown
- 通过回滚事务可以确保下一个测试将在完全干净的数据库上开始。
【讨论】:
可能是个愚蠢的问题,但是 BaseTest 拆解如何知道session
是什么?以上是关于使用 PostgreSQL 在 SQLAlchemy 测试中创建数据库的主要内容,如果未能解决你的问题,请参考以下文章