diff options
Diffstat (limited to 'test_utils')
| -rw-r--r-- | test_utils/__init__.py | 3 | ||||
| -rw-r--r-- | test_utils/conftest.py | 178 | ||||
| -rw-r--r-- | test_utils/managers/conftest.py | 48 |
3 files changed, 209 insertions, 20 deletions
diff --git a/test_utils/__init__.py b/test_utils/__init__.py index e69de29..0c8e77a 100644 --- a/test_utils/__init__.py +++ b/test_utils/__init__.py @@ -0,0 +1,3 @@ +import os + +os.environ["DISABLE_PANDERA_IMPORT_WARNING"] = "True" diff --git a/test_utils/conftest.py b/test_utils/conftest.py index 0e712bb..232c1fc 100644 --- a/test_utils/conftest.py +++ b/test_utils/conftest.py @@ -1,16 +1,20 @@ import os import shutil +import sys +from datetime import datetime, timedelta, timezone from os.path import join as pjoin from pathlib import Path -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING, Callable, Generator from uuid import uuid4 -from datetime import datetime, timedelta, timezone +import django import pytest import redis from _pytest.config import Config +from django.conf import settings as django_settings +from django.core.management import call_command from dotenv import load_dotenv -from pydantic import MariaDBDsn +from pydantic import MariaDBDsn, PostgresDsn from redis import Redis from generalresearch.pg_helper import PostgresConfig @@ -26,12 +30,19 @@ if TYPE_CHECKING: @pytest.fixture(scope="session") def env_file_path(pytestconfig: Config) -> str: root_path = pytestconfig.rootpath - env_path = os.path.join(root_path, ".env.test") + env_file = ".env.test" - if os.path.exists(env_path): - load_dotenv(dotenv_path=env_path, override=True) + candidates = [ + os.path.join(root_path, env_file), + os.path.join(root_path, "..", env_file), + ] - return env_path + for env_path in candidates: + if os.path.exists(env_path): + load_dotenv(dotenv_path=env_path, override=True) + return os.path.normpath(env_path) + + raise AssertionError(f"No .env.test file found in: {', '.join(candidates)}") @pytest.fixture(scope="session") @@ -57,24 +68,137 @@ def settings(env_file_path: str) -> "GRLBaseSettings": @pytest.fixture(scope="session") -def thl_web_rr(settings: "GRLBaseSettings") -> PostgresConfig: - assert settings.thl_web_rr_db is not None - assert "/unittest-" in settings.thl_web_rr_db.path +def postgres_instance(settings: "GRLBaseSettings") -> Generator[PostgresDsn]: + """Create a ephemeral postgresql instance for us to use during pytest. + + This is simplified, and only based off a single host. We don't want to + create multiple migrated tmp databases for each rw/rr/ro connection + """ + + assert settings.thl_web_rw_db + # assert settings.thl_web_rw_db.host + + dsn: PostgresDsn = settings.thl_web_rw_db + + # Connect to default DB to create the new one + from psycopg import connect + from psycopg.sql import SQL, Identifier + + now = datetime.now(timezone.utc) + ts: str = now.strftime("%Y-%m-%d") + + db_name = f"unittest-{ts}-{uuid4().hex[:6]}" + print("XXX", str(dsn)) + conn = connect(str(dsn)) + conn.autocommit = True + cur = conn.cursor() + cur.execute(SQL("CREATE DATABASE {}").format(Identifier(db_name))) + cur.close() + conn.close() + + host = dsn.hosts()[0] + db_url = ( + f"postgres://{host['username']}:{host['password']}@{host['host']}/{db_name}" + ) + + yield PostgresDsn(db_url) + + # Teardown: drop the DB after the session + conn = connect(str(dsn)) + conn.autocommit = True + cur = conn.cursor() + # cur.execute(SQL("DROP DATABASE {}").format(Identifier(db_name))) + cur.close() + conn.close() + + +@pytest.fixture(scope="session") +def django_db_setup(settings: "GRLBaseSettings") -> Callable[..., None]: + + def _inner(): + + assert settings.thl_web_rw_db + dsn: PostgresDsn = settings.thl_web_rw_db + host = dsn.hosts()[0] + + # 1. Bootstrapping Django settings + if not django_settings.configured: + django_settings.configure( + DATABASES={ + "default": { + "ENGINE": "django.db.backends.postgresql", + # PostgresDsn stores path as "/dbname" + "NAME": str(dsn.path).lstrip("/"), + "USER": host["username"], + "PASSWORD": host["password"], + "HOST": host["host"], + "PORT": "5432", + } + }, + INSTALLED_APPS=[ + "django.contrib.postgres", + "django.contrib.contenttypes", + "generalresearch.thl_django", + ], + ) + django.setup() + + from django.apps import apps + + for model in apps.get_models(): + print(f"Discovered model: {model._meta.label}") + + # 2. Run migrations directly during fixture activation + call_command("migrate") + + return _inner + + +@pytest.fixture(scope="session") +def thl_web_rr( + settings: "GRLBaseSettings", postgres_instance: PostgresDsn, django_db_setup +) -> PostgresConfig: + dsn = settings.thl_web_rr_db + assert dsn + assert dsn.path + + if dsn.path not in ["/", "/postgres"]: + assert "/unittest-" in dsn.path + + db_path = postgres_instance.path + host = dsn.hosts()[0] + db_url = f"postgres://{host['username']}:{host['password']}@{host['host']}{db_path}" + + # Run Migrations now. + django_db_setup() return PostgresConfig( - dsn=settings.thl_web_rr_db, + dsn=PostgresDsn(db_url), connect_timeout=1, statement_timeout=5, ) @pytest.fixture(scope="session") -def thl_web_rw(settings: "GRLBaseSettings") -> PostgresConfig: - assert settings.thl_web_rw_db is not None - assert "/unittest-" in settings.thl_web_rw_db.path +def thl_web_rw( + settings: "GRLBaseSettings", postgres_instance: PostgresDsn, django_db_setup +) -> PostgresConfig: + dsn = settings.thl_web_rw_db + assert dsn + assert dsn.path + + if dsn.path not in ["/", "/postgres"]: + assert "/unittest-" in dsn.path + + db_path = postgres_instance.path + host = dsn.hosts()[0] + db_url = f"postgres://{host['username']}:{host['password']}@{host['host']}{db_path}" + + # Run Migrations now. + django_db_setup() return PostgresConfig( - dsn=settings.thl_web_rw_db, + dsn=PostgresDsn(db_url), connect_timeout=1, statement_timeout=5, ) @@ -82,14 +206,24 @@ def thl_web_rw(settings: "GRLBaseSettings") -> PostgresConfig: @pytest.fixture(scope="session") def gr_db(settings: "GRLBaseSettings") -> PostgresConfig: - assert "/unittest-" in settings.gr_db.path + dsn = settings.gr_db + assert dsn + assert dsn.path + + if dsn.path not in ["/", "/postgres"]: + assert "/unittest-" in dsn.path + return PostgresConfig(dsn=settings.gr_db, connect_timeout=5, statement_timeout=2) @pytest.fixture(scope="session") def spectrum_rw(settings: "GRLBaseSettings") -> SqlHelper: - assert settings.spectrum_rw_db is not None - assert "/unittest-" in settings.spectrum_rw_db.path + dsn = settings.spectrum_rw_db + assert dsn + assert dsn.path + + if dsn.path not in ["/", "/postgres"]: + assert "/unittest-" in dsn.path return SqlHelper( dsn=settings.spectrum_rw_db, @@ -101,8 +235,12 @@ def spectrum_rw(settings: "GRLBaseSettings") -> SqlHelper: @pytest.fixture(scope="session") def grliq_db(settings: "GRLBaseSettings") -> PostgresConfig: - assert settings.grliq_db is not None - assert "/unittest-" in settings.grliq_db.path + dsn = settings.grliq_db + assert dsn + assert dsn.path + + if dsn.path not in ["/", "/postgres"]: + assert "/unittest-" in dsn.path # test_words = {"localhost", "127.0.0.1", "unittest", "grliq-test"} # assert any(w in str(postgres_config.dsn) for w in test_words), "check grliq postgres_config" diff --git a/test_utils/managers/conftest.py b/test_utils/managers/conftest.py index 10ee8ea..c8a6e2f 100644 --- a/test_utils/managers/conftest.py +++ b/test_utils/managers/conftest.py @@ -91,6 +91,7 @@ if TYPE_CHECKING: def ltxm( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "LedgerTransactionManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ledger_manager.ledger import ( @@ -109,6 +110,7 @@ def ltxm( def lam( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "LedgerAccountManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ledger_manager.ledger import ( @@ -125,6 +127,7 @@ def lam( @pytest.fixture(scope="session") def lm(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig) -> "LedgerManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ledger_manager.ledger import ( @@ -148,6 +151,7 @@ def lm(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig) -> "LedgerMana def thl_lm( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "ThlLedgerManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ledger_manager.thl_ledger import ( @@ -171,6 +175,7 @@ def thl_lm( def payout_event_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "PayoutEventManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.payout import PayoutEventManager @@ -186,6 +191,7 @@ def payout_event_manager( def user_payout_event_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "UserPayoutEventManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.payout import UserPayoutEventManager @@ -201,6 +207,7 @@ def user_payout_event_manager( def brokerage_product_payout_event_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "BrokerageProductPayoutEventManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.payout import ( @@ -218,6 +225,7 @@ def brokerage_product_payout_event_manager( def business_payout_event_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "BusinessPayoutEventManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.payout import ( @@ -233,6 +241,8 @@ def business_payout_event_manager( @pytest.fixture(scope="session") def product_manager(thl_web_rw: PostgresConfig) -> "ProductManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.product import ProductManager @@ -244,6 +254,10 @@ def product_manager(thl_web_rw: PostgresConfig) -> "ProductManager": def user_manager( settings: "GRLBaseSettings", thl_web_rw: PostgresConfig, thl_web_rr: PostgresConfig ) -> "UserManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path + assert thl_web_rr.dsn + assert thl_web_rr.dsn.path assert "/unittest-" in thl_web_rw.dsn.path assert "/unittest-" in thl_web_rr.dsn.path @@ -260,6 +274,8 @@ def user_manager( @pytest.fixture(scope="session") def user_metadata_manager(thl_web_rw: PostgresConfig) -> "UserMetadataManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.user_manager.user_metadata_manager import ( @@ -271,6 +287,8 @@ def user_metadata_manager(thl_web_rw: PostgresConfig) -> "UserMetadataManager": @pytest.fixture(scope="session") def session_manager(thl_web_rw: PostgresConfig) -> "SessionManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.session import SessionManager @@ -280,6 +298,8 @@ def session_manager(thl_web_rw: PostgresConfig) -> "SessionManager": @pytest.fixture(scope="session") def wall_manager(thl_web_rw: PostgresConfig) -> "WallManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.wall import WallManager @@ -311,6 +331,8 @@ def task_adjustment_manager(thl_web_rw: PostgresConfig) -> "TaskAdjustmentManage @pytest.fixture(scope="session") def contest_manager(thl_web_rw: PostgresConfig) -> "ContestManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.contest_manager import ContestManager @@ -328,6 +350,8 @@ def contest_manager(thl_web_rw: PostgresConfig) -> "ContestManager": @pytest.fixture(scope="session") def category_manager(thl_web_rw: PostgresConfig) -> "CategoryManager": + assert thl_web_rw.dsn + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.category import CategoryManager @@ -367,6 +391,7 @@ def surveypenalty_manager(thl_redis_config: RedisConfig): @pytest.fixture(scope="session") def upk_schema_manager(thl_web_rw: PostgresConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.profiling.schema import ( UpkSchemaManager, @@ -377,6 +402,7 @@ def upk_schema_manager(thl_web_rw: PostgresConfig): @pytest.fixture(scope="session") def user_upk_manager(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.profiling.user_upk import ( UserUpkManager, @@ -387,6 +413,7 @@ def user_upk_manager(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig): @pytest.fixture(scope="session") def question_manager(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.profiling.question import ( QuestionManager, @@ -397,6 +424,7 @@ def question_manager(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig): @pytest.fixture(scope="session") def uqa_manager(thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.profiling.uqa import UQAManager @@ -414,6 +442,7 @@ def uqa_manager_clear_cache(uqa_manager, user: "User"): @pytest.fixture(scope="session") def audit_log_manager(thl_web_rw: PostgresConfig) -> "AuditLogManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.userhealth import AuditLogManager @@ -423,6 +452,7 @@ def audit_log_manager(thl_web_rw: PostgresConfig) -> "AuditLogManager": @pytest.fixture(scope="session") def ip_geoname_manager(thl_web_rw: PostgresConfig) -> "IPGeonameManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ipinfo import IPGeonameManager @@ -432,6 +462,7 @@ def ip_geoname_manager(thl_web_rw: PostgresConfig) -> "IPGeonameManager": @pytest.fixture(scope="session") def ip_information_manager(thl_web_rw: PostgresConfig) -> "IPInformationManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ipinfo import IPInformationManager @@ -443,6 +474,7 @@ def ip_information_manager(thl_web_rw: PostgresConfig) -> "IPInformationManager" def ip_record_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "IPRecordManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.userhealth import IPRecordManager @@ -454,6 +486,7 @@ def ip_record_manager( def user_iphistory_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "UserIpHistoryManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.userhealth import ( @@ -476,6 +509,7 @@ def user_iphistory_manager_clear_cache(user_iphistory_manager, user): def geoipinfo_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig ) -> "GeoIpInfoManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.ipinfo import GeoIpInfoManager @@ -502,6 +536,7 @@ def maxmind_manager( thl_web_rw: PostgresConfig, thl_redis_config: RedisConfig, ) -> "MaxmindManager": + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.maxmind import MaxmindManager @@ -516,6 +551,7 @@ def maxmind_manager( @pytest.fixture(scope="session") def cashout_method_manager(thl_web_rw: PostgresConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.cashout_method import ( CashoutMethodManager, @@ -533,6 +569,7 @@ def event_manager(thl_redis_config: RedisConfig): @pytest.fixture(scope="session") def user_streak_manager(thl_web_rw: PostgresConfig): + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path from generalresearch.managers.thl.user_streak import ( UserStreakManager, @@ -545,6 +582,7 @@ def user_streak_manager(thl_web_rw: PostgresConfig): def uqa_db_index(thl_web_rw: PostgresConfig): # There were some custom indices created not through django. # Make sure the index used in the index hint exists + assert thl_web_rw.dsn.path assert "/unittest-" in thl_web_rw.dsn.path # query = f"""create index idx_user_id @@ -605,6 +643,7 @@ def business_manager( ) -> "BusinessManager": from generalresearch.redis_helper import RedisConfig + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path assert isinstance(gr_redis_config, RedisConfig) @@ -618,6 +657,7 @@ def business_manager( @pytest.fixture(scope="session") def business_address_manager(gr_db: PostgresConfig) -> "BusinessAddressManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.business import BusinessAddressManager @@ -629,6 +669,7 @@ def business_address_manager(gr_db: PostgresConfig) -> "BusinessAddressManager": def business_bank_account_manager( gr_db: PostgresConfig, ) -> "BusinessBankAccountManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.business import ( @@ -640,6 +681,7 @@ def business_bank_account_manager( @pytest.fixture(scope="session") def team_manager(gr_db: PostgresConfig, gr_redis_config: RedisConfig) -> "TeamManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.team import TeamManager @@ -649,6 +691,7 @@ def team_manager(gr_db: PostgresConfig, gr_redis_config: RedisConfig) -> "TeamMa @pytest.fixture(scope="session") def gr_um(gr_db: PostgresConfig, gr_redis_config: RedisConfig) -> "GRUserManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.authentication import GRUserManager @@ -658,6 +701,7 @@ def gr_um(gr_db: PostgresConfig, gr_redis_config: RedisConfig) -> "GRUserManager @pytest.fixture(scope="session") def gr_tm(gr_db: PostgresConfig) -> "GRTokenManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.authentication import GRTokenManager @@ -667,6 +711,7 @@ def gr_tm(gr_db: PostgresConfig) -> "GRTokenManager": @pytest.fixture(scope="session") def membership_manager(gr_db: PostgresConfig) -> "MembershipManager": + assert gr_db.dsn.path assert "/unittest-" in gr_db.dsn.path from generalresearch.managers.gr.team import MembershipManager @@ -679,6 +724,7 @@ def membership_manager(gr_db: PostgresConfig) -> "MembershipManager": @pytest.fixture(scope="session") def grliq_dm(grliq_db: PostgresConfig) -> "GrlIqDataManager": + assert grliq_db.dsn.path assert "/unittest-" in grliq_db.dsn.path from generalresearch.grliq.managers.forensic_data import ( @@ -690,6 +736,7 @@ def grliq_dm(grliq_db: PostgresConfig) -> "GrlIqDataManager": @pytest.fixture(scope="session") def grliq_em(grliq_db: PostgresConfig) -> "GrlIqEventManager": + assert grliq_db.dsn.path assert "/unittest-" in grliq_db.dsn.path from generalresearch.grliq.managers.forensic_events import ( @@ -701,6 +748,7 @@ def grliq_em(grliq_db: PostgresConfig) -> "GrlIqEventManager": @pytest.fixture(scope="session") def grliq_crr(grliq_db: PostgresConfig) -> "GrlIqCategoryResultsReader": + assert grliq_db.dsn.path assert "/unittest-" in grliq_db.dsn.path from generalresearch.grliq.managers.forensic_results import ( |
