SQLAlchemy创建MySQL引擎,使用PostgreSQL在SQLAlchemy测试中创建数据库

I am building a Pyramid web application which is built on the top of SQLAlchemy and solely relies PostgreSQL as its database backend.

What would be a way to have the unit tests structure so that

Database is built once per test run - not on every test setUp() as this is too slow for a complex application

Database tables are (re)created as they would be created in production (e.g. run migrations from Alembic). Any unclean databases are destroyed at the start of the test run.

It is possible to choose a custom test runner á la py.test if a specific features outside the standard library unittest framework makes it easier to write test cases.

解决方案

Nose test runner supports setup_package() and teardown_package() methods. Here's an excerpt from the docs:

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.

In my application I have setup_package() which looks roughly like the following:

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

In addition, all test case classes are subclassed from a base class, which, importantly, defines a common tearDown method:

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 often override base setUp, but there usually no need to override tearDown - by rolling back the transaction it ensures that the next test will start on a completely clean database.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值