Files
LEDMatrix/test/test_sports_integration.py
Chuck ad8a652183 Fix leaderboard scrolling performance after PR #39 merge (#63)
* Fix leaderboard scrolling performance after PR #39 merge

- Restore leaderboard background updates that were accidentally removed
- Fix duration method call from get_dynamic_duration() back to get_duration()
- Restore proper fallback duration (600s instead of 60s) for leaderboard
- Add back sports manager updates that feed data to leaderboard
- Fix leaderboard defer_update priority to prevent scrolling lag

These changes restore the leaderboard's dynamic duration calculation
and ensure it gets proper background updates for smooth scrolling.

* Apply PR #60 leaderboard performance optimizations

- Change scroll_delay from 0.05s to 0.01s (100fps instead of 20fps)
- Remove conditional scrolling logic - scroll every frame for smooth animation
- Add FPS tracking and logging for performance monitoring
- Restore high-framerate scrolling that was working before PR #39 merge

These changes restore the smooth leaderboard scrolling performance
that was achieved in PR #60 but was lost during the PR #39 merge.

* Fix critical bugs identified in PR #39 review

- Fix record filtering logic bug: change away_record == set to away_record in set
- Fix incorrect sport specification: change 'nfl' to 'ncaa_fb' for NCAA Football data requests
- These bugs were causing incorrect data display and wrong sport data fetching

Addresses issues found by cursor bot in PR #39 review:
- Record filtering was always evaluating to False
- NCAA Football was fetching NFL data instead of college football data

* Enhance cache clearing implementation from PR #39

- Add detailed logging to cache clearing process for better visibility
- Log cache clearing statistics (memory entries and file count)
- Improve startup logging to show cache clearing and data refetch process
- Addresses legoguy1000's comment about preventing stale data issues

This enhances the cache clearing implementation that was added in PR #39
to help prevent legacy cache issues and stale data problems.

* continuing on base_classes - added baseball and api extractor since we don't use ESPN api for all sports

* tests

* fix missing duration

* ensure milb, mlb, ncaa bb are all using new baseball base class properly

* cursor rule to help with PR creation

* fix image call

* fix _scoreboard suffix on milb, MLB
2025-09-25 09:34:20 -04:00

