Merge "set up tests to run with sqlite"
This commit is contained in:
commit
90fde5756b
16
.zuul.yaml
Normal file
16
.zuul.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
- job:
|
||||
name: storyboard-tox-sqlite
|
||||
parent: openstack-tox
|
||||
description: |
|
||||
Run tests using sqlite instead of mysql.
|
||||
vars:
|
||||
tox_envlist: sqlite
|
||||
|
||||
- project:
|
||||
name: openstack-infra/storyboard
|
||||
check:
|
||||
jobs:
|
||||
- storyboard-tox-sqlite
|
||||
gate:
|
||||
jobs:
|
||||
- storyboard-tox-sqlite
|
@ -30,6 +30,11 @@ or for Python 3::
|
||||
|
||||
$ tox -e py35
|
||||
|
||||
For faster versions of the integration tests using only Python 3,
|
||||
run::
|
||||
|
||||
$ tox -e sqlite
|
||||
|
||||
And to run the style-checker and static analysis tool::
|
||||
|
||||
$ tox -e pep8
|
||||
|
@ -82,10 +82,13 @@ def upgrade(active_plugins=None, options=None):
|
||||
worklist.id, move_permission, session=session)
|
||||
session.flush()
|
||||
|
||||
op.drop_constraint(u'boards_ibfk_2', 'boards', type_='foreignkey')
|
||||
op.drop_column(u'boards', 'permission_id')
|
||||
op.drop_constraint(u'worklists_ibfk_2', 'worklists', type_='foreignkey')
|
||||
op.drop_column(u'worklists', 'permission_id')
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.drop_constraint(u'boards_ibfk_2', 'boards', type_='foreignkey')
|
||||
op.drop_column(u'boards', 'permission_id')
|
||||
op.drop_constraint(u'worklists_ibfk_2', 'worklists',
|
||||
type_='foreignkey')
|
||||
op.drop_column(u'worklists', 'permission_id')
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -82,8 +82,10 @@ def upgrade(active_plugins=None, options=None):
|
||||
'worklist_items',
|
||||
sa.Column('display_due_date', sa.Integer(), nullable=True)
|
||||
)
|
||||
op.create_foreign_key(
|
||||
None, 'worklist_items', 'due_dates', ['display_due_date'], ['id'])
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.create_foreign_key(
|
||||
None, 'worklist_items', 'due_dates', ['display_due_date'], ['id'])
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -31,8 +31,10 @@ import sqlalchemy as sa
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.add_column(
|
||||
'comments', sa.Column('in_reply_to', sa.Integer(), nullable=True))
|
||||
op.create_foreign_key(
|
||||
'comments_ibfk_1', 'comments', 'comments', ['in_reply_to'], ['id'])
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.create_foreign_key(
|
||||
'comments_ibfk_1', 'comments', 'comments', ['in_reply_to'], ['id'])
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -46,12 +46,16 @@ def upgrade(active_plugins=None, options=None):
|
||||
sa.ForeignKeyConstraint(['permission_id'], ['permissions.id'], ),
|
||||
sa.ForeignKeyConstraint(['story_id'], ['stories.id'], )
|
||||
)
|
||||
op.add_column(
|
||||
u'stories',
|
||||
sa.Column('private', sa.Boolean(), default=False, nullable=False))
|
||||
op.alter_column('worklist_items', 'list_id',
|
||||
existing_type=mysql.INTEGER(display_width=11),
|
||||
nullable=True)
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.name == 'sqlite':
|
||||
col = sa.Column('private', sa.Boolean(), default=False)
|
||||
else:
|
||||
col = sa.Column('private', sa.Boolean(), default=False, nullable=False)
|
||||
op.add_column(u'stories', col)
|
||||
if dialect.supports_alter:
|
||||
op.alter_column('worklist_items', 'list_id',
|
||||
existing_type=mysql.INTEGER(display_width=11),
|
||||
nullable=True)
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -33,10 +33,12 @@ new_type_enum = sa.Enum(
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.alter_column('subscriptions',
|
||||
'target_type',
|
||||
existing_type=old_type_enum,
|
||||
type_=new_type_enum)
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.alter_column('subscriptions',
|
||||
'target_type',
|
||||
existing_type=old_type_enum,
|
||||
type_=new_type_enum)
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -33,10 +33,13 @@ def upgrade(active_plugins=None, options=None):
|
||||
'events', sa.Column('board_id', sa.Integer(), nullable=True))
|
||||
op.add_column(
|
||||
'events', sa.Column('worklist_id', sa.Integer(), nullable=True))
|
||||
op.create_foreign_key(
|
||||
'fk_event_worklist', 'events', 'worklists', ['worklist_id'], ['id'])
|
||||
op.create_foreign_key(
|
||||
'fk_event_board', 'events', 'boards', ['board_id'], ['id'])
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.create_foreign_key(
|
||||
'fk_event_worklist', 'events', 'worklists',
|
||||
['worklist_id'], ['id'])
|
||||
op.create_foreign_key(
|
||||
'fk_event_board', 'events', 'boards', ['board_id'], ['id'])
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -29,9 +29,10 @@ import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
|
||||
op.alter_column('project_groups', 'name', type_=sa.Unicode(100))
|
||||
op.alter_column('projects', 'name', type_=sa.Unicode(100))
|
||||
dialect = op.get_bind().engine.dialect
|
||||
if dialect.supports_alter:
|
||||
op.alter_column('project_groups', 'name', type_=sa.Unicode(100))
|
||||
op.alter_column('projects', 'name', type_=sa.Unicode(100))
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
|
@ -16,6 +16,7 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import shutil
|
||||
import stat
|
||||
import uuid
|
||||
@ -142,34 +143,52 @@ class DbTestCase(WorkingDirTestCase):
|
||||
self.setup_db()
|
||||
|
||||
def setup_db(self):
|
||||
|
||||
self.db_name = "storyboard_test_db_%s" % uuid.uuid4()
|
||||
self.db_name = self.db_name.replace("-", "_")
|
||||
LOG.info('creating database %s', self.db_name)
|
||||
|
||||
# The engine w/o db name
|
||||
engine = sqlalchemy.create_engine(
|
||||
self.test_connection)
|
||||
engine.execute("CREATE DATABASE %s" % self.db_name)
|
||||
|
||||
alembic_config = get_alembic_config()
|
||||
alembic_config.storyboard_config = CONF
|
||||
CONF.set_override(
|
||||
"connection",
|
||||
self.test_connection + "/%s"
|
||||
% self.db_name,
|
||||
group="database")
|
||||
self._full_db_name = self.test_connection + '/' + self.db_name
|
||||
LOG.info('using database %s', CONF.database.connection)
|
||||
|
||||
if self.test_connection.startswith('sqlite://'):
|
||||
self.using_sqlite = True
|
||||
else:
|
||||
self.using_sqlite = False
|
||||
# The engine w/o db name
|
||||
engine = sqlalchemy.create_engine(
|
||||
self.test_connection)
|
||||
engine.execute("CREATE DATABASE %s" % self.db_name)
|
||||
|
||||
alembic_config = get_alembic_config()
|
||||
alembic_config.storyboard_config = CONF
|
||||
|
||||
command.upgrade(alembic_config, "head")
|
||||
self.addCleanup(self._drop_db)
|
||||
|
||||
def _drop_db(self):
|
||||
engine = sqlalchemy.create_engine(
|
||||
self.test_connection)
|
||||
try:
|
||||
engine.execute("DROP DATABASE %s" % self.db_name)
|
||||
except Exception as err:
|
||||
LOG.error('failed to drop database %s: %s',
|
||||
self.db_name, err)
|
||||
if self.test_connection.startswith('sqlite://'):
|
||||
filename = self._full_db_name[9:]
|
||||
if filename[:2] == '//':
|
||||
filename = filename[1:]
|
||||
if os.path.exists(filename):
|
||||
LOG.info('removing database file %s', filename)
|
||||
try:
|
||||
os.unlink(filename)
|
||||
except OSError as err:
|
||||
LOG.error('could not remove %s: %s',
|
||||
filename, err)
|
||||
else:
|
||||
engine = sqlalchemy.create_engine(
|
||||
self.test_connection)
|
||||
try:
|
||||
engine.execute("DROP DATABASE %s" % self.db_name)
|
||||
except Exception as err:
|
||||
LOG.error('failed to drop database %s: %s',
|
||||
self.db_name, err)
|
||||
db_api_base.cleanup()
|
||||
|
||||
PATH_PREFIX = '/v1'
|
||||
|
@ -49,8 +49,26 @@ class TestDBReferenceError(base.BaseDbTestCase):
|
||||
'story_id': 100
|
||||
}
|
||||
|
||||
self.assertRaises(exc.DBReferenceError,
|
||||
lambda: tasks.task_create(task))
|
||||
# TODO(dhellmann): The SQLite database doesn't use foreign key
|
||||
# constraints instead of getting an error from the database
|
||||
# when we try to insert the task we get the error later when
|
||||
# we try to update the story. The behavior difference doesn't
|
||||
# seem all that important since it only affects this test, but
|
||||
# at some point we should probably ensure that all database
|
||||
# reference errors are turned into the same exception class
|
||||
# for consistency. For now we just test slightly differently.
|
||||
if self.using_sqlite:
|
||||
self.assertRaises(
|
||||
exc.NotFound,
|
||||
tasks.task_create,
|
||||
task,
|
||||
)
|
||||
else:
|
||||
self.assertRaises(
|
||||
exc.DBReferenceError,
|
||||
tasks.task_create,
|
||||
task,
|
||||
)
|
||||
|
||||
|
||||
class TestDbInvalidSortKey(base.BaseDbTestCase):
|
||||
|
13
tox.ini
13
tox.ini
@ -1,5 +1,5 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
minversion = 2.9.1
|
||||
skipsdist = True
|
||||
envlist = py34,py27,pep8
|
||||
|
||||
@ -10,12 +10,21 @@ setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
OS_STDERR_CAPTURE=1
|
||||
OS_STDOUT_CAPTURE=1
|
||||
passenv = OS_TEST_TIMEOUT
|
||||
passenv =
|
||||
OS_TEST_TIMEOUT
|
||||
STORYBOARD_TEST_DB
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = ostestr '{posargs}'
|
||||
whitelist_externals = bash
|
||||
|
||||
[testenv:sqlite]
|
||||
basepython = python3
|
||||
setenv =
|
||||
STORYBOARD_TEST_DB=sqlite:///{envtmpdir}
|
||||
OS_STDERR_CAPTURE=1
|
||||
OS_STDOUT_CAPTURE=1
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user