test: improve test coverage from 61% to 84.81%

Major improvements:
- Fixed all 42 broken tests (database connection leaks)
- Added db_connection() context manager for proper cleanup
- Created comprehensive test suites for undertested modules

New test coverage:
- tools/general_tools.py: 26 tests (97% coverage)
- tools/price_tools.py: 11 tests (validates NASDAQ symbols, date handling)
- api/price_data_manager.py: 12 tests (85% coverage)
- api/routes/results_v2.py: 3 tests (98% coverage)
- agent/reasoning_summarizer.py: 2 tests (87% coverage)
- api/routes/period_metrics.py: 2 edge case tests (100% coverage)
- agent/mock_provider: 1 test (100% coverage)

Database fixes:
- Added db_connection() context manager to prevent leaks
- Updated 16+ test files to use context managers
- Fixed drop_all_tables() to match new schema
- Added CHECK constraint for action_type
- Added ON DELETE CASCADE to trading_days foreign key

Test improvements:
- Updated SQL INSERT statements with all required fields
- Fixed date parameter handling in API integration tests
- Added edge case tests for validation functions
- Fixed import errors across test suite

Results:
- Total coverage: 84.81% (was 61%)
- Tests passing: 406 (was 364 with 42 failures)
- Total lines covered: 6364 of 7504

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-07 21:02:38 -05:00
parent 61baf3f90f
commit 14cf88f642
30 changed files with 1840 additions and 1013 deletions

View File

@@ -10,6 +10,7 @@ This module provides:
import sqlite3
from pathlib import Path
import os
from contextlib import contextmanager
from tools.deployment_config import get_db_path
@@ -44,6 +45,37 @@ def get_db_connection(db_path: str = "data/jobs.db") -> sqlite3.Connection:
return conn
@contextmanager
def db_connection(db_path: str = "data/jobs.db"):
"""
Context manager for database connections with guaranteed cleanup.
Ensures connections are properly closed even when exceptions occur.
Recommended for all test code to prevent connection leaks.
Usage:
with db_connection(db_path) as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM jobs")
conn.commit()
Args:
db_path: Path to SQLite database file
Yields:
sqlite3.Connection: Configured database connection
Note:
Connection is automatically closed in finally block.
Uncommitted transactions are rolled back on exception.
"""
conn = get_db_connection(db_path)
try:
yield conn
finally:
conn.close()
def resolve_db_path(db_path: str) -> str:
"""
Resolve database path based on deployment mode
@@ -431,10 +463,9 @@ def drop_all_tables(db_path: str = "data/jobs.db") -> None:
tables = [
'tool_usage',
'reasoning_logs',
'trading_sessions',
'actions',
'holdings',
'positions',
'trading_days',
'simulation_runs',
'job_details',
'jobs',
@@ -494,7 +525,7 @@ def get_database_stats(db_path: str = "data/jobs.db") -> dict:
stats["database_size_mb"] = 0
# Get row counts for each table
tables = ['jobs', 'job_details', 'positions', 'holdings', 'trading_sessions', 'reasoning_logs',
tables = ['jobs', 'job_details', 'trading_days', 'holdings', 'actions',
'tool_usage', 'price_data', 'price_data_coverage', 'simulation_runs']
for table in tables:

View File

@@ -66,7 +66,7 @@ def create_trading_days_schema(db: "Database") -> None:
completed_at TIMESTAMP,
UNIQUE(job_id, model, date),
FOREIGN KEY (job_id) REFERENCES jobs(job_id)
FOREIGN KEY (job_id) REFERENCES jobs(job_id) ON DELETE CASCADE
)
""")
@@ -101,7 +101,7 @@ def create_trading_days_schema(db: "Database") -> None:
id INTEGER PRIMARY KEY AUTOINCREMENT,
trading_day_id INTEGER NOT NULL,
action_type TEXT NOT NULL,
action_type TEXT NOT NULL CHECK(action_type IN ('buy', 'sell', 'hold')),
symbol TEXT,
quantity INTEGER,
price REAL,