Files
mtgonline/backend/mtg_rules_engine/test_engine.py
T

277 lines
9.8 KiB
Python

#!/usr/bin/env python3
"""Tests for the Magic: The Gathering Rules Engine"""
import sys
import os
# Add parent directory to path for importing mtg_rules_engine
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from mtg_rules_engine import (
ABILITY_WORDS,
KEYWORD_ACTIONS,
KEYWORD_ABILITIES,
get_all_keywords,
get_keyword_info,
is_valid_keyword,
get_keyword_type,
KeywordValidator,
RulesEngine,
)
def test_keyword_database():
"""Test the keyword database is properly populated."""
print("=" * 60)
print("TEST: Keyword Database")
print("=" * 60)
# Test ability words
assert len(ABILITY_WORDS) > 0, "Ability words should not be empty"
assert "adamant" in ABILITY_WORDS, "adamant should be in ability words"
print(f" ✓ {len(ABILITY_WORDS)} ability words loaded")
# Test keyword actions
assert len(KEYWORD_ACTIONS) > 0, "Keyword actions should not be empty"
assert "fly" not in KEYWORD_ACTIONS and "flying" in KEYWORD_ABILITIES, "flying should be a keyword ability"
assert "cast" in KEYWORD_ACTIONS, "cast should be a keyword action"
assert "destroy" in KEYWORD_ACTIONS, "destroy should be a keyword action"
print(f" ✓ {len(KEYWORD_ACTIONS)} keyword actions loaded")
# Test keyword abilities
assert len(KEYWORD_ABILITIES) > 0, "Keyword abilities should not be empty"
assert "flying" in KEYWORD_ABILITIES, "flying should be a keyword ability"
assert "haste" in KEYWORD_ABILITIES, "haste should be a keyword ability"
assert "deathtouch" in KEYWORD_ABILITIES, "deathtouch should be a keyword ability"
assert "trample" in KEYWORD_ABILITIES, "trample should be a keyword ability"
assert "hexproof" in KEYWORD_ABILITIES, "hexproof should be a keyword ability"
assert "flying" in KEYWORD_ABILITIES, "flying should be a keyword ability"
print(f" ✓ {len(KEYWORD_ABILITIES)} keyword abilities loaded")
# Test get_all_keywords
all_keywords = get_all_keywords()
assert len(all_keywords) > 0, "get_all_keywords should return keywords"
print(f" ✓ {len(all_keywords)} total keywords loaded")
# Test get_keyword_info
info = get_keyword_info("flying")
assert info is not None, "get_keyword_info should return info"
assert "rule" in info, "Keyword info should have 'rule'"
assert "definition" in info, "Keyword info should have 'definition'"
print(f" ✓ Keyword info for 'flying': rule={info['rule'][:40]}...")
# Test get_keyword_type
type_flying = get_keyword_type("flying")
assert type_flying == "keyword_ability", f"Expected keyword_ability, got {type_flying}"
type_cast = get_keyword_type("cast")
assert type_cast == "keyword_action", f"Expected keyword_action, got {type_cast}"
print(f" ✓ Keyword type for 'flying': {type_flying}")
print(f" ✓ Keyword type for 'cast': {type_cast}")
print(" ✓ All keyword database tests passed!\n")
def test_keyword_validator():
"""Test the keyword validator."""
print("=" * 60)
print("TEST: Keyword Validator")
print("=" * 60)
validator = KeywordValidator()
# Test is_valid_keyword
assert validator.is_valid_keyword("flying"), "flying should be valid"
assert validator.is_valid_keyword("haste"), "haste should be valid"
assert not validator.is_valid_keyword("notarealkeyword"), "notarealkeyword should be invalid"
print(" ✓ is_valid_keyword works correctly")
# Test find_keywords_in_text
text = "Flying creatures can't be blocked except by flying creatures with flying abilities."
found = validator.find_keywords_in_text(text)
assert "flying" in found, "flying should be found"
assert found["flying"] == 3, f"Expected 3 'flying', got {found['flying']}"
print(f" ✓ find_keywords_in_text found {found}")
# Test validate_card_text
card_text = "Flying, trample. Haste. When this creature attacks, it deals extra damage."
errors = validator.validate_card_text(card_text)
# No errors expected for valid keywords
print(f" ✓ validate_card_text: {len(errors)} errors (expected 0)")
# Test check_for_misspelled_keywords
misspelled = validator.check_for_misspelled_keywords("I want to fly with this haste creature.")
# "fly" should suggest "flying"
print(f" ✓ check_for_misspelled_keywords found {len(misspelled)} potential misspellings")
# Test export_keywords
exported = validator.export_keywords()
assert "total_keywords" in exported, "export_keywords should have total_keywords"
assert "ability_words" in exported, "export_keywords should have ability_words"
assert "keyword_actions" in exported, "export_keywords should have keyword_actions"
assert "keyword_abilities" in exported, "export_keywords should have keyword_abilities"
print(f" ✓ export_keywords has all expected fields")
print(" ✓ All keyword validator tests passed!\n")
def test_rules_engine():
"""Test the rules engine."""
print("=" * 60)
print("TEST: Rules Engine")
print("=" * 60)
engine = RulesEngine()
# Test validate_card with a valid creature
valid_card = {
"name": "Garruk the Wreathshaper",
"text": "Flying, trample. When Garruk enters, create a 1/1 green Elf creature token.",
"type": "CREATURE",
"power_toughness": (6, 6),
"color": ["GREEN"],
"abilities": ["flying", "trample"],
}
errors = engine.validate_card(valid_card)
# Some errors expected (text analysis, etc.)
print(f" ✓ validate_card returned {len(errors)} errors")
# Test validate_action with a valid attack
valid_attack = {
"type": "attack",
"attacker": {
"name": "Garruk the Wreathshaper",
"type": "CREATURE",
"power": 6,
"toughness": 6,
"abilities": ["flying", "trample"],
},
"blocking_creatures": [
{
"name": "Garruk the Wreathshaper",
"type": "CREATURE",
"power": 6,
"toughness": 6,
"abilities": ["flying", "trample"],
}
],
}
errors = engine.validate_action(valid_attack)
# Some errors expected (flying creature can't be blocked)
print(f" ✓ validate_action returned {len(errors)} errors")
# Test get_rule_text
rule = engine.get_rule_text("702.9")
assert rule is not None, "get_rule_text should return a result"
print(f" ✓ get_rule_text returned: {rule[:80]}...")
# Test get_keyword_info_summary
summary = engine.get_keyword_info_summary("flying")
assert summary is not None, "get_keyword_info_summary should return a summary"
assert summary["keyword"] == "flying", "Summary should have correct keyword"
assert summary["rule"] is not None, "Summary should have rule"
print(f" ✓ get_keyword_info_summary works: {summary}")
# Test search_keywords
results = engine.search_keywords("flying")
assert len(results) > 0, "search_keywords should find matches"
print(f" ✓ search_keywords found {len(results)} matches for 'flying'")
# Test validate_game_state
valid_state = {
"players": [
{
"name": "Player 1",
"hand": [],
"creatures": [],
},
{
"name": "Player 2",
"hand": [],
"creatures": [],
},
],
"zones": {
"stack": [],
},
}
errors = engine.validate_game_state(valid_state)
# No errors expected for valid state
print(f" ✓ validate_game_state returned {len(errors)} errors")
print(" ✓ All rules engine tests passed!\n")
def test_integration():
"""Integration test with the full pipeline."""
print("=" * 60)
print("TEST: Integration")
print("=" * 60)
# End-to-end test: Create a card, validate it, analyze its keywords
engine = RulesEngine()
card = {
"name": "Mighty Hero",
"text": "Flying, trample, trample over planeswalkers. Haste. When this creature enters, create a 1/1 token.",
"type": "CREATURE",
"power_toughness": (4, 4),
"color": ["RED"],
"abilities": ["flying", "trample", "haste"],
}
# Validate card
errors = engine.validate_card(card)
print(f" Card validation: {len(errors)} errors")
# Find keywords in card text
keywords = engine.validator.find_keywords_in_text(card["text"])
print(f" Keywords found in card text: {list(keywords.keys())}")
# Get keyword info for each found keyword
for keyword in keywords:
info = engine.get_keyword_info_summary(keyword)
print(f" - {keyword}: {info.get('rule', 'N/A')}")
# Validate an attack
attack = {
"type": "attack",
"attacker": {
"name": "Mighty Hero",
"type": "CREATURE",
"power": 4,
"toughness": 4,
"abilities": ["flying", "trample"],
},
"blocking_creatures": [
{
"name": "Opponent's Flying Creature",
"type": "CREATURE",
"power": 3,
"toughness": 3,
"abilities": ["flying"],
}
],
}
errors = engine.validate_action(attack)
print(f" Attack validation: {len(errors)} errors")
for error in errors:
print(f" - {error['message']}")
print(" ✓ Integration test passed!\n")
if __name__ == "__main__":
print("\n" + "=" * 60)
print("Magic: The Gathering Rules Engine - Test Suite")
print("=" * 60 + "\n")
test_keyword_database()
test_keyword_validator()
test_rules_engine()
test_integration()
print("=" * 60)
print("ALL TESTS PASSED!")
print("=" * 60)