def test_same_schema_is_the_same(uri_left, uri_right): prepare_schema_from_models(uri_left, Base_right) prepare_schema_from_models(uri_right, Base_right) result = compare(uri_left, uri_right) assert result.is_match
def test_schemas_are_different(uri_left, uri_right): prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) result = compare(uri_left, uri_right) assert not result.is_match
def test_ignores_alternative_sep(uri_left, uri_right): # functionally the same of `test_errors_dict_catches_all_differences` # but all errors are silenced with ignores prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) ignores = [ 'mobile_numbers', 'phone_numbers', 'companies#col#name', 'companies#idx#name', 'employees#fk#fk_employees_companies', 'employees#fk#fk_emp_comp', 'employees#idx#ix_employees_name', 'employees#idx#fk_employees_companies', 'employees#idx#name', 'employees#idx#fk_emp_comp', 'roles#col#name', 'skills#col#slug', 'skills#col#id', 'skills#pk#slug', 'skills#pk#id', ] result = compare(uri_left, uri_right, ignores=ignores, ignores_sep='#') assert result.is_match
def test_ignores_all_needed(uri_left, uri_right, missing_ignore): # proves each ignore clause is needed prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) ignores = [ 'mobile_numbers', 'phone_numbers', 'companies.col.name', 'companies.idx.name', 'employees.fk.fk_employees_companies', 'employees.fk.fk_emp_comp', 'employees.idx.ix_employees_name', 'employees.idx.fk_employees_companies', 'employees.idx.name', 'employees.idx.fk_emp_comp', 'roles.col.name', 'skills.col.slug', 'skills.col.id', 'skills.pk.slug', 'skills.pk.id', ] result = compare(uri_left, uri_right, ignores=list(set(ignores) - set([missing_ignore]))) assert not result.is_match
def test_ignores(uri_left, uri_right): # functionally the same of `test_errors_dict_catches_all_differences` # but all errors are silenced with ignores prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) ignores = [ 'mobile_numbers', 'phone_numbers', 'companies.col.name', 'companies.idx.name', 'employees.fk.fk_employees_companies', 'employees.fk.fk_emp_comp', 'employees.idx.ix_employees_name', 'employees.idx.fk_employees_companies', 'employees.idx.name', 'employees.idx.fk_emp_comp', 'roles.col.name', 'skills.col.slug', 'skills.col.id', 'skills.pk.slug', 'skills.pk.id', ] result = compare(uri_left, uri_right, ignores) assert result.is_match
def test_model_and_migration_schemas_are_the_same(uri_left, uri_right, alembic_config_left): """Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. """ prepare_schema_from_migrations(uri_left, alembic_config_left) prepare_schema_from_models(uri_right, Base) result = compare(uri_left, uri_right, set(['alembic_version'])) assert result.is_match
def test_model_and_migration_schemas_are_the_same(self, uri_left, uri_right, alembic_config_left): """Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. """ setup_extensions(uri_left) prepare_schema_from_migrations(uri_left, alembic_config_left) from ingredients_db.models.images import Image, ImageMembers from ingredients_db.models.instance import Instance, InstanceKeypair from ingredients_db.models.network import Network from ingredients_db.models.network_port import NetworkPort from ingredients_db.models.project import Project, ProjectMembers from ingredients_db.models.keypair import Keypair from ingredients_db.models.task import Task from ingredients_db.models.authn import AuthNUser, AuthNServiceAccount from ingredients_db.models.authz import AuthZPolicy, AuthZRole, AuthZRolePolicy from ingredients_db.models.region import Region from ingredients_db.models.zones import Zone from ingredients_db.models.builtin import BuiltInUser # Make sure the imports don't go away Image.mro() ImageMembers.mro() Instance.mro() InstanceKeypair.mro() Network.mro() NetworkPort.mro() Project.mro() ProjectMembers.mro() Keypair.mro() Task.mro() AuthNUser.mro() AuthNServiceAccount.mro() AuthZPolicy.mro() AuthZRole.mro() AuthZRolePolicy.mro() Region.mro() Zone.mro() BuiltInUser.mro() setup_extensions(uri_right) prepare_schema_from_models(uri_right, Base) result = compare(uri_left, uri_right, {'alembic_version'}) print(json.dumps(result.errors, indent=4)) assert result.is_match
def test_model_and_migration_schemas_are_the_same(self): """Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. It produces a text file with the results to help debug differences. """ prepare_schema_from_migrations(self.uri_left, self.alembic_config_left) prepare_schema_from_models(self.uri_right, Base) result = compare(self.uri_left, self.uri_right, set(['alembic_version'])) assert result.is_match
def test_model_and_migration_schemas_are_the_same(uri_left, uri_right, alembic_config_left): """Compares the database schema obtained with all migrations against the one we get out of the models. """ ah.load_premigration_sql(uri_left) prepare_schema_from_migrations(uri_left, alembic_config_left) prepare_schema_from_models(uri_right, Base) result = compare(uri_left, uri_right, ignores=['alembic_version']) assert result.is_match is True, \ 'Differences (left is migrations, right is models):\n' \ '%s' % json.dumps( result.errors, sort_keys=True, indent=4, separators=(',', ': ') )
def create_app(self): """ Переопределние метода create_app из LiveServerTestCase. Для того чтобы скормить тестам наше приложение. """ uri = (get_config('DB_CONFIG')) self.testdb_uri = get_temporary_uri(uri) new_db(self.testdb_uri) engine = create_engine(self.testdb_uri) engine.execute("CREATE EXTENSION pgcrypto;") prepare_schema_from_models(self.testdb_uri, Base) app = create_app(self.testdb_uri) app.config['TESTING'] = True app.config['DEBUG'] = True app.config['LIVESERVER_PORT'] = 8943 app.config['LIVESERVER_TIMEOUT'] = 10 return app
def test_model_and_migration_schemas_are_the_same(self): """Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. It produces a text file with the results to help debug differences. """ prepare_schema_from_migrations(self.uri_left, self.alembic_config_left) prepare_schema_from_models(self.uri_right, Base) result = compare(self.uri_left, self.uri_right, ignores=set([ 'alembic_version', 'menstrual_cup_fill.col.removal_time', 'menstrual_cup_fill.col.time' ])) import json assert result.is_match, json.dumps(result.errors, indent=True)
def test_model_and_migration_schemas_are_the_same( uri_left, uri_right, alembic_config_left): """Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. """ prepare_schema_from_migrations(uri_left, alembic_config_left) engine = create_engine(uri_right) engine.execute('create extension postgis') prepare_schema_from_models(uri_right, Base) result = compare( uri_left, uri_right, # Ignore grids.srid fkey because of the flaky way it has to be set up; # for details see comments in definiton of `Grid` in `v2.py`. ignores={'alembic_version', 'grids.fk.grids_srid_fkey'} ) assert result.is_match
def test_model_and_migration_schemas_are_the_same(self): """ Compare two databases. Compares the database obtained with all migrations against the one we get out of the models. It produces a text file with the results to help debug differences. """ prepare_schema_from_migrations(self.uri_left, self.alembic_config_left) engine = create_engine(self.uri_right) engine.execute("CREATE EXTENSION pgcrypto;") prepare_schema_from_models(self.uri_right, db) result = compare(self.uri_left, self.uri_right, set(['alembic_version'])) if not result.is_match: print("###### DB MISMATCH:") pprint.PrettyPrinter(indent=1).pprint(result.errors) assert result.is_match
def test_errors_dict_catches_all_differences(uri_left, uri_right): prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) result = compare(uri_left, uri_right) expected_errors = { 'tables': { 'left_only': ['mobile_numbers'], 'right_only': ['phone_numbers'], }, 'tables_data': { 'companies': { 'columns': { 'diff': [{ 'key': 'name', 'left': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(200)', }, 'right': { 'default': None, 'name': 'name', 'nullable': True, 'type': 'VARCHAR(200)', } }] }, 'indexes': { 'left_only': [{ 'column_names': ['name'], 'name': 'name', 'type': 'UNIQUE', 'unique': True, }] } }, 'employees': { 'foreign_keys': { 'left_only': [{ 'constrained_columns': ['company_id'], 'name': 'fk_employees_companies', 'options': {}, 'referred_columns': ['id'], 'referred_schema': None, 'referred_table': 'companies' }], 'right_only': [{ 'constrained_columns': ['company_id'], 'name': 'fk_emp_comp', 'options': {}, 'referred_columns': ['id'], 'referred_schema': None, 'referred_table': 'companies', }] }, 'indexes': { 'left_only': [{ 'column_names': ['name'], 'name': 'ix_employees_name', 'type': 'UNIQUE', 'unique': True, }, { 'column_names': ['company_id'], 'name': 'fk_employees_companies', 'unique': False, }], 'right_only': [{ 'column_names': ['company_id'], 'name': 'fk_emp_comp', 'unique': False, }, { 'column_names': ['name'], 'name': 'name', 'type': 'UNIQUE', 'unique': True, }] } }, 'roles': { 'columns': { 'diff': [{ 'key': 'name', 'left': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(50)', }, 'right': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(60)', } }] } }, 'skills': { 'columns': { 'diff': [{ 'key': 'slug', 'left': { 'default': None, 'name': 'slug', 'nullable': False, 'type': 'VARCHAR(50)', }, 'right': { 'default': None, 'name': 'slug', 'nullable': True, 'type': 'VARCHAR(50)', } }], 'right_only': [{ 'autoincrement': True, 'default': None, 'name': 'id', 'nullable': False, 'type': 'INTEGER(11)', }] }, 'primary_keys': { 'left_only': ['slug'], 'right_only': ['id'], } } }, 'uris': { 'left': uri_left, 'right': uri_right, } } assert not result.is_match compare_error_dicts(expected_errors, result.errors)
def test_model_and_migration_schemas_are_not_the_same(uri_left, uri_right, alembic_config_left): """Compares the database obtained with the first migration against the one we get out of the models. """ prepare_schema_from_migrations(uri_left, alembic_config_left, revision="+1") prepare_schema_from_models(uri_right, Base) result = compare(uri_left, uri_right, set(['alembic_version'])) # uncomment to see the dump of errors dict # result.dump_errors() errors = { 'tables': { 'left_only': ['addresses'], 'right_only': ['roles'] }, 'tables_data': { 'employees': { 'columns': { 'left_only': [{ 'default': None, 'name': 'favourite_meal', 'nullable': False, 'type': "ENUM('meat','vegan','vegetarian')" }], 'right_only': [ { 'autoincrement': False, 'default': None, 'name': 'role_id', 'nullable': False, 'type': 'INTEGER(11)' }, { 'autoincrement': False, 'default': None, 'name': 'number_of_pets', 'nullable': False, 'type': 'INTEGER(11)' }, ] }, 'foreign_keys': { 'right_only': [{ 'constrained_columns': ['role_id'], 'name': 'fk_employees_roles', 'options': {}, 'referred_columns': ['id'], 'referred_schema': None, 'referred_table': 'roles' }] }, 'indexes': { 'left_only': [{ 'column_names': ['name'], 'name': 'name', 'type': 'UNIQUE', 'unique': True }], 'right_only': [{ 'column_names': ['role_id'], 'name': 'fk_employees_roles', 'unique': False }, { 'column_names': ['name'], 'name': 'ix_employees_name', 'type': 'UNIQUE', 'unique': True }] } }, 'phone_numbers': { 'columns': { 'diff': [{ 'key': 'number', 'left': { 'default': None, 'name': 'number', 'nullable': True, 'type': 'VARCHAR(40)' }, 'right': { 'default': None, 'name': 'number', 'nullable': False, 'type': 'VARCHAR(40)' } }] } } }, 'uris': { 'left': uri_left, 'right': uri_right, } } compare_error_dicts(errors, result.errors)
def test_errors_dict_catches_all_differences(uri_left, uri_right): prepare_schema_from_models(uri_left, Base_left) prepare_schema_from_models(uri_right, Base_right) result = compare(uri_left, uri_right) expected_errors = { 'tables': { 'left_only': ['mobile_numbers'], 'right_only': ['phone_numbers'], }, 'tables_data': { 'companies': { 'columns': { 'diff': [{ 'key': 'name', 'left': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(200)', }, 'right': { 'default': None, 'name': 'name', 'nullable': True, 'type': 'VARCHAR(200)', } }] }, 'indexes': { 'left_only': [{ 'column_names': ['name'], 'name': 'name', 'type': 'UNIQUE', 'unique': True, }] } }, 'employees': { 'columns': { 'diff': [{ 'key': 'polarity', 'left': { 'default': None, 'name': 'polarity', 'nullable': True, 'type': "ENUM('NEGATIVE','POSITIVE')" }, 'right': { 'default': None, 'name': 'polarity', 'nullable': True, 'type': "ENUM('NEG','POS')" } }, { 'key': 'spin', 'left': { 'default': None, 'name': 'spin', 'nullable': True, 'type': 'VARCHAR(9)' }, 'right': { 'default': None, 'name': 'spin', 'nullable': True, 'type': 'VARCHAR(4)' } }] }, 'foreign_keys': { 'left_only': [{ 'constrained_columns': ['company_id'], 'name': 'fk_employees_companies', 'options': {}, 'referred_columns': ['id'], 'referred_schema': None, 'referred_table': 'companies' }], 'right_only': [{ 'constrained_columns': ['company_id'], 'name': 'fk_emp_comp', 'options': {}, 'referred_columns': ['id'], 'referred_schema': None, 'referred_table': 'companies', }] }, 'indexes': { 'left_only': [{ 'column_names': ['name'], 'name': 'ix_employees_name', 'type': 'UNIQUE', 'unique': True, }, { 'column_names': ['company_id'], 'name': 'fk_employees_companies', 'unique': False, }], 'right_only': [{ 'column_names': ['company_id'], 'name': 'fk_emp_comp', 'unique': False, }, { 'column_names': ['name'], 'name': 'name', 'type': 'UNIQUE', 'unique': True, }] } }, 'roles': { 'columns': { 'diff': [{ 'key': 'name', 'left': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(50)', }, 'right': { 'default': None, 'name': 'name', 'nullable': False, 'type': 'VARCHAR(60)', } }] } }, 'skills': { 'columns': { 'diff': [{ 'key': 'slug', 'left': { 'default': None, 'name': 'slug', 'nullable': False, 'type': 'VARCHAR(50)', }, 'right': { 'default': None, 'name': 'slug', 'nullable': True, 'type': 'VARCHAR(50)', } }], 'right_only': [{ 'autoincrement': True, 'default': None, 'name': 'id', 'nullable': False, 'type': 'INTEGER(11)', }] }, 'primary_keys': { 'left_only': ['slug'], 'right_only': ['id'], } } }, 'enums': {}, 'uris': { 'left': uri_left, 'right': uri_right, } } engine = create_engine(uri_left) dialect = engine.dialect if getattr(dialect, 'supports_comments', False): # sqlalchemy 1.2.0 adds support for SQL comments # expect them in the errors when supported for table in expected_errors['tables_data'].values(): for column in table['columns']['diff']: for side in ['left', 'right']: column[side].update(comment=None) for side in ['left_only', 'right_only']: for column in table['columns'].get(side, []): column.update(comment=None) assert not result.is_match compare_error_dicts(expected_errors, result.errors)