From 006c8fbe07bfd3ef82428b177866bbd1fca8d01c Mon Sep 17 00:00:00 2001 From: Dan Cardin Date: Wed, 26 Oct 2022 10:08:28 -0400 Subject: [PATCH] tests: Add tests to verify pmr_credentials access on fixtures. --- src/pytest_mock_resources/__init__.py | 2 +- .../{fixture => }/credentials.py | 26 +++- src/pytest_mock_resources/fixture/__init__.py | 2 - src/pytest_mock_resources/fixture/mongo.py | 10 +- src/pytest_mock_resources/fixture/mysql.py | 11 -- .../fixture/postgresql.py | 16 +-- src/pytest_mock_resources/fixture/redis.py | 4 +- src/pytest_mock_resources/fixture/sqlite.py | 11 -- src/pytest_mock_resources/sqlalchemy.py | 5 + tests/fixture/test_pmr_credentials.py | 121 ++++++++++++++++++ 10 files changed, 159 insertions(+), 49 deletions(-) rename src/pytest_mock_resources/{fixture => }/credentials.py (75%) create mode 100644 tests/fixture/test_pmr_credentials.py diff --git a/src/pytest_mock_resources/__init__.py b/src/pytest_mock_resources/__init__.py index 92250594..454c09ed 100644 --- a/src/pytest_mock_resources/__init__.py +++ b/src/pytest_mock_resources/__init__.py @@ -6,6 +6,7 @@ RedisConfig, RedshiftConfig, ) +from pytest_mock_resources.credentials import Credentials from pytest_mock_resources.fixture import ( create_mongo_fixture, create_moto_fixture, @@ -14,7 +15,6 @@ create_redis_fixture, create_redshift_fixture, create_sqlite_fixture, - Credentials, pmr_mongo_config, pmr_mongo_container, pmr_moto_config, diff --git a/src/pytest_mock_resources/fixture/credentials.py b/src/pytest_mock_resources/credentials.py similarity index 75% rename from src/pytest_mock_resources/fixture/credentials.py rename to src/pytest_mock_resources/credentials.py index aeeb3ea4..254cfb45 100644 --- a/src/pytest_mock_resources/fixture/credentials.py +++ b/src/pytest_mock_resources/credentials.py @@ -1,3 +1,5 @@ +from sqlalchemy.orm import Session + from pytest_mock_resources import compat @@ -74,6 +76,26 @@ def as_redis_kwargs(self): "password": self.password, } + @classmethod + def assign_from_connection(cls, connection): + if isinstance(connection, Session): + url = connection.connection().engine.url + else: + url = connection.url + + instance = cls( + drivername=url.drivername, + host=url.host, + port=url.port, + username=url.username, + password=url.password, + database=url.database, + ) + connection.pmr_credentials = instance + return instance -def assign_fixture_credentials(engine, **credentials): - engine.pmr_credentials = Credentials(**credentials) + @classmethod + def assign_from_credentials(cls, engine, **credentials): + instance = Credentials(**credentials) + engine.pmr_credentials = instance + return instance diff --git a/src/pytest_mock_resources/fixture/__init__.py b/src/pytest_mock_resources/fixture/__init__.py index 4987bbd4..ffad503f 100644 --- a/src/pytest_mock_resources/fixture/__init__.py +++ b/src/pytest_mock_resources/fixture/__init__.py @@ -1,4 +1,3 @@ -from pytest_mock_resources.fixture.credentials import Credentials from pytest_mock_resources.fixture.mongo import ( create_mongo_fixture, pmr_mongo_config, @@ -33,7 +32,6 @@ from pytest_mock_resources.fixture.sqlite import create_sqlite_fixture __all__ = [ - "Credentials", "create_mongo_fixture", "create_moto_fixture", "create_mysql_fixture", diff --git a/src/pytest_mock_resources/fixture/mongo.py b/src/pytest_mock_resources/fixture/mongo.py index fca95760..bd9cf73f 100644 --- a/src/pytest_mock_resources/fixture/mongo.py +++ b/src/pytest_mock_resources/fixture/mongo.py @@ -3,7 +3,7 @@ from pytest_mock_resources.compat import pymongo from pytest_mock_resources.container.base import get_container from pytest_mock_resources.container.mongo import MongoConfig -from pytest_mock_resources.fixture.credentials import assign_fixture_credentials +from pytest_mock_resources.credentials import Credentials @pytest.fixture(scope="session") @@ -64,14 +64,12 @@ def _create_clean_database(config): ) limited_db = limited_client[db_id] - assign_fixture_credentials( + Credentials.assign_from_credentials( limited_db, - drivername="mongodb", host=config.host, port=config.port, - database=db_id, username=db_id, - password="password", + password=password, + database=db_id, ) - return limited_db diff --git a/src/pytest_mock_resources/fixture/mysql.py b/src/pytest_mock_resources/fixture/mysql.py index 39fc4f8c..4af5f2fa 100644 --- a/src/pytest_mock_resources/fixture/mysql.py +++ b/src/pytest_mock_resources/fixture/mysql.py @@ -4,7 +4,6 @@ from pytest_mock_resources.container.base import get_container from pytest_mock_resources.container.mysql import get_sqlalchemy_engine, MysqlConfig -from pytest_mock_resources.fixture.credentials import assign_fixture_credentials from pytest_mock_resources.sqlalchemy import EngineManager @@ -45,16 +44,6 @@ def _(pmr_mysql_container, pmr_mysql_config): database_name = _create_clean_database(pmr_mysql_config) engine = get_sqlalchemy_engine(pmr_mysql_config, database_name) - assign_fixture_credentials( - engine, - drivername="mysql+pymysql", - host=pmr_mysql_config.host, - port=pmr_mysql_config.port, - database=database_name, - username=pmr_mysql_config.username, - password=pmr_mysql_config.password, - ) - engine_manager = EngineManager.create( engine, dynamic_actions=ordered_actions, tables=tables, session=session ) diff --git a/src/pytest_mock_resources/fixture/postgresql.py b/src/pytest_mock_resources/fixture/postgresql.py index fb76ba21..29f586de 100644 --- a/src/pytest_mock_resources/fixture/postgresql.py +++ b/src/pytest_mock_resources/fixture/postgresql.py @@ -7,8 +7,8 @@ from pytest_mock_resources.container.base import get_container from pytest_mock_resources.container.postgres import get_sqlalchemy_engine, PostgresConfig +from pytest_mock_resources.credentials import Credentials from pytest_mock_resources.fixture.base import asyncio_fixture, generate_fixture_id -from pytest_mock_resources.fixture.credentials import assign_fixture_credentials from pytest_mock_resources.sqlalchemy import bifurcate_actions, EngineManager, normalize_actions log = logging.getLogger(__name__) @@ -170,7 +170,7 @@ def create_engine_manager( # distinct from what might have been used for the template database. database_name = _produce_clean_database(root_engine, createdb_template=createdb_template) engine = get_sqlalchemy_engine(pmr_postgres_config, database_name, **engine_kwargs) - _assign_credential(engine, pmr_postgres_config, database_name) + Credentials.assign_from_connection(engine) return EngineManager( engine, @@ -217,15 +217,3 @@ def _generate_database_name(conn): id_ = tuple(result)[0][0] database_name = "pytest_mock_resource_db_{}".format(id_) return database_name - - -def _assign_credential(engine, config, database_name): - assign_fixture_credentials( - engine, - drivername="postgresql+psycopg2", - host=config.host, - port=config.port, - username=config.username, - password=config.password, - database=database_name, - ) diff --git a/src/pytest_mock_resources/fixture/redis.py b/src/pytest_mock_resources/fixture/redis.py index e426bf2d..8c112db2 100644 --- a/src/pytest_mock_resources/fixture/redis.py +++ b/src/pytest_mock_resources/fixture/redis.py @@ -3,7 +3,7 @@ from pytest_mock_resources.compat import redis from pytest_mock_resources.container.base import get_container from pytest_mock_resources.container.redis import RedisConfig -from pytest_mock_resources.fixture.credentials import assign_fixture_credentials +from pytest_mock_resources.credentials import Credentials @pytest.fixture(scope="session") @@ -65,7 +65,7 @@ def _(request, pmr_redis_container, pmr_redis_config): db = redis.Redis(host=pmr_redis_config.host, port=pmr_redis_config.port, db=database_number) db.flushdb() - assign_fixture_credentials( + Credentials.assign_from_credentials( db, drivername="redis", host=pmr_redis_config.host, diff --git a/src/pytest_mock_resources/fixture/sqlite.py b/src/pytest_mock_resources/fixture/sqlite.py index a553458c..f42267ef 100644 --- a/src/pytest_mock_resources/fixture/sqlite.py +++ b/src/pytest_mock_resources/fixture/sqlite.py @@ -25,7 +25,6 @@ from sqlalchemy.ext.compiler import compiles from sqlalchemy.sql import sqltypes -from pytest_mock_resources.fixture.credentials import assign_fixture_credentials from pytest_mock_resources.sqlalchemy import EngineManager @@ -261,16 +260,6 @@ def _(): ) for engine in engine_manager.manage_sync(): with filter_sqlalchemy_warnings(decimal_warnings_enabled=(not decimal_warnings)): - assign_fixture_credentials( - raw_engine, - drivername=driver_name, - host="", - port=None, - database=database_name, - username="", - password="", - ) - yield engine event.remove(raw_engine, "connect", enable_foreign_key_checks) diff --git a/src/pytest_mock_resources/sqlalchemy.py b/src/pytest_mock_resources/sqlalchemy.py index 84a37a55..8d88ab2b 100644 --- a/src/pytest_mock_resources/sqlalchemy.py +++ b/src/pytest_mock_resources/sqlalchemy.py @@ -12,6 +12,7 @@ from sqlalchemy.sql.schema import Table from pytest_mock_resources import compat +from pytest_mock_resources.credentials import Credentials log = logging.getLogger(__name__) @@ -136,6 +137,7 @@ def manage_sync(self): if self.actions_share_transaction is False: self.engine.dispose() + Credentials.assign_from_connection(session) yield session finally: session.close() @@ -147,6 +149,7 @@ def manage_sync(self): if self.actions_share_transaction is False: self.engine.dispose() + Credentials.assign_from_connection(self.engine) yield self.engine finally: @@ -173,6 +176,7 @@ async def manage_async(self, session=None): await session.commit() await session.close() + Credentials.assign_from_connection(engine.sync_engine) yield session else: async with engine.begin() as conn: @@ -182,6 +186,7 @@ async def manage_async(self, session=None): if not self.actions_share_transaction: await engine.dispose() + Credentials.assign_from_connection(engine.sync_engine) yield engine finally: await engine.dispose() diff --git a/tests/fixture/test_pmr_credentials.py b/tests/fixture/test_pmr_credentials.py new file mode 100644 index 00000000..795988de --- /dev/null +++ b/tests/fixture/test_pmr_credentials.py @@ -0,0 +1,121 @@ +import pytest +from sqlalchemy import create_engine, text + +from pytest_mock_resources import ( + create_mongo_fixture, + create_moto_fixture, + create_mysql_fixture, + create_postgres_fixture, + create_redis_fixture, + create_redshift_fixture, + create_sqlite_fixture, +) + +mongo = create_mongo_fixture() +moto = create_moto_fixture() +mysql = create_mysql_fixture() +mysql_session = create_mysql_fixture(session=True) +pg = create_postgres_fixture() +pg_session = create_postgres_fixture(session=True) +pg_async = create_postgres_fixture(async_=True) +pg_async_session = create_postgres_fixture(async_=True, session=True) +redis = create_redis_fixture() +redshift = create_redshift_fixture() +redshift_session = create_redshift_fixture(session=True) +redshift_async = create_redshift_fixture(async_=True) +redshift_async_session = create_redshift_fixture(async_=True, session=True) +sqlite = create_sqlite_fixture() +sqlite_session = create_sqlite_fixture(session=True) + + +def test_mongo_pmr_credentials(mongo): + assert mongo.pmr_credentials + + +def test_moto_pmr_credentials(moto, pmr_moto_credentials): + assert moto + assert pmr_moto_credentials.aws_access_key_id + assert pmr_moto_credentials.aws_secret_access_key + + +def test_mysql_pmr_credentials(mysql): + credentials = mysql.pmr_credentials + verify_relational(mysql, credentials) + + +def test_mysql_session_pmr_credentials(mysql_session): + credentials = mysql_session.pmr_credentials + verify_relational(mysql_session, credentials, session=True) + + +def test_postgres_pmr_credentials(pg): + credentials = pg.pmr_credentials + verify_relational(pg, credentials) + + +def test_postgres_session_pmr_credentials(pg_session): + credentials = pg_session.pmr_credentials + verify_relational(pg_session, credentials, session=True) + + +@pytest.mark.asyncio +async def test_postgres_async_pmr_credentials(pg_async): + assert pg_async.sync_engine.pmr_credentials + + +@pytest.mark.asyncio +async def test_postgres_async_session_pmr_credentials(pg_async_session): + assert (await pg_async_session.connection()).sync_engine.pmr_credentials + + +def test_redis_pmr_credentials(redis): + assert redis.pmr_credentials + + +def test_redshift_pmr_credentials(redshift): + credentials = redshift.pmr_credentials + verify_relational(redshift, credentials) + + +def test_redshift_session_pmr_credentials(redshift_session): + credentials = redshift_session.pmr_credentials + verify_relational(redshift_session, credentials, session=True) + + +@pytest.mark.asyncio +async def test_redshift_async_pmr_credentials(redshift_async): + assert redshift_async.sync_engine.pmr_credentials + + +@pytest.mark.asyncio +async def test_redshift_async_session_pmr_credentials(redshift_async_session): + assert (await redshift_async_session.connection()).sync_engine.pmr_credentials + + +def test_sqlite_pmr_credentials(sqlite): + assert sqlite.pmr_credentials + + +def test_sqlite_session_pmr_credentials(sqlite_session): + assert sqlite_session.pmr_credentials + + +def verify_relational(connection, credentials, session=False): + """Verify connection to the same database as the one given to the test function, using credentials.""" + assert credentials + + queries = [ + text("create table foo (id integer)"), + text("commit"), + ] + if not session: + with connection.begin() as conn: + for query in queries: + conn.execute(query) + else: + for query in queries: + connection.execute(query) + + manual_engine = create_engine(credentials.as_url()) + with manual_engine.connect() as conn: + conn.execute(text("select * from foo"))