我正在构建一个构建在SQLAlchemy顶部的Pyramid Web应用程序,并且只依赖PostgreSQL作为其数据库后端。
有什么方法可以让单元测试结构
数据库在每次测试运行时构建一次 - 而不是在每个测试setUp()
上构建,因为这对于复杂的应用来说太慢了
创建数据库表(因为它们将在生产中创建)(例如,从Alembic运行迁移)。在测试运行开始时,任何不干净的数据库都会被销毁。
如果标准库unittest框架之外的特定功能可以更轻松地编写测试用例,则可以选择自定义测试运行程序la py.test
。
答案 0 :(得分:5)
Nose测试运行器支持setup_package()
和teardown_package()
方法。以下是文档的摘录:
nose允许将测试分组到测试包中。这允许 包级设置;例如,如果您需要创建测试 您可以在其中创建测试的数据库或其他数据夹具 软件包设置并在每次测试运行时将其删除一次 而不是每个测试模块或者必须创建和拆除它一次 测试用例。
要创建包级别设置和拆卸方法,请定义设置 和/或拆解测试包的 init .py中的函数。建立 方法可以命名为setup,setup_package,setUp或setUpPackage; 拆解可能被命名为拆解,拆卸,拆卸或拆卸 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
此外,所有测试用例类都是从基类创建的子类,重要的是,它定义了一个通用的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
- 通过回滚事务,它确保下一个测试将在完全干净的数据库上启动。