Crypto Rug Muncher
feat(t17+t21+t45): Infisical + integration tests + backup verification
4295a74
Raw
History Blame Contribute Delete
4.28 kB
"""Integration test fixtures using real DBs in containers.
Per v4.0 §T21. Mocks prove the code compiles — real DBs prove it works.
"""
import pytest
import pytest_asyncio
@pytest.fixture(scope="session")
def postgres_container():
from testcontainers.postgres import PostgresContainer
pg = PostgresContainer("postgres:16-alpine")
pg.start()
yield pg
pg.stop()
@pytest_asyncio.fixture
async def pg_conn(postgres_container):
import asyncpg
url = postgres_container.get_connection_url()
if url.startswith("postgresql+psycopg2://"):
url = "postgresql://" + url[len("postgresql+psycopg2://"):]
conn = await asyncpg.connect(url)
await _init_pg_schema(conn)
try:
yield conn
finally:
await conn.close()
async def _init_pg_schema(conn) -> None:
await conn.execute("""
CREATE TABLE IF NOT EXISTS tokens (
token_id TEXT PRIMARY KEY,
chain TEXT NOT NULL,
address TEXT NOT NULL,
symbol TEXT,
name TEXT,
decimals INT DEFAULT 18,
deployer_wallet_id TEXT,
deployed_at TIMESTAMPTZ DEFAULT NOW(),
initial_supply BIGINT,
current_supply BIGINT,
is_honeypot BOOLEAN,
is_mintable BOOLEAN,
is_proxy BOOLEAN,
tax_buy_bps INT,
tax_sell_bps INT,
risk_tier TEXT,
risk_score INT,
risk_factors JSONB DEFAULT '[]',
rag_embedding_id TEXT,
UNIQUE(chain, address)
);
CREATE TABLE IF NOT EXISTS wallets (
wallet_id TEXT PRIMARY KEY,
chain TEXT NOT NULL,
address TEXT NOT NULL,
first_seen TIMESTAMPTZ DEFAULT NOW(),
last_seen TIMESTAMPTZ DEFAULT NOW(),
tx_count INT DEFAULT 0,
total_volume_usd DOUBLE PRECISION DEFAULT 0.0,
is_deployer BOOLEAN DEFAULT FALSE,
reputation_score INT
);
CREATE TABLE IF NOT EXISTS news_items (
news_id TEXT PRIMARY KEY,
url TEXT NOT NULL,
title TEXT NOT NULL,
summary TEXT,
published_at TIMESTAMPTZ DEFAULT NOW(),
ingested_at TIMESTAMPTZ DEFAULT NOW(),
source TEXT,
sentiment_score DOUBLE PRECISION,
body_markdown TEXT,
chains_mentioned JSONB DEFAULT '[]',
tokens_mentioned JSONB DEFAULT '[]',
wallets_mentioned JSONB DEFAULT '[]',
ai_analysis TEXT
);
CREATE TABLE IF NOT EXISTS scan_reports (
report_id TEXT PRIMARY KEY,
subject_type TEXT NOT NULL,
subject_id TEXT NOT NULL,
generated_at TIMESTAMPTZ DEFAULT NOW(),
generated_by_model TEXT,
risk_score INT,
risk_tier TEXT,
markdown_url TEXT
);
""")
@pytest.fixture(scope="session")
def redis_container():
from testcontainers.redis import RedisContainer
r = RedisContainer("redis:7-alpine")
r.start()
yield r
r.stop()
@pytest_asyncio.fixture
async def redis_client(redis_container):
import redis.asyncio as aioredis
try:
url = redis_container.get_connection_url()
except AttributeError:
host = redis_container.get_container_host_ip()
port = redis_container.get_exposed_port(6379)
url = f"redis://{host}:{port}"
client = aioredis.from_url(url)
try:
yield client
finally:
try:
await client.flushdb()
except Exception:
pass
await client.aclose()
@pytest.fixture(scope="session")
def neo4j_container():
from testcontainers.neo4j import Neo4jContainer
n = Neo4jContainer("neo4j:5")
n.start()
yield n
n.stop()
@pytest_asyncio.fixture
async def neo4j_driver(neo4j_container):
from neo4j import AsyncGraphDatabase
# testcontainers Neo4jContainer exposes `.password` attribute
password = getattr(neo4j_container, "password", "admin")
uri = neo4j_container.get_connection_url()
driver = AsyncGraphDatabase.driver(uri, auth=("neo4j", password))
try:
yield driver
finally:
await driver.close()