Files
LEDMatrix/test/test_new_architecture.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

244 lines
8.7 KiB
Python

#!/usr/bin/env python3
"""
Test New Architecture Components
This test validates the new sports architecture including:
- API extractors
- Sport configurations
- Data sources
- Baseball base classes
"""
import sys
import os
import logging
from typing import Dict, Any
# Add src to path
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
def test_sport_configurations():
"""Test sport-specific configurations."""
print("🧪 Testing Sport Configurations...")
try:
from src.base_classes.sport_configs import get_sport_configs, get_sport_config
# Test getting all configurations
configs = get_sport_configs()
print(f"✅ Loaded {len(configs)} sport configurations")
# Test each sport
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)
print(f"{sport_key}: {config.update_cadence}, {config.season_length} games, {config.data_source_type}")
# Validate configuration
assert config.update_cadence in ['daily', 'weekly', 'hourly', 'live_only']
assert config.season_length > 0
assert config.data_source_type in ['espn', 'mlb_api', 'soccer_api']
assert len(config.sport_specific_fields) > 0
print("✅ All sport configurations valid")
return True
except Exception as e:
print(f"❌ Sport configuration test failed: {e}")
return False
def test_api_extractors():
"""Test API extractors for different sports."""
print("\n🧪 Testing API Extractors...")
try:
from src.base_classes.api_extractors import get_extractor_for_sport
logger = logging.getLogger('test')
# Test each sport extractor
sports_to_test = ['nfl', 'mlb', 'nhl', 'soccer']
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 API extractors valid")
return True
except Exception as e:
print(f"❌ API extractor test failed: {e}")
return False
def test_data_sources():
"""Test data sources for different sports."""
print("\n🧪 Testing Data Sources...")
try:
from src.base_classes.data_sources import get_data_source_for_sport
logger = logging.getLogger('test')
# Test different data source types
data_source_tests = [
('nfl', 'espn'),
('mlb', 'mlb_api'),
('soccer', 'soccer_api')
]
for sport_key, source_type in data_source_tests:
data_source = get_data_source_for_sport(sport_key, source_type, logger)
print(f"{sport_key} data source: {type(data_source).__name__}")
# 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 data sources valid")
return True
except Exception as e:
print(f"❌ Data source test failed: {e}")
return False
def test_baseball_base_class():
"""Test baseball base class without hardware dependencies."""
print("\n🧪 Testing Baseball Base Class...")
try:
# Test that we can import the baseball base class
from src.base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming
print("✅ Baseball base classes imported successfully")
# Test that classes are properly defined
assert Baseball is not None
assert BaseballLive is not None
assert BaseballRecent is not None
assert BaseballUpcoming is not None
print("✅ Baseball base classes properly defined")
return True
except Exception as e:
print(f"❌ Baseball base class test failed: {e}")
return False
def test_sport_specific_fields():
"""Test that each sport has appropriate sport-specific fields."""
print("\n🧪 Testing Sport-Specific Fields...")
try:
from src.base_classes.sport_configs import get_sport_config
# Test sport-specific fields for each sport
sport_fields_tests = {
'nfl': ['down', 'distance', 'possession', 'timeouts', 'is_redzone'],
'mlb': ['inning', 'outs', 'bases', 'strikes', 'balls', 'pitcher', 'batter'],
'nhl': ['period', 'power_play', 'penalties', 'shots_on_goal'],
'soccer': ['half', 'stoppage_time', 'cards', 'possession']
}
for sport_key, expected_fields in sport_fields_tests.items():
config = get_sport_config(sport_key, None)
actual_fields = config.sport_specific_fields
print(f"{sport_key} fields: {actual_fields}")
# Check that we have the expected fields
for field in expected_fields:
assert field in actual_fields, f"Missing field {field} for {sport_key}"
print("✅ All sport-specific fields valid")
return True
except Exception as e:
print(f"❌ Sport-specific fields test failed: {e}")
return False
def test_configuration_consistency():
"""Test that configurations are consistent and logical."""
print("\n🧪 Testing Configuration 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
if config.season_length > 100: # Long season
assert config.update_cadence in ['daily', 'hourly'], f"{sport_key} should have frequent updates for long season"
elif config.season_length < 20: # Short season
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 configurations are consistent")
return True
except Exception as e:
print(f"❌ Configuration consistency test failed: {e}")
return False
def main():
"""Run all architecture tests."""
print("🚀 Testing New Sports Architecture")
print("=" * 50)
# Configure logging
logging.basicConfig(level=logging.WARNING)
# Run all tests
tests = [
test_sport_configurations,
test_api_extractors,
test_data_sources,
test_baseball_base_class,
test_sport_specific_fields,
test_configuration_consistency
]
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"🏁 Test Results: {passed}/{total} tests passed")
if passed == total:
print("🎉 All architecture tests passed! The new system is ready to use.")
return True
else:
print("❌ Some tests failed. Please check the errors above.")
return False
if __name__ == "__main__":
success = main()
sys.exit(0 if success else 1)