271 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test Sports Integration
This test validates that all sports work together with the new architecture
and that the system can handle multiple sports simultaneously.
"""
import sys
import os
import logging
from typing import Dict, Any, List
# Add src to path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
def test_all_sports_configuration():
"""Test that all sports have valid configurations."""
print("🧪 Testing All Sports Configuration...")
try:
from src.base_classes.sport_configs import get_sport_configs, get_sport_config
# Get all sport configurations
configs = get_sport_configs()
all_sports = list(configs.keys())
print(f"✅ Found {len(all_sports)} sports: {all_sports}")
# Test each sport
for sport_key in all_sports:
config = get_sport_config(sport_key, None)
# Validate basic configuration
assert config.update_cadence in ['daily', 'weekly', 'hourly', 'live_only']
assert config.season_length > 0
assert config.games_per_week > 0
assert config.data_source_type in ['espn', 'mlb_api', 'soccer_api']
assert len(config.sport_specific_fields) > 0
print(f"{sport_key}: {config.update_cadence}, {config.season_length} games, {config.data_source_type}")
print("✅ All sports have valid configurations")
return True
except Exception as e:
print(f"❌ All sports configuration test failed: {e}")
return False
def test_sports_api_extractors():
"""Test that all sports have working API extractors."""
print("\n🧪 Testing All Sports API Extractors...")
try:
from src.base_classes.api_extractors import get_extractor_for_sport
logger = logging.getLogger('test')
# Test all sports
sports_to_test = ['nfl', 'ncaa_fb', 'mlb', 'nhl', 'ncaam_hockey', 'soccer', 'nba']
for sport_key in sports_to_test:
extractor = get_extractor_for_sport(sport_key, logger)
print(f"{sport_key} extractor: {type(extractor).__name__}")
# Test that extractor has required methods
assert hasattr(extractor, 'extract_game_details')
assert hasattr(extractor, 'get_sport_specific_fields')
assert callable(extractor.extract_game_details)
assert callable(extractor.get_sport_specific_fields)
print("✅ All sports have working API extractors")
return True
except Exception as e:
print(f"❌ Sports API extractors test failed: {e}")
return False
def test_sports_data_sources():
"""Test that all sports have working data sources."""
print("\n🧪 Testing All Sports Data Sources...")
try:
from src.base_classes.data_sources import get_data_source_for_sport
from src.base_classes.sport_configs import get_sport_config
logger = logging.getLogger('test')
# Test all sports
sports_to_test = ['nfl', 'ncaa_fb', 'mlb', 'nhl', 'ncaam_hockey', 'soccer', 'nba']
for sport_key in sports_to_test:
# Get sport configuration to determine data source type
config = get_sport_config(sport_key, None)
data_source_type = config.data_source_type
# Get data source
data_source = get_data_source_for_sport(sport_key, data_source_type, logger)
print(f"{sport_key} data source: {type(data_source).__name__} ({data_source_type})")
# Test that data source has required methods
assert hasattr(data_source, 'fetch_live_games')
assert hasattr(data_source, 'fetch_schedule')
assert hasattr(data_source, 'fetch_standings')
assert callable(data_source.fetch_live_games)
assert callable(data_source.fetch_schedule)
assert callable(data_source.fetch_standings)
print("✅ All sports have working data sources")
return True
except Exception as e:
print(f"❌ Sports data sources test failed: {e}")
return False
def test_sports_consistency():
"""Test that sports configurations are consistent and logical."""
print("\n🧪 Testing Sports Consistency...")
try:
from src.base_classes.sport_configs import get_sport_config
# Test that each sport has logical configuration
sports_to_test = ['nfl', 'ncaa_fb', 'mlb', 'nhl', 'ncaam_hockey', 'soccer', 'nba']
for sport_key in sports_to_test:
config = get_sport_config(sport_key, None)
# Test update cadence makes sense for season length
if config.season_length > 100: # Long season (MLB, NBA, NHL)
assert config.update_cadence in ['daily', 'hourly'], f"{sport_key} should have frequent updates for long season"
elif config.season_length < 20: # Short season (NFL, NCAA)
assert config.update_cadence in ['weekly', 'daily'], f"{sport_key} should have less frequent updates for short season"
# Test that games per week makes sense
assert config.games_per_week > 0, f"{sport_key} should have at least 1 game per week"
assert config.games_per_week <= 7, f"{sport_key} should not have more than 7 games per week"
# Test that season length is reasonable
assert config.season_length > 0, f"{sport_key} should have positive season length"
assert config.season_length < 200, f"{sport_key} season length seems too long"
print(f"{sport_key} configuration is consistent")
print("✅ All sports configurations are consistent")
return True
except Exception as e:
print(f"❌ Sports consistency test failed: {e}")
return False
def test_sports_uniqueness():
"""Test that each sport has unique characteristics."""
print("\n🧪 Testing Sports Uniqueness...")
try:
from src.base_classes.sport_configs import get_sport_config
# Test that each sport has unique sport-specific fields
sports_to_test = ['nfl', 'mlb', 'nhl', 'soccer']
sport_fields = {}
for sport_key in sports_to_test:
config = get_sport_config(sport_key, None)
sport_fields[sport_key] = set(config.sport_specific_fields)
# Test that each sport has unique fields
for sport_key in sports_to_test:
current_fields = sport_fields[sport_key]
# Check that sport has unique fields
if sport_key == 'nfl':
assert 'down' in current_fields, "NFL should have down field"
assert 'distance' in current_fields, "NFL should have distance field"
assert 'possession' in current_fields, "NFL should have possession field"
elif sport_key == 'mlb':
assert 'inning' in current_fields, "MLB should have inning field"
assert 'outs' in current_fields, "MLB should have outs field"
assert 'bases' in current_fields, "MLB should have bases field"
assert 'strikes' in current_fields, "MLB should have strikes field"
assert 'balls' in current_fields, "MLB should have balls field"
elif sport_key == 'nhl':
assert 'period' in current_fields, "NHL should have period field"
assert 'power_play' in current_fields, "NHL should have power_play field"
assert 'penalties' in current_fields, "NHL should have penalties field"
elif sport_key == 'soccer':
assert 'half' in current_fields, "Soccer should have half field"
assert 'stoppage_time' in current_fields, "Soccer should have stoppage_time field"
assert 'cards' in current_fields, "Soccer should have cards field"
assert 'possession' in current_fields, "Soccer should have possession field"
print(f"{sport_key} has unique sport-specific fields")
print("✅ All sports have unique characteristics")
return True
except Exception as e:
print(f"❌ Sports uniqueness test failed: {e}")
return False
def test_sports_data_source_mapping():
"""Test that sports are mapped to appropriate data sources."""
print("\n🧪 Testing Sports Data Source Mapping...")
try:
from src.base_classes.sport_configs import get_sport_config
# Test that each sport uses an appropriate data source
sports_to_test = ['nfl', 'ncaa_fb', 'mlb', 'nhl', 'ncaam_hockey', 'soccer', 'nba']
for sport_key in sports_to_test:
config = get_sport_config(sport_key, None)
data_source_type = config.data_source_type
# Test that data source type makes sense for the sport
if sport_key == 'mlb':
assert data_source_type == 'mlb_api', "MLB should use MLB API"
elif sport_key == 'soccer':
assert data_source_type == 'soccer_api', "Soccer should use Soccer API"
else:
assert data_source_type == 'espn', f"{sport_key} should use ESPN API"
print(f"{sport_key} uses appropriate data source: {data_source_type}")
print("✅ All sports use appropriate data sources")
return True
except Exception as e:
print(f"❌ Sports data source mapping test failed: {e}")
return False
def main():
"""Run all sports integration tests."""
print("🏈 Testing Sports Integration")
print("=" * 50)
# Configure logging
logging.basicConfig(level=logging.WARNING)
# Run all tests
tests = [
test_all_sports_configuration,
test_sports_api_extractors,
test_sports_data_sources,
test_sports_consistency,
test_sports_uniqueness,
test_sports_data_source_mapping
]
passed = 0
total = len(tests)
for test in tests:
try:
if test():
passed += 1
except Exception as e:
print(f"❌ Test {test.__name__} failed with exception: {e}")
print("\n" + "=" * 50)
print(f"🏁 Sports Integration Test Results: {passed}/{total} tests passed")
if passed == total:
print("🎉 All sports integration tests passed! The system can handle multiple sports.")
return True
else:
print("❌ Some sports integration tests failed. Please check the errors above.")
return False
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)