def test__get_tables_info_called_with_correct_inspectors( self, _get_inspectors_mock, _get_tables_info_mock, _get_tables_data_mock, _get_enums_data_mock, _compile_errors_mock): left_inspector, right_inspector = _get_inspectors_mock.return_value compare("left_uri", "right_uri", ignores=['ignore_me']) _get_inspectors_mock.assert_called_once_with("left_uri", "right_uri") _get_tables_info_mock.assert_called_once_with( left_inspector, right_inspector, set(['ignore_me']))
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_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_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_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(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_compare_calls_chain( self, _get_tables_info_mock, _get_tables_data_mock, _get_enums_data_mock, _compile_errors_mock): """By inspecting `info` and `errors` at the end, we automatically check that the whole process works as expected. What this test leaves out is the verifications about inspectors. """ _get_tables_data_mock.return_value = { 'common_table_A': { 'data': 'some-data-A', }, 'common_table_B': { 'data': 'some-data-B', }, } tables_info = _get_tables_info_mock.return_value result = compare( "left_uri", "right_uri", ignores=['ignore_me']) expected_info = { 'uris': { 'left': "left_uri", 'right': "right_uri", }, 'tables': { 'left': tables_info.left, 'left_only': tables_info.left_only, 'right': tables_info.right, 'right_only': tables_info.right_only, 'common': tables_info.common, }, 'tables_data': { 'common_table_A': { 'data': 'some-data-A', }, 'common_table_B': { 'data': 'some-data-B', }, }, 'enums': { 'left_only': [], 'right_only': [], 'common': [], 'diff': [], }, } expected_errors = expected_info.copy() expected_errors['_err'] = True assert expected_info == result.info assert expected_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': { '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_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)