Run tests on PostgreSQL and MySQL too

In addition to running tests with different Python and SQLAlchemy
versions, they should also be run on different DB backends, which
are used in production (PostgreSQL and MySQL).

This patch:
  - modifies test_db.cfg to run tests on PostgreSQL and MySQL
    (Jenkins Slave credentials are used here, to ensure these
    tests are always run by Jenkins gate); if a backend is not
    available, test cases will be skipped for it
  - concurrency is set to 1 (sharing of the one MySQL or PostgreSQL
    DB among different test runner processes would lead to
    race conditions)
  - fixes tests dropping FK columns in MySQL: in earlier MySQL
    versions dropping a column that is a part of a FK constraint
    would lead to dropping of the FK too. As of MySQL 5.5 that's
    not the case anymore: if one tries to drop such column, he/she
    will get a very obscure error (something like "Error on rename
    of './openstack_citest/#sql-4af_aa2' to './openstack_citest/tmp_adddropcol'
    (errno: 150)") '\nALTER TABLE tmp_adddropcol DROP COLUMN r2').
    So the solution if to drop FK constraints first, and only then
    the columns it is made up of

Change-Id: I8c5d2874c83e7df46da69969ed54d85437c849e7
This commit is contained in:
Roman Podolyaka 2013-08-06 17:20:38 +03:00 committed by Gerrit Code Review
parent 838c1cbb14
commit a91766a1ac
4 changed files with 31 additions and 13 deletions

View File

@ -7,6 +7,7 @@ from sqlalchemy import *
from migrate import changeset, exceptions
from migrate.changeset import *
from migrate.changeset import constraint
from migrate.changeset.schema import ColumnDelta
from migrate.tests import fixture
from migrate.tests.fixture.warnings import catch_warnings
@ -168,7 +169,7 @@ class TestAddDropColumn(fixture.DB):
reftable.create()
# create column with fk
col = Column('data', Integer, ForeignKey(reftable.c.id))
col = Column('data', Integer, ForeignKey(reftable.c.id, name='testfk'))
col.create(self.table)
# check if constraint is added
@ -186,6 +187,11 @@ class TestAddDropColumn(fixture.DB):
else:
self.assertEqual(reftable.c.id.name,
col.foreign_keys[0].column.name)
if self.engine.name == 'mysql':
constraint.ForeignKeyConstraint([self.table.c.data],
[reftable.c.id],
name='testfk').drop()
col.drop(self.table)
if self.engine.has_table(reftable.name):
@ -384,8 +390,8 @@ class TestAddDropColumn(fixture.DB):
self.table = Table(
self.table_name, self.meta,
Column('id', Integer, primary_key=True),
Column('r1', Integer, ForeignKey('tmp_ref.id')),
Column('r2', Integer, ForeignKey('tmp_ref.id')),
Column('r1', Integer, ForeignKey('tmp_ref.id', name='test_fk1')),
Column('r2', Integer, ForeignKey('tmp_ref.id', name='test_fk2')),
)
self.table.create()
@ -394,6 +400,9 @@ class TestAddDropColumn(fixture.DB):
self._actual_foreign_keys())
# delete one
if self.engine.name == 'mysql':
constraint.ForeignKeyConstraint([self.table.c.r2], [reftable.c.id],
name='test_fk2').drop()
self.table.c.r2.drop()
# check remaining foreign key is there
@ -435,6 +444,10 @@ class TestAddDropColumn(fixture.DB):
self._actual_foreign_keys())
# delete one
if self.engine.name == 'mysql':
constraint.ForeignKeyConstraint([self.table.c.r1, self.table.c.r2],
[reftable.c.id, reftable.c.jd],
name='test_fk').drop()
self.table.c.r2.drop()
# check the constraint is gone, since part of it

View File

@ -6,6 +6,7 @@ import logging
from decorator import decorator
from sqlalchemy import create_engine, Table, MetaData
from sqlalchemy import exc as sa_exc
from sqlalchemy.orm import create_session
from sqlalchemy.pool import StaticPool
@ -81,13 +82,17 @@ def usedb(supported=None, not_supported=None):
try:
log.debug("Running test with engine %s", url)
try:
try:
self._setup(url)
except Exception,e:
setup_exception=e
else:
setup_exception=None
f(self, *a, **kw)
self._setup(url)
except sa_exc.OperationalError:
log.info('Backend %s is not available, skip it', url)
continue
except Exception as e:
setup_exception = e
else:
setup_exception = None
try:
f(self, *a, **kw)
finally:
try:
self._teardown()

View File

@ -8,7 +8,7 @@
# The string '__tmp__' is substituted for a temporary file in each connection
# string. This is useful for sqlite tests.
sqlite:///__tmp__
#postgresql://postgres@localhost/testdb
#mysql://root@localhost/testdb
postgresql://openstack_citest:openstack_citest@localhost/openstack_citest
mysql://openstack_citest:openstack_citest@localhost/openstack_citest
#oracle://scott:tiger@localhost
#firebird://scott:tiger@localhost//var/lib/firebird/databases/test_migrate

View File

@ -10,7 +10,7 @@ setenv = VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
python setup.py testr --slowest --testr-args='{posargs}'
python setup.py testr --slowest --testr-args='{posargs} --concurrency=1'
[testenv:py26sa07]
basepython = python2.6