Files
pokemon-battle-engine/tools/data/test_downloader.py
2025-08-14 03:48:42 +00:00

296 lines
11 KiB
Python

#!/usr/bin/env python3
"""
Test script for the Pokemon data downloader.
This script tests the downloader with small data segments to ensure
everything works correctly before downloading larger datasets.
"""
import sys
import tempfile
import shutil
from pathlib import Path
import json
# Add the tools directory to Python path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))
from data.pokemon_downloader import PokemonDownloader
from data.schemas import DataValidator
from rich.console import Console
from rich.panel import Panel
console = Console()
def test_small_pokemon_download():
"""Test downloading a small set of Pokemon (first 3)."""
console.print(Panel.fit("🧪 Testing Pokemon Download (IDs 1-3)", style="bold yellow"))
# Create temporary directory for test output
with tempfile.TemporaryDirectory() as temp_dir:
downloader = PokemonDownloader(output_dir=Path(temp_dir))
# Download first 3 Pokemon
pokemon_data = downloader.download_pokemon_batch(1, 3, max_workers=2)
if not pokemon_data:
console.print("❌ Failed to download any Pokemon")
return False
console.print(f"✅ Downloaded {len(pokemon_data)} Pokemon:")
for pokemon_id, pokemon in pokemon_data.items():
console.print(f" - #{pokemon_id}: {pokemon.name.title()} ({', '.join(pokemon.types)})")
# Save and validate
downloader.save_pokemon_data(pokemon_data, "test_pokemon.json")
# Check the saved file
saved_file = Path(temp_dir) / "test_pokemon.json"
if saved_file.exists():
with open(saved_file) as f:
saved_data = json.load(f)
console.print(f"✅ Successfully saved {len(saved_data)} Pokemon to file")
# Show first Pokemon details
first_pokemon = list(saved_data.values())[0]
console.print(f"📊 Sample data for {first_pokemon['name']}:")
console.print(f" - Types: {first_pokemon['types']}")
console.print(f" - Base HP: {first_pokemon['base_stats']['hp']}")
console.print(f" - Abilities: {first_pokemon['abilities'][:2]}...") # Show first 2
console.print(f" - Move count: {len(first_pokemon['moves'])}")
return True
def test_moves_download():
"""Test downloading a small set of moves."""
console.print(Panel.fit("🧪 Testing Moves Download (IDs 1-5)", style="bold yellow"))
with tempfile.TemporaryDirectory() as temp_dir:
downloader = PokemonDownloader(output_dir=Path(temp_dir))
# Download first 5 moves
move_ids = [1, 2, 3, 4, 5] # Pound, Karate Chop, Double Slap, Comet Punch, Mega Punch
moves_data = downloader.download_moves_batch(move_ids, max_workers=2)
if not moves_data:
console.print("❌ Failed to download any moves")
return False
console.print(f"✅ Downloaded {len(moves_data)} moves:")
for move_id, move in moves_data.items():
power_str = f"{move.power} power" if move.power else "no power"
console.print(f" - #{move_id}: {move.name.title()} ({move.type}, {power_str})")
# Save and validate
downloader.save_moves_data(moves_data, "test_moves.json")
# Check the saved file
saved_file = Path(temp_dir) / "test_moves.json"
if saved_file.exists():
with open(saved_file) as f:
saved_data = json.load(f)
console.print(f"✅ Successfully saved {len(saved_data)} moves to file")
# Show move details
for move_data in list(saved_data.values())[:2]: # Show first 2 moves
console.print(f"📊 {move_data['name'].title()}:")
console.print(f" - Type: {move_data['type']}")
console.print(f" - Power: {move_data['power']}")
console.print(f" - Accuracy: {move_data['accuracy']}")
console.print(f" - PP: {move_data['pp']}")
return True
def test_type_effectiveness():
"""Test downloading type effectiveness data."""
console.print(Panel.fit("🧪 Testing Type Effectiveness Download", style="bold yellow"))
with tempfile.TemporaryDirectory() as temp_dir:
downloader = PokemonDownloader(output_dir=Path(temp_dir))
# Download type effectiveness
effectiveness_data = downloader.download_type_effectiveness()
if not effectiveness_data:
console.print("❌ Failed to download type effectiveness data")
return False
console.print(f"✅ Downloaded {len(effectiveness_data)} type effectiveness entries")
# Show some examples
console.print("📊 Sample type effectiveness entries:")
for entry in effectiveness_data[:5]:
factor_str = {0.0: "no effect", 0.5: "not very effective", 2.0: "super effective"}
console.print(f" - {entry.attacking_type} vs {entry.defending_type}: {factor_str.get(entry.damage_factor, str(entry.damage_factor))}")
# Save and validate
downloader.save_type_effectiveness(effectiveness_data, "test_types.json")
# Check the saved file
saved_file = Path(temp_dir) / "test_types.json"
if saved_file.exists():
with open(saved_file) as f:
saved_data = json.load(f)
console.print(f"✅ Successfully saved {len(saved_data)} type effectiveness entries to file")
return True
def test_validation():
"""Test the data validation system."""
console.print(Panel.fit("🧪 Testing Data Validation", style="bold yellow"))
validator = DataValidator()
# Test valid Pokemon data
valid_pokemon = {
"1": {
"id": 1,
"name": "bulbasaur",
"types": ["grass", "poison"],
"base_stats": {
"hp": 45,
"attack": 49,
"defense": 49,
"special_attack": 65,
"special_defense": 65,
"speed": 45
},
"abilities": ["overgrow", "chlorophyll"],
"moves": [1, 2, 3, 4],
"weight": 69,
"height": 7,
"base_experience": 64
}
}
errors = validator.validate_pokemon_collection(valid_pokemon)
if errors:
console.print(f"❌ Validation failed for valid data: {errors}")
return False
else:
console.print("✅ Valid Pokemon data passed validation")
# Test invalid Pokemon data
invalid_pokemon = {
"1": {
"id": 1,
"name": "bulbasaur",
"types": ["grass", "invalid_type"], # Invalid type
"base_stats": {
"hp": 45,
"attack": 49,
"defense": 49,
"special_attack": 65,
"special_defense": 65,
"speed": 45
},
"abilities": ["overgrow"],
"moves": [1, 2, 3, 4],
"weight": 69,
"height": 7,
"base_experience": 64
}
}
errors = validator.validate_pokemon_collection(invalid_pokemon)
if errors:
console.print(f"✅ Invalid Pokemon data correctly failed validation: {len(errors)} errors")
else:
console.print("❌ Invalid data should have failed validation")
return False
return True
def test_integrated_download():
"""Test downloading Pokemon with their moves in an integrated fashion."""
console.print(Panel.fit("🧪 Testing Integrated Pokemon + Moves Download", style="bold yellow"))
with tempfile.TemporaryDirectory() as temp_dir:
downloader = PokemonDownloader(output_dir=Path(temp_dir))
# Download a single Pokemon (Pikachu)
pokemon_data = downloader.download_pokemon_batch(25, 25, max_workers=1)
if not pokemon_data:
console.print("❌ Failed to download Pikachu")
return False
pikachu = pokemon_data[25]
console.print(f"✅ Downloaded {pikachu.name.title()}")
console.print(f" - Types: {pikachu.types}")
console.print(f" - Base stats total: {sum(pikachu.base_stats.__dict__.values())}")
console.print(f" - Can learn {len(pikachu.moves)} moves")
# Download first 10 moves that Pikachu can learn
pikachu_moves = pikachu.moves[:10]
moves_data = downloader.download_moves_batch(pikachu_moves, max_workers=3)
if moves_data:
console.print(f"✅ Downloaded {len(moves_data)} of Pikachu's moves:")
for move_id, move in list(moves_data.items())[:5]:
console.print(f" - {move.name.title()} ({move.type} type)")
# Save both datasets
downloader.save_pokemon_data(pokemon_data, "pikachu.json")
downloader.save_moves_data(moves_data, "pikachu_moves.json")
return True
def run_all_tests():
"""Run all tests."""
console.print(Panel.fit(
"🚀 Pokemon Data Downloader Test Suite",
style="bold green"
))
tests = [
("Pokemon Download", test_small_pokemon_download),
("Moves Download", test_moves_download),
("Type Effectiveness", test_type_effectiveness),
("Data Validation", test_validation),
("Integrated Download", test_integrated_download),
]
results = []
for test_name, test_func in tests:
console.print(f"\n{'='*50}")
try:
result = test_func()
results.append((test_name, result))
status = "✅ PASSED" if result else "❌ FAILED"
console.print(f"{test_name}: {status}")
except Exception as e:
results.append((test_name, False))
console.print(f"{test_name}: ❌ ERROR - {e}")
# Summary
console.print(f"\n{'='*50}")
console.print("TEST SUMMARY:")
passed = sum(1 for _, result in results if result)
total = len(results)
for test_name, result in results:
status = "" if result else ""
console.print(f" {status} {test_name}")
console.print(f"\nOverall: {passed}/{total} tests passed")
if passed == total:
console.print(Panel.fit("🎉 All tests passed! The downloader is ready to use.", style="bold green"))
else:
console.print(Panel.fit("⚠️ Some tests failed. Please check the errors above.", style="bold red"))
return passed == total
if __name__ == "__main__":
success = run_all_tests()
sys.exit(0 if success else 1)