Best Python code snippet using tempest_python
test_migrations.py
Source:test_migrations.py
1# Copyright (C) 2015-2016 by the Free Software Foundation, Inc.2#3# This file is part of GNU Mailman.4#5# GNU Mailman is free software: you can redistribute it and/or modify it under6# the terms of the GNU General Public License as published by the Free7# Software Foundation, either version 3 of the License, or (at your option)8# any later version.9#10# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT11# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for13# more details.14#15# You should have received a copy of the GNU General Public License along with16# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.17"""Test database schema migrations with Alembic"""18import os19import unittest20import sqlalchemy as sa21import alembic.command22from mailman.app.lifecycle import create_list23from mailman.config import config24from mailman.database.alembic import alembic_cfg25from mailman.database.helpers import exists_in_db26from mailman.database.model import Model27from mailman.database.transaction import transaction28from mailman.database.types import Enum29from mailman.interfaces.action import Action30from mailman.interfaces.member import MemberRole31from mailman.interfaces.usermanager import IUserManager32from mailman.testing.layers import ConfigLayer33from zope.component import getUtility34class TestMigrations(unittest.TestCase):35 layer = ConfigLayer36 def setUp(self):37 alembic.command.stamp(alembic_cfg, 'head')38 def tearDown(self):39 # Drop and restore a virgin database.40 config.db.store.rollback()41 md = sa.MetaData(bind=config.db.engine)42 md.reflect()43 # We have circular dependencies between user and address, thus we can't44 # use drop_all() without getting a warning. Setting use_alter to True45 # on the foreign keys helps SQLAlchemy mark those loops as known.46 for tablename in ('user', 'address'):47 if tablename not in md.tables:48 continue49 for fk in md.tables[tablename].foreign_keys:50 fk.constraint.use_alter = True51 md.drop_all()52 Model.metadata.create_all(config.db.engine)53 def test_all_migrations(self):54 script_dir = alembic.script.ScriptDirectory.from_config(alembic_cfg)55 revisions = [sc.revision for sc in script_dir.walk_revisions()]56 for revision in revisions:57 alembic.command.downgrade(alembic_cfg, revision)58 revisions.reverse()59 for revision in revisions:60 alembic.command.upgrade(alembic_cfg, revision)61 def test_42756496720_header_matches(self):62 test_header_matches = [63 ('test-header-1', 'test-pattern-1'),64 ('test-header-2', 'test-pattern-2'),65 ('test-header-3', 'test-pattern-3'),66 ]67 mlist_table = sa.sql.table(68 'mailinglist',69 sa.sql.column('id', sa.Integer),70 sa.sql.column('header_matches', sa.PickleType)71 )72 header_match_table = sa.sql.table(73 'headermatch',74 sa.sql.column('mailing_list_id', sa.Integer),75 sa.sql.column('header', sa.Unicode),76 sa.sql.column('pattern', sa.Unicode),77 )78 # Bring the DB to the revision that is being tested.79 alembic.command.downgrade(alembic_cfg, '42756496720')80 # Test downgrading.81 config.db.store.execute(mlist_table.insert().values(id=1))82 config.db.store.execute(header_match_table.insert().values(83 [{'mailing_list_id': 1, 'header': hm[0], 'pattern': hm[1]}84 for hm in test_header_matches]))85 config.db.store.commit()86 alembic.command.downgrade(alembic_cfg, '2bb9b382198')87 results = config.db.store.execute(88 mlist_table.select()).fetchall()89 self.assertEqual(results[0].header_matches, test_header_matches)90 self.assertFalse(exists_in_db(config.db.engine, 'headermatch'))91 config.db.store.commit()92 # Test upgrading.93 alembic.command.upgrade(alembic_cfg, '42756496720')94 results = config.db.store.execute(95 header_match_table.select()).fetchall()96 self.assertEqual(97 results,98 [(1, hm[0], hm[1]) for hm in test_header_matches])99 def test_47294d3a604_pendable_keyvalues(self):100 # We have 5 pended items:101 # - one is a probe request102 # - one is a subscription request103 # - one is a moderation request104 # - one is a held message105 # - one is a registration request in the new format106 #107 # The first three used to have no 'type' key and must be properly108 # typed, the held message used to have a type key, but in JSON, and109 # must be converted.110 pended_table = sa.sql.table(111 'pended',112 sa.sql.column('id', sa.Integer),113 )114 keyvalue_table = sa.sql.table(115 'pendedkeyvalue',116 sa.sql.column('id', sa.Integer),117 sa.sql.column('key', sa.Unicode),118 sa.sql.column('value', sa.Unicode),119 sa.sql.column('pended_id', sa.Integer),120 )121 def get_from_db(): # noqa122 results = {}123 for i in range(1, 6):124 query = sa.sql.select(125 [keyvalue_table.c.key, keyvalue_table.c.value]126 ).where(127 keyvalue_table.c.pended_id == i128 )129 results[i] = dict([130 (r['key'], r['value']) for r in131 config.db.store.execute(query).fetchall()132 ])133 return results134 # Start at the previous revision135 with transaction():136 alembic.command.downgrade(alembic_cfg, '33bc0099223')137 for i in range(1, 6):138 config.db.store.execute(pended_table.insert().values(id=i))139 config.db.store.execute(keyvalue_table.insert().values([140 {'pended_id': 1, 'key': 'member_id', 'value': 'test-value'},141 {'pended_id': 2, 'key': 'token_owner', 'value': 'test-value'},142 {'pended_id': 3, 'key': '_mod_message_id',143 'value': 'test-value'},144 {'pended_id': 4, 'key': 'type', 'value': '"held message"'},145 {'pended_id': 5, 'key': 'type', 'value': 'registration'},146 ]))147 # Upgrading.148 with transaction():149 alembic.command.upgrade(alembic_cfg, '47294d3a604')150 results = get_from_db()151 for i in range(1, 5):152 self.assertIn('type', results[i])153 self.assertEqual(results[1]['type'], 'probe')154 self.assertEqual(results[2]['type'], 'subscription')155 self.assertEqual(results[3]['type'], 'data')156 self.assertEqual(results[4]['type'], 'held message')157 self.assertEqual(results[5]['type'], 'registration')158 # Downgrading.159 with transaction():160 alembic.command.downgrade(alembic_cfg, '33bc0099223')161 results = get_from_db()162 for i in range(1, 4):163 self.assertNotIn('type', results[i])164 self.assertEqual(results[4]['type'], '"held message"')165 self.assertEqual(results[5]['type'], '"registration"')166 def test_70af5a4e5790_digests(self):167 IDS_TO_DIGESTABLE = [168 (1, True),169 (2, False),170 (3, False),171 (4, True),172 ]173 mlist_table = sa.sql.table(174 'mailinglist',175 sa.sql.column('id', sa.Integer),176 sa.sql.column('digests_enabled', sa.Boolean)177 )178 # Downgrading.179 with transaction():180 for table_id, enabled in IDS_TO_DIGESTABLE:181 config.db.store.execute(mlist_table.insert().values(182 id=table_id, digests_enabled=enabled))183 with transaction():184 alembic.command.downgrade(alembic_cfg, '47294d3a604')185 results = config.db.store.execute(186 'SELECT id, digestable FROM mailinglist').fetchall()187 self.assertEqual(results, IDS_TO_DIGESTABLE)188 # Upgrading.189 with transaction():190 alembic.command.upgrade(alembic_cfg, '70af5a4e5790')191 results = config.db.store.execute(192 'SELECT id, digests_enabled FROM mailinglist').fetchall()193 self.assertEqual(results, IDS_TO_DIGESTABLE)194 def test_70af5a4e5790_data_paths(self):195 # Create a couple of mailing lists through the standard API.196 with transaction():197 ant = create_list('ant@example.com')198 bee = create_list('bee@example.com')199 # Downgrade and verify that the old data paths exist.200 alembic.command.downgrade(alembic_cfg, '47294d3a604')201 self.assertTrue(os.path.exists(202 os.path.join(config.LIST_DATA_DIR, 'ant@example.com')))203 self.assertTrue(os.path.exists(204 os.path.join(config.LIST_DATA_DIR, 'ant@example.com')))205 # Upgrade and verify that the new data paths exists and the old ones206 # no longer do.207 alembic.command.upgrade(alembic_cfg, '70af5a4e5790')208 self.assertFalse(os.path.exists(209 os.path.join(config.LIST_DATA_DIR, 'ant@example.com')))210 self.assertFalse(os.path.exists(211 os.path.join(config.LIST_DATA_DIR, 'ant@example.com')))212 self.assertTrue(os.path.exists(ant.data_path))213 self.assertTrue(os.path.exists(bee.data_path))214 def test_7b254d88f122_moderation_action(self):215 mailinglist_table = sa.sql.table( # noqa216 'mailinglist',217 sa.sql.column('id', sa.Integer),218 sa.sql.column('list_id', sa.Unicode),219 sa.sql.column('default_member_action', Enum(Action)),220 sa.sql.column('default_nonmember_action', Enum(Action)),221 )222 member_table = sa.sql.table(223 'member',224 sa.sql.column('id', sa.Integer),225 sa.sql.column('list_id', sa.Unicode),226 sa.sql.column('address_id', sa.Integer),227 sa.sql.column('role', Enum(MemberRole)),228 sa.sql.column('moderation_action', Enum(Action)),229 )230 user_manager = getUtility(IUserManager)231 with transaction():232 # Start at the previous revision.233 alembic.command.downgrade(alembic_cfg, 'd4fbb4fd34ca')234 # Create a mailing list through the standard API.235 ant = create_list('ant@example.com')236 # Create some members.237 anne = user_manager.create_address('anne@example.com')238 bart = user_manager.create_address('bart@example.com')239 cris = user_manager.create_address('cris@example.com')240 dana = user_manager.create_address('dana@example.com')241 # Flush the database to get the last auto-increment id.242 config.db.store.flush()243 # Assign some moderation actions to the members created above.244 config.db.store.execute(member_table.insert().values([245 {'address_id': anne.id, 'role': MemberRole.owner,246 'list_id': ant.list_id, 'moderation_action': Action.accept},247 {'address_id': bart.id, 'role': MemberRole.moderator,248 'list_id': ant.list_id, 'moderation_action': Action.accept},249 {'address_id': cris.id, 'role': MemberRole.member,250 'list_id': ant.list_id, 'moderation_action': Action.defer},251 {'address_id': dana.id, 'role': MemberRole.nonmember,252 'list_id': ant.list_id, 'moderation_action': Action.hold},253 ]))254 # Cris and Dana have actions which match the list default action for255 # members and nonmembers respectively.256 self.assertEqual(257 ant.members.get_member('cris@example.com').moderation_action,258 ant.default_member_action)259 self.assertEqual(260 ant.nonmembers.get_member('dana@example.com').moderation_action,261 ant.default_nonmember_action)262 # Upgrade and check the moderation_actions. Cris's and Dana's263 # actions have been set to None to fall back to the list defaults.264 alembic.command.upgrade(alembic_cfg, '7b254d88f122')265 members = config.db.store.execute(sa.select([266 member_table.c.address_id, member_table.c.moderation_action,267 ])).fetchall()268 self.assertEqual(members, [269 (anne.id, Action.accept),270 (bart.id, Action.accept),271 (cris.id, None),272 (dana.id, None),273 ])274 # Downgrade and check that Cris's and Dana's actions have been set275 # explicitly.276 alembic.command.downgrade(alembic_cfg, 'd4fbb4fd34ca')277 members = config.db.store.execute(sa.select([278 member_table.c.address_id, member_table.c.moderation_action,279 ])).fetchall()280 self.assertEqual(members, [281 (anne.id, Action.accept),282 (bart.id, Action.accept),283 (cris.id, Action.defer),284 (dana.id, Action.hold),...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!