使用 PostgreSQL 在 SQLAlchemy 测试中创建数据库
Creating databases in SQLAlchemy tests with PostgreSQL
我正在构建一个基于 SQLAlchemy 的 Pyramid Web 应用程序,它完全依赖 PostgreSQL 作为其数据库后端。
有什么方法可以使单元测试结构
每个测试构建一次数据库 运行 - 不是每个测试都构建一次 setUp()
因为这对于复杂的应用程序来说太慢了
(重新)创建数据库表,因为它们将在生产中创建(例如 运行 从 Alembic 迁移)。任何不干净的数据库都会在测试开始时销毁 运行.
如果标准库 unittest 框架之外的特定功能使编写测试用例更容易,则可以选择自定义测试 运行和 py.test
。
Nose 测试运行器支持 setup_package()
和 teardown_package()
方法。这是文档的摘录:
nose allows tests to be grouped into test packages. This allows
package-level setup; for instance, if you need to create a test
database or other data fixture for your tests, you may create it in
package setup and remove it in package teardown once per test run,
rather than having to create and tear it down once per test module or
test case.
To create package-level setup and teardown methods, define setup
and/or teardown functions in the init.py of a test package. Setup
methods may be named setup, setup_package, setUp, or setUpPackage;
teardown may be named teardown, teardown_package, tearDown or
tearDownPackage. Execution of tests in a test package begins as soon
as the first test module is loaded from the test package.
在我的应用程序中,我有 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
此外,所有测试用例 class 都是从基础 class 继承而来的 class,重要的是,它定义了一个通用的 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()
Subclasses 通常会覆盖基础 setUp
,但通常不需要覆盖 tearDown
- 通过回滚事务,它确保下一个测试将在完全开始清理数据库。
我正在构建一个基于 SQLAlchemy 的 Pyramid Web 应用程序,它完全依赖 PostgreSQL 作为其数据库后端。
有什么方法可以使单元测试结构
每个测试构建一次数据库 运行 - 不是每个测试都构建一次
setUp()
因为这对于复杂的应用程序来说太慢了(重新)创建数据库表,因为它们将在生产中创建(例如 运行 从 Alembic 迁移)。任何不干净的数据库都会在测试开始时销毁 运行.
如果标准库 unittest 框架之外的特定功能使编写测试用例更容易,则可以选择自定义测试 运行和
py.test
。
Nose 测试运行器支持 setup_package()
和 teardown_package()
方法。这是文档的摘录:
nose allows tests to be grouped into test packages. This allows package-level setup; for instance, if you need to create a test database or other data fixture for your tests, you may create it in package setup and remove it in package teardown once per test run, rather than having to create and tear it down once per test module or test case.
To create package-level setup and teardown methods, define setup and/or teardown functions in the init.py of a test package. Setup methods may be named setup, setup_package, setUp, or setUpPackage; teardown may be named teardown, teardown_package, tearDown or tearDownPackage. Execution of tests in a test package begins as soon as the first test module is loaded from the test package.
在我的应用程序中,我有 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
此外,所有测试用例 class 都是从基础 class 继承而来的 class,重要的是,它定义了一个通用的 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()
Subclasses 通常会覆盖基础 setUp
,但通常不需要覆盖 tearDown
- 通过回滚事务,它确保下一个测试将在完全开始清理数据库。