You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
stock-oracle/tests/test_final_verification.py

300 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Final verification test for 15-year financial data fixes
Tests all the key improvements made to resolve the issues
"""
import requests
import json
from datetime import datetime
from typing import Dict, Any
# API configuration
API_URL = "http://localhost:18001/api/v1"
def test_database_cleanup():
"""Test database cleanup functionality"""
print("🧹 Testing database cleanup...")
response = requests.post(f"{API_URL}/database/cleanup/duplicates")
if response.status_code == 200:
print(" ✅ Database cleanup successful")
return True
else:
print(f" ❌ Database cleanup failed: {response.status_code}")
return False
def test_multiple_tickers_quarterly():
"""Test quarterly data for multiple tickers"""
print("\n📊 Testing quarterly data for multiple tickers...")
tickers = ["AAPL", "MSFT", "GOOGL"]
results = {}
for ticker in tickers:
request_data = {
"ticker": ticker,
"start_date": "2023-01-01",
"end_date": "2024-12-31",
"period_type": "quarterly",
"include_metrics": True,
"force_refresh": False
}
try:
response = requests.post(f"{API_URL}/financial/data", json=request_data, timeout=30)
if response.status_code == 200:
data = response.json()
financial_data = data.get('financial_data', [])
results[ticker] = {
'success': True,
'records': len(financial_data),
'real_data': sum(1 for d in financial_data if not d.get('is_estimated', True))
}
print(f"{ticker}: {len(financial_data)} records, {results[ticker]['real_data']} real data")
else:
results[ticker] = {'success': False, 'error': response.status_code}
print(f"{ticker}: Failed with {response.status_code}")
except Exception as e:
results[ticker] = {'success': False, 'error': str(e)}
print(f"{ticker}: Exception - {str(e)}")
success_count = sum(1 for r in results.values() if r.get('success', False))
print(f" 📊 Summary: {success_count}/{len(tickers)} tickers successful")
return success_count == len(tickers)
def test_historical_data_range():
"""Test historical data requests with different ranges"""
print("\n🕰️ Testing historical data ranges...")
test_cases = [
{
"name": "3-year quarterly",
"ticker": "AAPL",
"start_date": "2022-01-01",
"end_date": "2024-12-31",
"period_type": "quarterly",
"expected_min": 8 # At least 8 quarters
},
{
"name": "5-year annual",
"ticker": "AAPL",
"start_date": "2020-01-01",
"end_date": "2024-12-31",
"period_type": "annual",
"expected_min": 4 # At least 4 years (yfinance_plus limitation)
},
{
"name": "15-year annual (auto-switch)",
"ticker": "MSFT",
"start_date": "2009-01-01",
"end_date": "2024-12-31",
"period_type": "annual",
"expected_min": 3 # At least 3 years due to yfinance_plus limitations
}
]
results = []
for test_case in test_cases:
print(f" 🔍 Testing {test_case['name']}...")
request_data = {
"ticker": test_case["ticker"],
"start_date": test_case["start_date"],
"end_date": test_case["end_date"],
"period_type": test_case["period_type"],
"include_metrics": True,
"force_refresh": True
}
try:
response = requests.post(f"{API_URL}/financial/data", json=request_data, timeout=60)
if response.status_code == 200:
data = response.json()
financial_data = data.get('financial_data', [])
if len(financial_data) >= test_case["expected_min"]:
print(f" ✅ Success: {len(financial_data)} records (expected ≥{test_case['expected_min']})")
# Check data quality
real_data = sum(1 for d in financial_data if not d.get('is_estimated', True))
years_covered = set()
for d in financial_data:
year = d.get('period_date', '')[:4]
years_covered.add(year)
print(f" 📈 Real data: {real_data}/{len(financial_data)}")
print(f" 📅 Years: {sorted(years_covered)}")
results.append(True)
else:
print(f" ❌ Insufficient data: {len(financial_data)} < {test_case['expected_min']}")
results.append(False)
else:
print(f" ❌ Request failed: {response.status_code}")
results.append(False)
except Exception as e:
print(f" ❌ Exception: {str(e)}")
results.append(False)
success_count = sum(results)
print(f" 📊 Summary: {success_count}/{len(test_cases)} test cases passed")
return success_count == len(test_cases)
def test_performance_improvements():
"""Test performance and caching"""
print("\n⚡ Testing performance improvements...")
ticker = "GOOGL"
request_data = {
"ticker": ticker,
"start_date": "2023-01-01",
"end_date": "2024-12-31",
"period_type": "quarterly",
"include_metrics": True
}
# Test cache usage (should be fast)
print(" 🔄 Testing cache usage...")
start_time = datetime.now()
request_data["force_refresh"] = False
response1 = requests.post(f"{API_URL}/financial/data", json=request_data, timeout=30)
cache_time = (datetime.now() - start_time).total_seconds()
if response1.status_code == 200:
data1 = response1.json()
print(f" ✅ Cache request: {len(data1.get('financial_data', []))} records in {cache_time:.1f}s")
cache_success = True
else:
print(f" ❌ Cache request failed: {response1.status_code}")
cache_success = False
# Test force refresh (should work but be slower)
print(" 🔄 Testing force refresh...")
start_time = datetime.now()
request_data["force_refresh"] = True
response2 = requests.post(f"{API_URL}/financial/data", json=request_data, timeout=60)
refresh_time = (datetime.now() - start_time).total_seconds()
if response2.status_code == 200:
data2 = response2.json()
print(f" ✅ Refresh request: {len(data2.get('financial_data', []))} records in {refresh_time:.1f}s")
refresh_success = True
# Performance comparison
if cache_success and refresh_time > cache_time:
speed_diff = refresh_time / cache_time if cache_time > 0 else 1
print(f" ⚡ Performance: Cache {speed_diff:.1f}x faster than refresh")
else:
print(f" ❌ Refresh request failed: {response2.status_code}")
refresh_success = False
return cache_success and refresh_success
def test_error_handling():
"""Test error handling and validation"""
print("\n🚨 Testing error handling...")
error_tests = [
{
"name": "Invalid ticker",
"data": {"ticker": "INVALID", "start_date": "2023-01-01", "end_date": "2023-12-31", "period_type": "quarterly"},
"expected_codes": [422, 400]
},
{
"name": "Future dates",
"data": {"ticker": "AAPL", "start_date": "2030-01-01", "end_date": "2030-12-31", "period_type": "quarterly"},
"expected_codes": [400]
},
{
"name": "Very old dates",
"data": {"ticker": "AAPL", "start_date": "1990-01-01", "end_date": "1990-12-31", "period_type": "quarterly"},
"expected_codes": [400]
}
]
results = []
for test in error_tests:
try:
response = requests.post(f"{API_URL}/financial/data", json=test["data"], timeout=30)
if response.status_code in test["expected_codes"]:
print(f"{test['name']}: Properly handled ({response.status_code})")
results.append(True)
else:
print(f"{test['name']}: Unexpected response ({response.status_code})")
results.append(False)
except Exception as e:
print(f"{test['name']}: Exception - {str(e)}")
results.append(False)
success_count = sum(results)
print(f" 📊 Summary: {success_count}/{len(error_tests)} error cases handled correctly")
return success_count == len(error_tests)
def main():
"""Run all verification tests"""
print("🔧 Stock Oracle 15-Year Financial Data Fix Verification")
print("=" * 70)
print(f"🚀 Test started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"🎯 API URL: {API_URL}")
# Run all tests
tests = [
("Database Cleanup", test_database_cleanup),
("Multiple Tickers Quarterly", test_multiple_tickers_quarterly),
("Historical Data Range", test_historical_data_range),
("Performance Improvements", test_performance_improvements),
("Error Handling", test_error_handling),
]
results = []
for test_name, test_func in tests:
print(f"\n{'='*70}")
print(f"🔍 {test_name}")
print('='*70)
try:
result = test_func()
results.append((test_name, "PASS" if result else "FAIL"))
except Exception as e:
print(f"{test_name} threw exception: {str(e)}")
results.append((test_name, "ERROR"))
# Final summary
print(f"\n{'='*70}")
print("📋 FINAL TEST RESULTS")
print('='*70)
for test_name, result in results:
icon = "" if result == "PASS" else ""
print(f"{icon} {test_name}: {result}")
pass_count = sum(1 for _, result in results if result == "PASS")
total_count = len(results)
print(f"\n📊 Overall Result: {pass_count}/{total_count} tests passed ({pass_count/total_count*100:.1f}%)")
print(f"🕐 Test completed: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if pass_count == total_count:
print("\n🎉 ALL TESTS PASSED! 15-year financial data fixes are working correctly.")
else:
print(f"\n⚠️ {total_count - pass_count} tests failed. Some issues may remain.")
if __name__ == "__main__":
main()