使用PostgreSQL在SQLAlchemy测试中创建数据库

Mik*_*maa 7 python postgresql sqlalchemy pytest pyramid

我正在构建一个Pyramid Web应用程序,该应用程序建立在SQLAlchemy的顶部,并且仅依赖PostgreSQL作为其数据库后端。

什么是具有单元测试结构的方法,以便

  • 数据库每次测试运行一次,而不是每次测试一次,setUp()因为这对于复杂的应用程序来说太慢了

  • 数据库表的创建(重新)过程与在生产环境中创建数据库表的过程一样(例如,从Alembic运行迁移)。在测试运行开始时,所有不干净的数据库都会被销毁。

  • py.test如果标准库unittest框架之外的特定功能使编写测试用例更加容易,则可以选择自定义测试运行器ala。

Ser*_*gey 6

鼻子测试跑步者的支持setup_package()teardown_package()方法。以下是文档摘录:

测试包

鼻子可以将测试分组到测试包中。这允许包级别的设置;例如,如果您需要为测试创建测试数据库或其他数据夹具,则可以在程序包设置中创建它,并在每次测试运行中将其在程序包拆卸中删除,而不必为每个测试模块创建和拆卸一次或测试用例。

创建包级建立和拆除方法,在定义的设置和/或拆除的功能初始化的测试包的的.py。设置方法可以命名为setup,setup_package,setUp或setUpPackage。拆解可以被命名为teardown,teardown_package,tearDown或tearDownPackage。从测试包中加载第一个测试模块后,即开始执行测试包中的测试。

在我的应用程序中,我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
Run Code Online (Sandbox Code Playgroud)

此外,所有测试用例类都是从基类中继承的,基类很重要地定义了一个通用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()
Run Code Online (Sandbox Code Playgroud)

子类通常会覆盖base setUp,但是通常无需覆盖tearDown-通过回滚事务,它可以确保下一个测试将在完全干净的数据库上启动。

  • 可能是个愚蠢的问题,但是 BaseTest 拆解如何知道“会话”是什么? (2认同)