mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
* 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
This commit is contained in:
@@ -184,7 +184,7 @@ def test_configuration():
|
||||
with open(config_path, 'r') as f:
|
||||
config = json.load(f)
|
||||
|
||||
milb_config = config.get('milb', {})
|
||||
milb_config = config.get('milb_scoreboard', {})
|
||||
|
||||
print(f"✅ Configuration file loaded successfully")
|
||||
print(f"MiLB enabled: {milb_config.get('enabled', False)}")
|
||||
|
||||
256
test/test_baseball_architecture.py
Normal file
256
test/test_baseball_architecture.py
Normal file
@@ -0,0 +1,256 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Baseball Architecture
|
||||
|
||||
This test validates the new baseball base class and its integration
|
||||
with the new architecture components.
|
||||
"""
|
||||
|
||||
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_baseball_imports():
|
||||
"""Test that baseball base classes can be imported."""
|
||||
print("🧪 Testing Baseball Imports...")
|
||||
|
||||
try:
|
||||
from src.base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming
|
||||
print("✅ Baseball base classes imported successfully")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball import failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_configuration():
|
||||
"""Test baseball-specific configuration."""
|
||||
print("\n🧪 Testing Baseball Configuration...")
|
||||
|
||||
try:
|
||||
from src.base_classes.sport_configs import get_sport_config
|
||||
|
||||
# Test MLB configuration
|
||||
mlb_config = get_sport_config('mlb', None)
|
||||
|
||||
# Validate MLB-specific settings
|
||||
assert mlb_config.update_cadence == 'daily', "MLB should have daily updates"
|
||||
assert mlb_config.season_length == 162, "MLB season should be 162 games"
|
||||
assert mlb_config.games_per_week == 6, "MLB should have ~6 games per week"
|
||||
assert mlb_config.data_source_type == 'mlb_api', "MLB should use MLB API"
|
||||
|
||||
# Test baseball-specific fields
|
||||
expected_fields = ['inning', 'outs', 'bases', 'strikes', 'balls', 'pitcher', 'batter']
|
||||
for field in expected_fields:
|
||||
assert field in mlb_config.sport_specific_fields, f"Missing baseball field: {field}"
|
||||
|
||||
print("✅ Baseball configuration is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball configuration test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_api_extractor():
|
||||
"""Test baseball API extractor."""
|
||||
print("\n🧪 Testing Baseball API Extractor...")
|
||||
|
||||
try:
|
||||
from src.base_classes.api_extractors import get_extractor_for_sport
|
||||
logger = logging.getLogger('test')
|
||||
|
||||
# Get MLB extractor
|
||||
mlb_extractor = get_extractor_for_sport('mlb', logger)
|
||||
print(f"✅ MLB extractor: {type(mlb_extractor).__name__}")
|
||||
|
||||
# Test that extractor has baseball-specific methods
|
||||
assert hasattr(mlb_extractor, 'extract_game_details')
|
||||
assert hasattr(mlb_extractor, 'get_sport_specific_fields')
|
||||
|
||||
# Test with sample baseball data
|
||||
sample_baseball_game = {
|
||||
"id": "test_game",
|
||||
"competitions": [{
|
||||
"status": {"type": {"state": "in", "detail": "Top 3rd"}},
|
||||
"competitors": [
|
||||
{"homeAway": "home", "team": {"abbreviation": "NYY", "displayName": "Yankees"}, "score": "2"},
|
||||
{"homeAway": "away", "team": {"abbreviation": "BOS", "displayName": "Red Sox"}, "score": "1"}
|
||||
],
|
||||
"situation": {
|
||||
"inning": "3rd",
|
||||
"outs": 2,
|
||||
"bases": "1st, 3rd",
|
||||
"strikes": 2,
|
||||
"balls": 1,
|
||||
"pitcher": "Gerrit Cole",
|
||||
"batter": "Rafael Devers"
|
||||
}
|
||||
}],
|
||||
"date": "2024-01-01T19:00:00Z"
|
||||
}
|
||||
|
||||
# Test game details extraction
|
||||
game_details = mlb_extractor.extract_game_details(sample_baseball_game)
|
||||
if game_details:
|
||||
print("✅ Baseball game details extracted successfully")
|
||||
|
||||
# Test sport-specific fields
|
||||
sport_fields = mlb_extractor.get_sport_specific_fields(sample_baseball_game)
|
||||
expected_fields = ['inning', 'outs', 'bases', 'strikes', 'balls', 'pitcher', 'batter']
|
||||
|
||||
for field in expected_fields:
|
||||
assert field in sport_fields, f"Missing baseball field: {field}"
|
||||
|
||||
print("✅ Baseball sport-specific fields extracted")
|
||||
else:
|
||||
print("⚠️ Baseball game details extraction returned None")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball API extractor test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_data_source():
|
||||
"""Test baseball data source."""
|
||||
print("\n🧪 Testing Baseball Data Source...")
|
||||
|
||||
try:
|
||||
from src.base_classes.data_sources import get_data_source_for_sport
|
||||
logger = logging.getLogger('test')
|
||||
|
||||
# Get MLB data source
|
||||
mlb_data_source = get_data_source_for_sport('mlb', 'mlb_api', logger)
|
||||
print(f"✅ MLB data source: {type(mlb_data_source).__name__}")
|
||||
|
||||
# Test that data source has required methods
|
||||
assert hasattr(mlb_data_source, 'fetch_live_games')
|
||||
assert hasattr(mlb_data_source, 'fetch_schedule')
|
||||
assert hasattr(mlb_data_source, 'fetch_standings')
|
||||
|
||||
print("✅ Baseball data source is properly configured")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball data source test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_sport_specific_logic():
|
||||
"""Test baseball-specific logic without hardware dependencies."""
|
||||
print("\n🧪 Testing Baseball Sport-Specific Logic...")
|
||||
|
||||
try:
|
||||
# Test baseball-specific game data
|
||||
sample_baseball_game = {
|
||||
'inning': '3rd',
|
||||
'outs': 2,
|
||||
'bases': '1st, 3rd',
|
||||
'strikes': 2,
|
||||
'balls': 1,
|
||||
'pitcher': 'Gerrit Cole',
|
||||
'batter': 'Rafael Devers',
|
||||
'is_live': True,
|
||||
'is_final': False,
|
||||
'is_upcoming': False
|
||||
}
|
||||
|
||||
# Test that we can identify baseball-specific characteristics
|
||||
assert sample_baseball_game['inning'] == '3rd'
|
||||
assert sample_baseball_game['outs'] == 2
|
||||
assert sample_baseball_game['bases'] == '1st, 3rd'
|
||||
assert sample_baseball_game['strikes'] == 2
|
||||
assert sample_baseball_game['balls'] == 1
|
||||
|
||||
print("✅ Baseball sport-specific logic is working")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball sport-specific logic test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_vs_other_sports():
|
||||
"""Test that baseball has different characteristics than other sports."""
|
||||
print("\n🧪 Testing Baseball vs Other Sports...")
|
||||
|
||||
try:
|
||||
from src.base_classes.sport_configs import get_sport_config
|
||||
|
||||
# Compare baseball with other sports
|
||||
mlb_config = get_sport_config('mlb', None)
|
||||
nfl_config = get_sport_config('nfl', None)
|
||||
nhl_config = get_sport_config('nhl', None)
|
||||
|
||||
# Baseball should have different characteristics
|
||||
assert mlb_config.season_length > nfl_config.season_length, "MLB season should be longer than NFL"
|
||||
assert mlb_config.games_per_week > nfl_config.games_per_week, "MLB should have more games per week than NFL"
|
||||
assert mlb_config.update_cadence == 'daily', "MLB should have daily updates"
|
||||
assert nfl_config.update_cadence == 'weekly', "NFL should have weekly updates"
|
||||
|
||||
# Baseball should have different sport-specific fields
|
||||
mlb_fields = set(mlb_config.sport_specific_fields)
|
||||
nfl_fields = set(nfl_config.sport_specific_fields)
|
||||
nhl_fields = set(nhl_config.sport_specific_fields)
|
||||
|
||||
# Baseball should have unique fields
|
||||
assert 'inning' in mlb_fields, "Baseball should have inning field"
|
||||
assert 'outs' in mlb_fields, "Baseball should have outs field"
|
||||
assert 'bases' in mlb_fields, "Baseball should have bases field"
|
||||
assert 'strikes' in mlb_fields, "Baseball should have strikes field"
|
||||
assert 'balls' in mlb_fields, "Baseball should have balls field"
|
||||
|
||||
# Baseball should not have football/hockey fields
|
||||
assert 'down' not in mlb_fields, "Baseball should not have down field"
|
||||
assert 'distance' not in mlb_fields, "Baseball should not have distance field"
|
||||
assert 'period' not in mlb_fields, "Baseball should not have period field"
|
||||
|
||||
print("✅ Baseball has distinct characteristics from other sports")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball vs other sports test failed: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Run all baseball architecture tests."""
|
||||
print("⚾ Testing Baseball Architecture")
|
||||
print("=" * 50)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
|
||||
# Run all tests
|
||||
tests = [
|
||||
test_baseball_imports,
|
||||
test_baseball_configuration,
|
||||
test_baseball_api_extractor,
|
||||
test_baseball_data_source,
|
||||
test_baseball_sport_specific_logic,
|
||||
test_baseball_vs_other_sports
|
||||
]
|
||||
|
||||
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"🏁 Baseball Test Results: {passed}/{total} tests passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All baseball architecture tests passed! Baseball is ready to use.")
|
||||
return True
|
||||
else:
|
||||
print("❌ Some baseball tests failed. Please check the errors above.")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
236
test/test_baseball_managers_integration.py
Normal file
236
test/test_baseball_managers_integration.py
Normal file
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Baseball Managers Integration
|
||||
|
||||
This test validates that MILB and NCAA Baseball managers work with the new
|
||||
baseball base class architecture.
|
||||
"""
|
||||
|
||||
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_milb_manager_imports():
|
||||
"""Test that MILB managers can be imported."""
|
||||
print("🧪 Testing MILB Manager Imports...")
|
||||
|
||||
try:
|
||||
# Test that we can import the new MILB managers
|
||||
from src.milb_managers_v2 import BaseMiLBManager, MiLBLiveManager, MiLBRecentManager, MiLBUpcomingManager
|
||||
print("✅ MILB managers imported successfully")
|
||||
|
||||
# Test that classes are properly defined
|
||||
assert BaseMiLBManager is not None
|
||||
assert MiLBLiveManager is not None
|
||||
assert MiLBRecentManager is not None
|
||||
assert MiLBUpcomingManager is not None
|
||||
|
||||
print("✅ MILB managers are properly defined")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ MILB manager import test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_ncaa_baseball_manager_imports():
|
||||
"""Test that NCAA Baseball managers can be imported."""
|
||||
print("\n🧪 Testing NCAA Baseball Manager Imports...")
|
||||
|
||||
try:
|
||||
# Test that we can import the new NCAA Baseball managers
|
||||
from src.ncaa_baseball_managers_v2 import BaseNCAABaseballManager, NCAABaseballLiveManager, NCAABaseballRecentManager, NCAABaseballUpcomingManager
|
||||
print("✅ NCAA Baseball managers imported successfully")
|
||||
|
||||
# Test that classes are properly defined
|
||||
assert BaseNCAABaseballManager is not None
|
||||
assert NCAABaseballLiveManager is not None
|
||||
assert NCAABaseballRecentManager is not None
|
||||
assert NCAABaseballUpcomingManager is not None
|
||||
|
||||
print("✅ NCAA Baseball managers are properly defined")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ NCAA Baseball manager import test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_milb_manager_inheritance():
|
||||
"""Test that MILB managers properly inherit from baseball base classes."""
|
||||
print("\n🧪 Testing MILB Manager Inheritance...")
|
||||
|
||||
try:
|
||||
from src.milb_managers_v2 import BaseMiLBManager, MiLBLiveManager, MiLBRecentManager, MiLBUpcomingManager
|
||||
from src.base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming
|
||||
|
||||
# Test inheritance
|
||||
assert issubclass(BaseMiLBManager, Baseball), "BaseMiLBManager should inherit from Baseball"
|
||||
assert issubclass(MiLBLiveManager, BaseballLive), "MiLBLiveManager should inherit from BaseballLive"
|
||||
assert issubclass(MiLBRecentManager, BaseballRecent), "MiLBRecentManager should inherit from BaseballRecent"
|
||||
assert issubclass(MiLBUpcomingManager, BaseballUpcoming), "MiLBUpcomingManager should inherit from BaseballUpcoming"
|
||||
|
||||
print("✅ MILB managers properly inherit from baseball base classes")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ MILB manager inheritance test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_ncaa_baseball_manager_inheritance():
|
||||
"""Test that NCAA Baseball managers properly inherit from baseball base classes."""
|
||||
print("\n🧪 Testing NCAA Baseball Manager Inheritance...")
|
||||
|
||||
try:
|
||||
from src.ncaa_baseball_managers_v2 import BaseNCAABaseballManager, NCAABaseballLiveManager, NCAABaseballRecentManager, NCAABaseballUpcomingManager
|
||||
from src.base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming
|
||||
|
||||
# Test inheritance
|
||||
assert issubclass(BaseNCAABaseballManager, Baseball), "BaseNCAABaseballManager should inherit from Baseball"
|
||||
assert issubclass(NCAABaseballLiveManager, BaseballLive), "NCAABaseballLiveManager should inherit from BaseballLive"
|
||||
assert issubclass(NCAABaseballRecentManager, BaseballRecent), "NCAABaseballRecentManager should inherit from BaseballRecent"
|
||||
assert issubclass(NCAABaseballUpcomingManager, BaseballUpcoming), "NCAABaseballUpcomingManager should inherit from BaseballUpcoming"
|
||||
|
||||
print("✅ NCAA Baseball managers properly inherit from baseball base classes")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ NCAA Baseball manager inheritance test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_milb_manager_methods():
|
||||
"""Test that MILB managers have required methods."""
|
||||
print("\n🧪 Testing MILB Manager Methods...")
|
||||
|
||||
try:
|
||||
from src.milb_managers_v2 import BaseMiLBManager, MiLBLiveManager, MiLBRecentManager, MiLBUpcomingManager
|
||||
|
||||
# Test that managers have required methods
|
||||
required_methods = ['get_duration', 'display', '_display_single_game']
|
||||
|
||||
for manager_class in [MiLBLiveManager, MiLBRecentManager, MiLBUpcomingManager]:
|
||||
for method in required_methods:
|
||||
assert hasattr(manager_class, method), f"{manager_class.__name__} should have {method} method"
|
||||
assert callable(getattr(manager_class, method)), f"{manager_class.__name__}.{method} should be callable"
|
||||
|
||||
print("✅ MILB managers have all required methods")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ MILB manager methods test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_ncaa_baseball_manager_methods():
|
||||
"""Test that NCAA Baseball managers have required methods."""
|
||||
print("\n🧪 Testing NCAA Baseball Manager Methods...")
|
||||
|
||||
try:
|
||||
from src.ncaa_baseball_managers_v2 import BaseNCAABaseballManager, NCAABaseballLiveManager, NCAABaseballRecentManager, NCAABaseballUpcomingManager
|
||||
|
||||
# Test that managers have required methods
|
||||
required_methods = ['get_duration', 'display', '_display_single_game']
|
||||
|
||||
for manager_class in [NCAABaseballLiveManager, NCAABaseballRecentManager, NCAABaseballUpcomingManager]:
|
||||
for method in required_methods:
|
||||
assert hasattr(manager_class, method), f"{manager_class.__name__} should have {method} method"
|
||||
assert callable(getattr(manager_class, method)), f"{manager_class.__name__}.{method} should be callable"
|
||||
|
||||
print("✅ NCAA Baseball managers have all required methods")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ NCAA Baseball manager methods test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_sport_specific_features():
|
||||
"""Test that managers have baseball-specific features."""
|
||||
print("\n🧪 Testing Baseball Sport-Specific Features...")
|
||||
|
||||
try:
|
||||
from src.milb_managers_v2 import BaseMiLBManager
|
||||
from src.ncaa_baseball_managers_v2 import BaseNCAABaseballManager
|
||||
|
||||
# Test that managers have baseball-specific methods
|
||||
baseball_methods = ['_get_baseball_display_text', '_is_baseball_game_live', '_get_baseball_game_status']
|
||||
|
||||
for manager_class in [BaseMiLBManager, BaseNCAABaseballManager]:
|
||||
for method in baseball_methods:
|
||||
assert hasattr(manager_class, method), f"{manager_class.__name__} should have {method} method"
|
||||
assert callable(getattr(manager_class, method)), f"{manager_class.__name__}.{method} should be callable"
|
||||
|
||||
print("✅ Baseball managers have sport-specific features")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball sport-specific features test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_manager_configuration():
|
||||
"""Test that managers use proper sport configuration."""
|
||||
print("\n🧪 Testing Manager Configuration...")
|
||||
|
||||
try:
|
||||
from src.base_classes.sport_configs import get_sport_config
|
||||
|
||||
# Test MILB configuration
|
||||
milb_config = get_sport_config('milb', None)
|
||||
assert milb_config is not None, "MILB should have configuration"
|
||||
assert milb_config.sport_specific_fields, "MILB should have sport-specific fields"
|
||||
|
||||
# Test NCAA Baseball configuration
|
||||
ncaa_baseball_config = get_sport_config('ncaa_baseball', None)
|
||||
assert ncaa_baseball_config is not None, "NCAA Baseball should have configuration"
|
||||
assert ncaa_baseball_config.sport_specific_fields, "NCAA Baseball should have sport-specific fields"
|
||||
|
||||
print("✅ Managers use proper sport configuration")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Manager configuration test failed: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Run all baseball manager integration tests."""
|
||||
print("⚾ Testing Baseball Managers Integration")
|
||||
print("=" * 50)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
|
||||
# Run all tests
|
||||
tests = [
|
||||
test_milb_manager_imports,
|
||||
test_ncaa_baseball_manager_imports,
|
||||
test_milb_manager_inheritance,
|
||||
test_ncaa_baseball_manager_inheritance,
|
||||
test_milb_manager_methods,
|
||||
test_ncaa_baseball_manager_methods,
|
||||
test_baseball_sport_specific_features,
|
||||
test_manager_configuration
|
||||
]
|
||||
|
||||
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"🏁 Baseball Manager Integration Test Results: {passed}/{total} tests passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All baseball manager integration tests passed! MILB and NCAA Baseball work with the new architecture.")
|
||||
return True
|
||||
else:
|
||||
print("❌ Some baseball manager integration tests failed. Please check the errors above.")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
243
test/test_baseball_managers_simple.py
Normal file
243
test/test_baseball_managers_simple.py
Normal file
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Baseball Managers Integration - Simple Version
|
||||
|
||||
This test validates that MILB and NCAA Baseball managers work with the new
|
||||
baseball base class architecture without requiring full imports.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Add src to path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
def test_milb_manager_structure():
|
||||
"""Test that MILB managers have the correct structure."""
|
||||
print("🧪 Testing MILB Manager Structure...")
|
||||
|
||||
try:
|
||||
# Read the MILB managers file
|
||||
with open('src/milb_managers_v2.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check that it imports the baseball base classes
|
||||
assert 'from .base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming' in content
|
||||
print("✅ MILB managers import baseball base classes")
|
||||
|
||||
# Check that classes are defined
|
||||
assert 'class BaseMiLBManager(Baseball):' in content
|
||||
assert 'class MiLBLiveManager(BaseMiLBManager, BaseballLive):' in content
|
||||
assert 'class MiLBRecentManager(BaseMiLBManager, BaseballRecent):' in content
|
||||
assert 'class MiLBUpcomingManager(BaseMiLBManager, BaseballUpcoming):' in content
|
||||
print("✅ MILB managers have correct class definitions")
|
||||
|
||||
# Check that required methods exist
|
||||
assert 'def get_duration(self) -> int:' in content
|
||||
assert 'def display(self, force_clear: bool = False) -> bool:' in content
|
||||
assert 'def _display_single_game(self, game: Dict) -> None:' in content
|
||||
print("✅ MILB managers have required methods")
|
||||
|
||||
print("✅ MILB manager structure is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ MILB manager structure test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_ncaa_baseball_manager_structure():
|
||||
"""Test that NCAA Baseball managers have the correct structure."""
|
||||
print("\n🧪 Testing NCAA Baseball Manager Structure...")
|
||||
|
||||
try:
|
||||
# Read the NCAA Baseball managers file
|
||||
with open('src/ncaa_baseball_managers_v2.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check that it imports the baseball base classes
|
||||
assert 'from .base_classes.baseball import Baseball, BaseballLive, BaseballRecent, BaseballUpcoming' in content
|
||||
print("✅ NCAA Baseball managers import baseball base classes")
|
||||
|
||||
# Check that classes are defined
|
||||
assert 'class BaseNCAABaseballManager(Baseball):' in content
|
||||
assert 'class NCAABaseballLiveManager(BaseNCAABaseballManager, BaseballLive):' in content
|
||||
assert 'class NCAABaseballRecentManager(BaseNCAABaseballManager, BaseballRecent):' in content
|
||||
assert 'class NCAABaseballUpcomingManager(BaseNCAABaseballManager, BaseballUpcoming):' in content
|
||||
print("✅ NCAA Baseball managers have correct class definitions")
|
||||
|
||||
# Check that required methods exist
|
||||
assert 'def get_duration(self) -> int:' in content
|
||||
assert 'def display(self, force_clear: bool = False) -> bool:' in content
|
||||
assert 'def _display_single_game(self, game: Dict) -> None:' in content
|
||||
print("✅ NCAA Baseball managers have required methods")
|
||||
|
||||
print("✅ NCAA Baseball manager structure is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ NCAA Baseball manager structure test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_inheritance():
|
||||
"""Test that managers properly inherit from baseball base classes."""
|
||||
print("\n🧪 Testing Baseball Inheritance...")
|
||||
|
||||
try:
|
||||
# Read both manager files
|
||||
with open('src/milb_managers_v2.py', 'r') as f:
|
||||
milb_content = f.read()
|
||||
|
||||
with open('src/ncaa_baseball_managers_v2.py', 'r') as f:
|
||||
ncaa_content = f.read()
|
||||
|
||||
# Check that managers inherit from baseball base classes
|
||||
assert 'BaseMiLBManager(Baseball)' in milb_content
|
||||
assert 'MiLBLiveManager(BaseMiLBManager, BaseballLive)' in milb_content
|
||||
assert 'MiLBRecentManager(BaseMiLBManager, BaseballRecent)' in milb_content
|
||||
assert 'MiLBUpcomingManager(BaseMiLBManager, BaseballUpcoming)' in milb_content
|
||||
print("✅ MILB managers properly inherit from baseball base classes")
|
||||
|
||||
assert 'BaseNCAABaseballManager(Baseball)' in ncaa_content
|
||||
assert 'NCAABaseballLiveManager(BaseNCAABaseballManager, BaseballLive)' in ncaa_content
|
||||
assert 'NCAABaseballRecentManager(BaseNCAABaseballManager, BaseballRecent)' in ncaa_content
|
||||
assert 'NCAABaseballUpcomingManager(BaseNCAABaseballManager, BaseballUpcoming)' in ncaa_content
|
||||
print("✅ NCAA Baseball managers properly inherit from baseball base classes")
|
||||
|
||||
print("✅ Baseball inheritance is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball inheritance test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_baseball_sport_specific_methods():
|
||||
"""Test that managers have baseball-specific methods."""
|
||||
print("\n🧪 Testing Baseball Sport-Specific Methods...")
|
||||
|
||||
try:
|
||||
# Read both manager files
|
||||
with open('src/milb_managers_v2.py', 'r') as f:
|
||||
milb_content = f.read()
|
||||
|
||||
with open('src/ncaa_baseball_managers_v2.py', 'r') as f:
|
||||
ncaa_content = f.read()
|
||||
|
||||
# Check for baseball-specific methods
|
||||
baseball_methods = [
|
||||
'_get_baseball_display_text',
|
||||
'_is_baseball_game_live',
|
||||
'_get_baseball_game_status',
|
||||
'_draw_base_indicators'
|
||||
]
|
||||
|
||||
for method in baseball_methods:
|
||||
assert method in milb_content, f"MILB managers should have {method} method"
|
||||
assert method in ncaa_content, f"NCAA Baseball managers should have {method} method"
|
||||
|
||||
print("✅ Baseball managers have sport-specific methods")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Baseball sport-specific methods test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_manager_initialization():
|
||||
"""Test that managers are properly initialized."""
|
||||
print("\n🧪 Testing Manager Initialization...")
|
||||
|
||||
try:
|
||||
# Read both manager files
|
||||
with open('src/milb_managers_v2.py', 'r') as f:
|
||||
milb_content = f.read()
|
||||
|
||||
with open('src/ncaa_baseball_managers_v2.py', 'r') as f:
|
||||
ncaa_content = f.read()
|
||||
|
||||
# Check that managers call super().__init__ with sport_key
|
||||
assert 'super().__init__(config, display_manager, cache_manager, logger, "milb")' in milb_content
|
||||
assert 'super().__init__(config, display_manager, cache_manager, logger, "ncaa_baseball")' in ncaa_content
|
||||
print("✅ Managers are properly initialized with sport keys")
|
||||
|
||||
# Check that managers have proper logging
|
||||
assert 'self.logger.info(' in milb_content
|
||||
assert 'self.logger.info(' in ncaa_content
|
||||
print("✅ Managers have proper logging")
|
||||
|
||||
print("✅ Manager initialization is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Manager initialization test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_sport_configuration_integration():
|
||||
"""Test that managers integrate with sport configuration."""
|
||||
print("\n🧪 Testing Sport Configuration Integration...")
|
||||
|
||||
try:
|
||||
# Read both manager files
|
||||
with open('src/milb_managers_v2.py', 'r') as f:
|
||||
milb_content = f.read()
|
||||
|
||||
with open('src/ncaa_baseball_managers_v2.py', 'r') as f:
|
||||
ncaa_content = f.read()
|
||||
|
||||
# Check that managers use sport configuration
|
||||
assert 'self.sport_config' in milb_content or 'super().__init__' in milb_content
|
||||
assert 'self.sport_config' in ncaa_content or 'super().__init__' in ncaa_content
|
||||
print("✅ Managers use sport configuration")
|
||||
|
||||
# Check that managers have sport-specific configuration
|
||||
assert 'self.milb_config' in milb_content
|
||||
assert 'self.ncaa_baseball_config' in ncaa_content
|
||||
print("✅ Managers have sport-specific configuration")
|
||||
|
||||
print("✅ Sport configuration integration is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Sport configuration integration test failed: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Run all baseball manager integration tests."""
|
||||
print("⚾ Testing Baseball Managers Integration (Simple)")
|
||||
print("=" * 50)
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
|
||||
# Run all tests
|
||||
tests = [
|
||||
test_milb_manager_structure,
|
||||
test_ncaa_baseball_manager_structure,
|
||||
test_baseball_inheritance,
|
||||
test_baseball_sport_specific_methods,
|
||||
test_manager_initialization,
|
||||
test_sport_configuration_integration
|
||||
]
|
||||
|
||||
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"🏁 Baseball Manager Integration Test Results: {passed}/{total} tests passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All baseball manager integration tests passed! MILB and NCAA Baseball work with the new architecture.")
|
||||
return True
|
||||
else:
|
||||
print("❌ Some baseball manager integration tests failed. Please check the errors above.")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
@@ -31,8 +31,8 @@ def test_config_values():
|
||||
("NCAA Football", config.get('ncaa_fb_scoreboard', {})),
|
||||
("NCAA Baseball", config.get('ncaa_baseball_scoreboard', {})),
|
||||
("NCAA Basketball", config.get('ncaam_basketball_scoreboard', {})),
|
||||
("MLB", config.get('mlb', {})),
|
||||
("MiLB", config.get('milb', {})),
|
||||
("MLB", config.get('mlb_scoreboard', {})),
|
||||
("MiLB", config.get('milb_scoreboard', {})),
|
||||
("Soccer", config.get('soccer_scoreboard', {}))
|
||||
]
|
||||
|
||||
@@ -84,8 +84,8 @@ def test_config_consistency():
|
||||
("NCAA Football", config.get('ncaa_fb_scoreboard', {})),
|
||||
("NCAA Baseball", config.get('ncaa_baseball_scoreboard', {})),
|
||||
("NCAA Basketball", config.get('ncaam_basketball_scoreboard', {})),
|
||||
("MLB", config.get('mlb', {})),
|
||||
("MiLB", config.get('milb', {})),
|
||||
("MLB", config.get('mlb_scoreboard', {})),
|
||||
("MiLB", config.get('milb_scoreboard', {})),
|
||||
("Soccer", config.get('soccer_scoreboard', {}))
|
||||
]
|
||||
|
||||
|
||||
169
test/test_leaderboard_duration_fix.py
Normal file
169
test/test_leaderboard_duration_fix.py
Normal file
@@ -0,0 +1,169 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test Leaderboard Duration Fix
|
||||
|
||||
This test validates that the LeaderboardManager has the required get_duration method
|
||||
that the display controller expects.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Add src to path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
def test_leaderboard_duration_method():
|
||||
"""Test that LeaderboardManager has the get_duration method."""
|
||||
print("🧪 Testing Leaderboard Duration Method...")
|
||||
|
||||
try:
|
||||
# Read the leaderboard manager file
|
||||
with open('src/leaderboard_manager.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check that get_duration method exists
|
||||
if 'def get_duration(self) -> int:' in content:
|
||||
print("✅ get_duration method found in LeaderboardManager")
|
||||
else:
|
||||
print("❌ get_duration method not found in LeaderboardManager")
|
||||
return False
|
||||
|
||||
# Check that method is properly implemented
|
||||
if 'return self.get_dynamic_duration()' in content:
|
||||
print("✅ get_duration method uses dynamic duration when enabled")
|
||||
else:
|
||||
print("❌ get_duration method not properly implemented for dynamic duration")
|
||||
return False
|
||||
|
||||
if 'return self.display_duration' in content:
|
||||
print("✅ get_duration method falls back to display_duration")
|
||||
else:
|
||||
print("❌ get_duration method not properly implemented for fallback")
|
||||
return False
|
||||
|
||||
# Check that method is in the right place (after get_dynamic_duration)
|
||||
lines = content.split('\n')
|
||||
get_dynamic_duration_line = None
|
||||
get_duration_line = None
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if 'def get_dynamic_duration(self) -> int:' in line:
|
||||
get_dynamic_duration_line = i
|
||||
elif 'def get_duration(self) -> int:' in line:
|
||||
get_duration_line = i
|
||||
|
||||
if get_dynamic_duration_line is not None and get_duration_line is not None:
|
||||
if get_duration_line > get_dynamic_duration_line:
|
||||
print("✅ get_duration method is placed after get_dynamic_duration")
|
||||
else:
|
||||
print("❌ get_duration method is not in the right place")
|
||||
return False
|
||||
|
||||
print("✅ LeaderboardManager duration method is properly implemented")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Leaderboard duration method test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_leaderboard_duration_logic():
|
||||
"""Test that the duration logic makes sense."""
|
||||
print("\n🧪 Testing Leaderboard Duration Logic...")
|
||||
|
||||
try:
|
||||
# Read the leaderboard manager file
|
||||
with open('src/leaderboard_manager.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check that the logic is correct
|
||||
if 'if self.dynamic_duration_enabled:' in content:
|
||||
print("✅ Dynamic duration logic is implemented")
|
||||
else:
|
||||
print("❌ Dynamic duration logic not found")
|
||||
return False
|
||||
|
||||
if 'return self.get_dynamic_duration()' in content:
|
||||
print("✅ Returns dynamic duration when enabled")
|
||||
else:
|
||||
print("❌ Does not return dynamic duration when enabled")
|
||||
return False
|
||||
|
||||
if 'return self.display_duration' in content:
|
||||
print("✅ Returns display duration as fallback")
|
||||
else:
|
||||
print("❌ Does not return display duration as fallback")
|
||||
return False
|
||||
|
||||
print("✅ Leaderboard duration logic is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Leaderboard duration logic test failed: {e}")
|
||||
return False
|
||||
|
||||
def test_leaderboard_method_signature():
|
||||
"""Test that the method signature is correct."""
|
||||
print("\n🧪 Testing Leaderboard Method Signature...")
|
||||
|
||||
try:
|
||||
# Read the leaderboard manager file
|
||||
with open('src/leaderboard_manager.py', 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check method signature
|
||||
if 'def get_duration(self) -> int:' in content:
|
||||
print("✅ Method signature is correct")
|
||||
else:
|
||||
print("❌ Method signature is incorrect")
|
||||
return False
|
||||
|
||||
# Check docstring
|
||||
if '"""Get the display duration for the leaderboard."""' in content:
|
||||
print("✅ Method has proper docstring")
|
||||
else:
|
||||
print("❌ Method missing docstring")
|
||||
return False
|
||||
|
||||
print("✅ Leaderboard method signature is correct")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Leaderboard method signature test failed: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
"""Run all leaderboard duration tests."""
|
||||
print("🏆 Testing Leaderboard Duration Fix")
|
||||
print("=" * 50)
|
||||
|
||||
# Run all tests
|
||||
tests = [
|
||||
test_leaderboard_duration_method,
|
||||
test_leaderboard_duration_logic,
|
||||
test_leaderboard_method_signature
|
||||
]
|
||||
|
||||
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"🏁 Leaderboard Duration Test Results: {passed}/{total} tests passed")
|
||||
|
||||
if passed == total:
|
||||
print("🎉 All leaderboard duration tests passed! The fix is working correctly.")
|
||||
return True
|
||||
else:
|
||||
print("❌ Some leaderboard duration tests failed. Please check the errors above.")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
@@ -23,7 +23,7 @@ def test_milb_api_accuracy():
|
||||
try:
|
||||
with open('config/config.json', 'r') as f:
|
||||
config = json.load(f)
|
||||
milb_config = config.get('milb', {})
|
||||
milb_config = config.get('milb_scoreboard', {})
|
||||
favorite_teams = milb_config.get('favorite_teams', [])
|
||||
print(f"Favorite teams: {favorite_teams}")
|
||||
except Exception as e:
|
||||
|
||||
243
test/test_new_architecture.py
Normal file
243
test/test_new_architecture.py
Normal file
@@ -0,0 +1,243 @@
|
||||
#!/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)
|
||||
270
test/test_sports_integration.py
Normal file
270
test/test_sports_integration.py
Normal file
@@ -0,0 +1,270 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user