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
|
$ 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::
|
And to run the style-checker and static analysis tool::
|
||||||
|
|
||||||
$ tox -e pep8
|
$ tox -e pep8
|
||||||
|
@ -82,9 +82,12 @@ def upgrade(active_plugins=None, options=None):
|
|||||||
worklist.id, move_permission, session=session)
|
worklist.id, move_permission, session=session)
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.drop_constraint(u'boards_ibfk_2', 'boards', type_='foreignkey')
|
op.drop_constraint(u'boards_ibfk_2', 'boards', type_='foreignkey')
|
||||||
op.drop_column(u'boards', 'permission_id')
|
op.drop_column(u'boards', 'permission_id')
|
||||||
op.drop_constraint(u'worklists_ibfk_2', 'worklists', type_='foreignkey')
|
op.drop_constraint(u'worklists_ibfk_2', 'worklists',
|
||||||
|
type_='foreignkey')
|
||||||
op.drop_column(u'worklists', 'permission_id')
|
op.drop_column(u'worklists', 'permission_id')
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@ def upgrade(active_plugins=None, options=None):
|
|||||||
'worklist_items',
|
'worklist_items',
|
||||||
sa.Column('display_due_date', sa.Integer(), nullable=True)
|
sa.Column('display_due_date', sa.Integer(), nullable=True)
|
||||||
)
|
)
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.create_foreign_key(
|
op.create_foreign_key(
|
||||||
None, 'worklist_items', 'due_dates', ['display_due_date'], ['id'])
|
None, 'worklist_items', 'due_dates', ['display_due_date'], ['id'])
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ import sqlalchemy as sa
|
|||||||
def upgrade(active_plugins=None, options=None):
|
def upgrade(active_plugins=None, options=None):
|
||||||
op.add_column(
|
op.add_column(
|
||||||
'comments', sa.Column('in_reply_to', sa.Integer(), nullable=True))
|
'comments', sa.Column('in_reply_to', sa.Integer(), nullable=True))
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.create_foreign_key(
|
op.create_foreign_key(
|
||||||
'comments_ibfk_1', 'comments', 'comments', ['in_reply_to'], ['id'])
|
'comments_ibfk_1', 'comments', 'comments', ['in_reply_to'], ['id'])
|
||||||
|
|
||||||
|
@ -46,9 +46,13 @@ def upgrade(active_plugins=None, options=None):
|
|||||||
sa.ForeignKeyConstraint(['permission_id'], ['permissions.id'], ),
|
sa.ForeignKeyConstraint(['permission_id'], ['permissions.id'], ),
|
||||||
sa.ForeignKeyConstraint(['story_id'], ['stories.id'], )
|
sa.ForeignKeyConstraint(['story_id'], ['stories.id'], )
|
||||||
)
|
)
|
||||||
op.add_column(
|
dialect = op.get_bind().engine.dialect
|
||||||
u'stories',
|
if dialect.name == 'sqlite':
|
||||||
sa.Column('private', sa.Boolean(), default=False, nullable=False))
|
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',
|
op.alter_column('worklist_items', 'list_id',
|
||||||
existing_type=mysql.INTEGER(display_width=11),
|
existing_type=mysql.INTEGER(display_width=11),
|
||||||
nullable=True)
|
nullable=True)
|
||||||
|
@ -33,6 +33,8 @@ new_type_enum = sa.Enum(
|
|||||||
|
|
||||||
|
|
||||||
def upgrade(active_plugins=None, options=None):
|
def upgrade(active_plugins=None, options=None):
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.alter_column('subscriptions',
|
op.alter_column('subscriptions',
|
||||||
'target_type',
|
'target_type',
|
||||||
existing_type=old_type_enum,
|
existing_type=old_type_enum,
|
||||||
|
@ -33,8 +33,11 @@ def upgrade(active_plugins=None, options=None):
|
|||||||
'events', sa.Column('board_id', sa.Integer(), nullable=True))
|
'events', sa.Column('board_id', sa.Integer(), nullable=True))
|
||||||
op.add_column(
|
op.add_column(
|
||||||
'events', sa.Column('worklist_id', sa.Integer(), nullable=True))
|
'events', sa.Column('worklist_id', sa.Integer(), nullable=True))
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.create_foreign_key(
|
op.create_foreign_key(
|
||||||
'fk_event_worklist', 'events', 'worklists', ['worklist_id'], ['id'])
|
'fk_event_worklist', 'events', 'worklists',
|
||||||
|
['worklist_id'], ['id'])
|
||||||
op.create_foreign_key(
|
op.create_foreign_key(
|
||||||
'fk_event_board', 'events', 'boards', ['board_id'], ['id'])
|
'fk_event_board', 'events', 'boards', ['board_id'], ['id'])
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ import sqlalchemy as sa
|
|||||||
|
|
||||||
|
|
||||||
def upgrade(active_plugins=None, options=None):
|
def upgrade(active_plugins=None, options=None):
|
||||||
|
dialect = op.get_bind().engine.dialect
|
||||||
|
if dialect.supports_alter:
|
||||||
op.alter_column('project_groups', 'name', type_=sa.Unicode(100))
|
op.alter_column('project_groups', 'name', type_=sa.Unicode(100))
|
||||||
op.alter_column('projects', 'name', type_=sa.Unicode(100))
|
op.alter_column('projects', 'name', type_=sa.Unicode(100))
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
import stat
|
import stat
|
||||||
import uuid
|
import uuid
|
||||||
@ -142,10 +143,21 @@ class DbTestCase(WorkingDirTestCase):
|
|||||||
self.setup_db()
|
self.setup_db()
|
||||||
|
|
||||||
def setup_db(self):
|
def setup_db(self):
|
||||||
|
|
||||||
self.db_name = "storyboard_test_db_%s" % uuid.uuid4()
|
self.db_name = "storyboard_test_db_%s" % uuid.uuid4()
|
||||||
self.db_name = self.db_name.replace("-", "_")
|
self.db_name = self.db_name.replace("-", "_")
|
||||||
LOG.info('creating database %s', self.db_name)
|
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
|
# The engine w/o db name
|
||||||
engine = sqlalchemy.create_engine(
|
engine = sqlalchemy.create_engine(
|
||||||
self.test_connection)
|
self.test_connection)
|
||||||
@ -153,16 +165,23 @@ class DbTestCase(WorkingDirTestCase):
|
|||||||
|
|
||||||
alembic_config = get_alembic_config()
|
alembic_config = get_alembic_config()
|
||||||
alembic_config.storyboard_config = CONF
|
alembic_config.storyboard_config = CONF
|
||||||
CONF.set_override(
|
|
||||||
"connection",
|
|
||||||
self.test_connection + "/%s"
|
|
||||||
% self.db_name,
|
|
||||||
group="database")
|
|
||||||
|
|
||||||
command.upgrade(alembic_config, "head")
|
command.upgrade(alembic_config, "head")
|
||||||
self.addCleanup(self._drop_db)
|
self.addCleanup(self._drop_db)
|
||||||
|
|
||||||
def _drop_db(self):
|
def _drop_db(self):
|
||||||
|
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(
|
engine = sqlalchemy.create_engine(
|
||||||
self.test_connection)
|
self.test_connection)
|
||||||
try:
|
try:
|
||||||
|
@ -49,8 +49,26 @@ class TestDBReferenceError(base.BaseDbTestCase):
|
|||||||
'story_id': 100
|
'story_id': 100
|
||||||
}
|
}
|
||||||
|
|
||||||
self.assertRaises(exc.DBReferenceError,
|
# TODO(dhellmann): The SQLite database doesn't use foreign key
|
||||||
lambda: tasks.task_create(task))
|
# 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):
|
class TestDbInvalidSortKey(base.BaseDbTestCase):
|
||||||
|
13
tox.ini
13
tox.ini
@ -1,5 +1,5 @@
|
|||||||
[tox]
|
[tox]
|
||||||
minversion = 1.6
|
minversion = 2.9.1
|
||||||
skipsdist = True
|
skipsdist = True
|
||||||
envlist = py34,py27,pep8
|
envlist = py34,py27,pep8
|
||||||
|
|
||||||
@ -10,12 +10,21 @@ setenv =
|
|||||||
VIRTUAL_ENV={envdir}
|
VIRTUAL_ENV={envdir}
|
||||||
OS_STDERR_CAPTURE=1
|
OS_STDERR_CAPTURE=1
|
||||||
OS_STDOUT_CAPTURE=1
|
OS_STDOUT_CAPTURE=1
|
||||||
passenv = OS_TEST_TIMEOUT
|
passenv =
|
||||||
|
OS_TEST_TIMEOUT
|
||||||
|
STORYBOARD_TEST_DB
|
||||||
deps = -r{toxinidir}/requirements.txt
|
deps = -r{toxinidir}/requirements.txt
|
||||||
-r{toxinidir}/test-requirements.txt
|
-r{toxinidir}/test-requirements.txt
|
||||||
commands = ostestr '{posargs}'
|
commands = ostestr '{posargs}'
|
||||||
whitelist_externals = bash
|
whitelist_externals = bash
|
||||||
|
|
||||||
|
[testenv:sqlite]
|
||||||
|
basepython = python3
|
||||||
|
setenv =
|
||||||
|
STORYBOARD_TEST_DB=sqlite:///{envtmpdir}
|
||||||
|
OS_STDERR_CAPTURE=1
|
||||||
|
OS_STDOUT_CAPTURE=1
|
||||||
|
|
||||||
[testenv:pep8]
|
[testenv:pep8]
|
||||||
commands = flake8
|
commands = flake8
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user