使用 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 测试中创建数据库的主要内容,如果未能解决你的问题,请参考以下文章

登录之后更新导航

无法从 sqlalchemy 插入到 mysql

基于flask的网页聊天室

使用 sqlalchemy 将 csv 文件加载到数据库中

prometheus使用postgresql-adapter连接postgresql

Flask 进阶系列:SQLAlchemy 扩展学习