From 5ee7eee279cc4508b3bbdc737e75969b4a2dfb20 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 10 Nov 2022 16:14:15 +0300 Subject: Tests: Generalise tests for adding/removing columns to/from tables --- ...rce_meta_field_to_resources_categories_table.py | 77 ------------------ .../auth/test_migrations_add_remove_columns.py | 95 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 77 deletions(-) delete mode 100644 tests/unit/auth/test_migration_add_resource_meta_field_to_resources_categories_table.py create mode 100644 tests/unit/auth/test_migrations_add_remove_columns.py (limited to 'tests') diff --git a/tests/unit/auth/test_migration_add_resource_meta_field_to_resources_categories_table.py b/tests/unit/auth/test_migration_add_resource_meta_field_to_resources_categories_table.py deleted file mode 100644 index 43ee88f..0000000 --- a/tests/unit/auth/test_migration_add_resource_meta_field_to_resources_categories_table.py +++ /dev/null @@ -1,77 +0,0 @@ -"""Test migration adding the `resource_meta` field to `resource_categories` table.""" -from contextlib import closing - -import pytest -import sqlite3 - -from gn3.migrations import get_migration, apply_migrations, rollback_migrations -from tests.unit.auth.conftest import ( - migrations_up_to, apply_single_migration, rollback_single_migration) - -migration_path = "migrations/auth/20221109_01_HbD5F-add-resource-meta-field-to-resource-categories-field.py" - -def __has_resource_meta(value: str): - return value.find("resource_meta TEXT") >= 0 - -@pytest.mark.unit_test -def test_apply_add_resource_meta(auth_migrations_dir, auth_testdb_path, backend): - older_migrations = migrations_up_to(migration_path, auth_migrations_dir) - the_migration = get_migration(migration_path) - apply_migrations(backend, older_migrations) - with closing(sqlite3.connect(auth_testdb_path)) as conn, closing(conn.cursor()) as cursor: - cursor.execute( - "SELECT sql FROM sqlite_schema WHERE name=?", - ("resource_categories",)) - results_before_migration = cursor.fetchone() - apply_single_migration(backend, the_migration) - cursor.execute( - "SELECT sql FROM sqlite_schema WHERE name=?", - ("resource_categories",)) - results_after_migration = cursor.fetchone() - - rollback_migrations(backend, older_migrations + [the_migration]) - - assert not any( - [__has_resource_meta(line.strip()) - for line in results_before_migration[0].split("\n")] - ), "`resource_meta` field exists in table before migration." - assert any( - [__has_resource_meta(line.strip()) - for line in results_after_migration[0].split("\n")] - ), "Couldn't find `resource_meta` field in table" - -@pytest.mark.unit_test -def test_rollback_add_resource_meta(auth_migrations_dir, auth_testdb_path, backend): - older_migrations = migrations_up_to(migration_path, auth_migrations_dir) - the_migration = get_migration(migration_path) - apply_migrations(backend, older_migrations) - with closing(sqlite3.connect(auth_testdb_path)) as conn, closing(conn.cursor()) as cursor: - cursor.execute( - "SELECT sql FROM sqlite_schema WHERE name=?", - ("resource_categories",)) - results_before_migration = cursor.fetchone() - apply_single_migration(backend, the_migration) - cursor.execute( - "SELECT sql FROM sqlite_schema WHERE name=?", - ("resource_categories",)) - results_after_migration = cursor.fetchone() - rollback_single_migration(backend, the_migration) - cursor.execute( - "SELECT sql FROM sqlite_schema WHERE name=?", - ("resource_categories",)) - results_after_rollback = cursor.fetchone() - - rollback_migrations(backend, older_migrations) - - assert not any ([ - __has_resource_meta(line.strip()) - for line in results_before_migration[0].split("\n")] - ), "`resource_meta` field exists in table before migration." - assert any([ - __has_resource_meta(line.strip()) - for line in results_after_migration[0].split("\n")] - ), "Couldn't find `resource_meta` field in table" - assert not any([ - __has_resource_meta(line.strip()) - for line in results_after_rollback[0].split("\n")] - ), "`resource_meta` field exists in table after rollback." diff --git a/tests/unit/auth/test_migrations_add_remove_columns.py b/tests/unit/auth/test_migrations_add_remove_columns.py new file mode 100644 index 0000000..b5df9d3 --- /dev/null +++ b/tests/unit/auth/test_migrations_add_remove_columns.py @@ -0,0 +1,95 @@ +"""Test migrations that alter tables adding/removing columns.""" + +from contextlib import closing + +import pytest +import sqlite3 + +from gn3.migrations import get_migration, apply_migrations, rollback_migrations +from tests.unit.auth.conftest import ( + apply_single_migration, rollback_single_migration, migrations_up_to) + +query = "SELECT sql FROM sqlite_schema WHERE name=?" + +test_params = ( + ("20221109_01_HbD5F-add-resource-meta-field-to-resource-categories-field.py", + "resource_categories", "resource_meta TEXT", True),) + +def found(haystack: str, needle: str) -> bool: + return any([ + (line.strip().find(needle) >= 0) for line in haystack.split("\n")]) + +def pristine_before_migration(adding: bool, result_str: str, column: str) -> bool: + col_was_found = found(result_str, column) + if adding: + return not col_was_found + return col_was_found + +def applied_successfully(adding: bool, result_str: str, column: str) -> bool: + col_was_found = found(result_str, column) + if adding: + return col_was_found + return not col_was_found + +@pytest.mark.unit_test +@pytest.mark.parametrize( + "migration_file,the_table,the_column,adding", test_params) +def test_apply_add_remove_column( + auth_migrations_dir, auth_testdb_path, backend, migration_file, + the_table, the_column, adding): + """ + GIVEN: A migration that alters a table, adding or removing a column + WHEN: The migration is applied + THEN: Ensure the column exists if `adding` is True, otherwise, ensure the + column has been dropped + """ + migration_path = f"{auth_migrations_dir}/{migration_file}" + older_migrations = migrations_up_to(migration_path, auth_migrations_dir) + the_migration = get_migration(migration_path) + apply_migrations(backend, older_migrations) + with closing(sqlite3.connect(auth_testdb_path)) as conn, closing(conn.cursor()) as cursor: + cursor.execute(query, (the_table,)) + results_before_migration = cursor.fetchone() + apply_single_migration(backend, the_migration) + cursor.execute(query, (the_table,)) + results_after_migration = cursor.fetchone() + + rollback_migrations(backend, older_migrations + [the_migration]) + + assert pristine_before_migration( + adding, results_before_migration[0], the_column), ( + "Database inconsistent before applying migration.") + assert applied_successfully( + adding, results_after_migration[0], the_column), "Migration failed" + +@pytest.mark.unit_test +@pytest.mark.parametrize( + "migration_file,the_table,the_column,adding", test_params) +def test_rollback_add_remove_column( + auth_migrations_dir, auth_testdb_path, backend, migration_file, + the_table, the_column, adding): + """ + GIVEN: A migration that alters a table, adding or removing a column + WHEN: The migration is applied + THEN: Ensure the column is dropped if `adding` is True, otherwise, ensure + the column has been restored + """ + migration_path = f"{auth_migrations_dir}/{migration_file}" + older_migrations = migrations_up_to(migration_path, auth_migrations_dir) + the_migration = get_migration(migration_path) + apply_migrations(backend, older_migrations) + apply_single_migration(backend, the_migration) + with closing(sqlite3.connect(auth_testdb_path)) as conn, closing(conn.cursor()) as cursor: + cursor.execute(query, (the_table,)) + results_before_migration = cursor.fetchone() + rollback_single_migration(backend, the_migration) + cursor.execute(query, (the_table,)) + results_after_migration = cursor.fetchone() + + rollback_migrations(backend, older_migrations + [the_migration]) + + assert pristine_before_migration( + not adding, results_before_migration[0], the_column), ( + "Database inconsistent before applying migration.") + assert applied_successfully( + not adding, results_after_migration[0], the_column), "Migration failed" -- cgit v1.2.3