295 lines
11 KiB
Python
295 lines
11 KiB
Python
"""
|
||
卡牌系统测试
|
||
"""
|
||
import pytest
|
||
from kards_battle.core.enums import Nation, Rarity
|
||
from kards_battle.cards.card import UnitCard
|
||
from kards_battle.cards.deck import DeckBuilder, DeckValidationError
|
||
from kards_battle.cards.card_manager import CardManager
|
||
from kards_battle.cards.placeholder_cards import create_placeholder_unit_cards, create_test_deck_cards
|
||
from kards_battle.game.game_engine import GameEngine
|
||
|
||
|
||
class TestCardSystem:
|
||
"""卡牌系统基础测试"""
|
||
|
||
def test_unit_card_creation(self):
|
||
"""测试单位卡牌创建"""
|
||
card = UnitCard(
|
||
name="德军掷弹兵",
|
||
cost=2,
|
||
nation=Nation.GERMANY,
|
||
rarity=Rarity.COMMON,
|
||
unit_definition_id="ger_infantry_grenadier",
|
||
description="基础德军步兵单位"
|
||
)
|
||
|
||
assert card.name == "德军掷弹兵"
|
||
assert card.stats.cost == 2
|
||
assert card.stats.nation == Nation.GERMANY
|
||
assert card.stats.rarity == Rarity.COMMON
|
||
assert card.unit_definition_id == "ger_infantry_grenadier"
|
||
|
||
def test_placeholder_cards_creation(self):
|
||
"""测试占位卡牌创建"""
|
||
cards = create_placeholder_unit_cards()
|
||
|
||
assert len(cards) == 10
|
||
|
||
# 检查所有卡牌都是德国的
|
||
for card in cards:
|
||
assert card.stats.nation == Nation.GERMANY
|
||
assert card.stats.rarity == Rarity.COMMON
|
||
assert card.unit_definition_id == "ger_infantry_grenadier"
|
||
|
||
def test_deck_validation_success(self):
|
||
"""测试卡组验证成功案例"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
|
||
|
||
# 应该能成功创建卡组
|
||
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
|
||
|
||
assert deck.major_nation == Nation.GERMANY
|
||
assert deck.minor_nation == Nation.ITALY
|
||
assert len(deck.cards) == 39
|
||
|
||
# 获取统计信息
|
||
stats = deck.get_statistics()
|
||
assert stats['total_cards'] == 39
|
||
assert stats['major_nation'] == Nation.GERMANY
|
||
assert stats['minor_nation'] == Nation.ITALY
|
||
|
||
def test_deck_validation_invalid_count(self):
|
||
"""测试卡组验证:卡牌数量错误"""
|
||
cards = create_placeholder_unit_cards()[:5] # 只有5张卡
|
||
|
||
with pytest.raises(DeckValidationError, match="卡组必须包含39张卡牌"):
|
||
DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
|
||
|
||
def test_deck_validation_invalid_major_nation(self):
|
||
"""测试卡组验证:无效主国"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
|
||
|
||
with pytest.raises(DeckValidationError, match="主国.*不在允许的主要国家列表中"):
|
||
DeckBuilder.build_deck(Nation.FINLAND, Nation.ITALY, cards) # Finland不是主要国家
|
||
|
||
def test_deck_validation_same_nations(self):
|
||
"""测试卡组验证:主国和盟国相同"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.GERMANY)
|
||
|
||
with pytest.raises(DeckValidationError, match="主国和盟国不能相同"):
|
||
DeckBuilder.build_deck(Nation.GERMANY, Nation.GERMANY, cards)
|
||
|
||
def test_card_manager_initialization(self):
|
||
"""测试卡牌管理器初始化"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
|
||
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
|
||
|
||
manager = CardManager(deck)
|
||
|
||
assert manager.cards_remaining_in_deck() == 39
|
||
assert manager.hand_size() == 0
|
||
assert len(manager.discard_pile) == 0
|
||
assert manager.fatigue_damage == 1
|
||
assert not manager.strategic_deployment_completed
|
||
|
||
def test_card_manager_initial_draw(self):
|
||
"""测试初始摸牌"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
|
||
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
|
||
|
||
manager = CardManager(deck)
|
||
drawn_cards = manager.initial_draw(5)
|
||
|
||
assert len(drawn_cards) == 5
|
||
assert manager.hand_size() == 5
|
||
assert manager.cards_remaining_in_deck() == 34
|
||
|
||
def test_card_manager_strategic_deployment(self):
|
||
"""测试战略调度"""
|
||
cards = create_test_deck_cards(Nation.GERMANY, Nation.ITALY)
|
||
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, cards)
|
||
|
||
manager = CardManager(deck)
|
||
initial_cards = manager.initial_draw(4)
|
||
|
||
# 选择重抽2张牌
|
||
cards_to_mulligan = initial_cards[:2]
|
||
new_cards = manager.strategic_deployment(cards_to_mulligan)
|
||
|
||
assert len(new_cards) == 2
|
||
assert manager.hand_size() == 4 # 仍然是4张牌
|
||
assert manager.strategic_deployment_completed
|
||
|
||
# 不应该能再次进行战略调度
|
||
with pytest.raises(ValueError, match="战略调度已经完成"):
|
||
manager.strategic_deployment([])
|
||
|
||
def test_card_manager_fatigue_system(self):
|
||
"""测试疲劳系统"""
|
||
# 创建一个小卡组用于快速测试疲劳
|
||
small_cards = []
|
||
# 主国卡(27张)
|
||
for i in range(9): # 9种不同的卡
|
||
for j in range(3): # 每种3张
|
||
card = UnitCard(
|
||
name=f"德军测试卡{i}",
|
||
cost=1,
|
||
nation=Nation.GERMANY,
|
||
rarity=Rarity.COMMON,
|
||
unit_definition_id="ger_infantry_grenadier",
|
||
description="测试用德军卡牌"
|
||
)
|
||
small_cards.append(card)
|
||
|
||
# 盟国卡(12张)
|
||
for i in range(4): # 4种不同的卡
|
||
for j in range(3): # 每种3张
|
||
card = UnitCard(
|
||
name=f"意军测试卡{i}",
|
||
cost=1,
|
||
nation=Nation.ITALY,
|
||
rarity=Rarity.COMMON,
|
||
unit_definition_id="ger_infantry_grenadier",
|
||
description="测试用意军卡牌"
|
||
)
|
||
small_cards.append(card)
|
||
|
||
deck = DeckBuilder.build_deck(Nation.GERMANY, Nation.ITALY, small_cards)
|
||
|
||
manager = CardManager(deck)
|
||
|
||
# 抽完所有牌
|
||
while manager.can_draw_safely():
|
||
manager.draw_card()
|
||
|
||
assert manager.cards_remaining_in_deck() == 0
|
||
|
||
# 记录疲劳伤害
|
||
fatigue_damages = []
|
||
def hq_damage_callback(damage):
|
||
fatigue_damages.append(damage)
|
||
|
||
# 继续抽牌应该造成疲劳伤害
|
||
result = manager.draw_card(hq_damage_callback)
|
||
assert result is None
|
||
assert len(fatigue_damages) == 1
|
||
assert fatigue_damages[0] == 1
|
||
assert manager.fatigue_damage == 2 # 递增
|
||
|
||
# 再次抽牌
|
||
result = manager.draw_card(hq_damage_callback)
|
||
assert result is None
|
||
assert len(fatigue_damages) == 2
|
||
assert fatigue_damages[1] == 2
|
||
assert manager.fatigue_damage == 3
|
||
|
||
|
||
class TestGameEngine:
|
||
"""游戏引擎测试"""
|
||
|
||
def test_game_engine_creation(self):
|
||
"""测试游戏引擎创建"""
|
||
engine = GameEngine(debug_mode=True)
|
||
|
||
game_state = engine.create_test_game(
|
||
"Player1", Nation.GERMANY, Nation.ITALY,
|
||
"Player2", Nation.USA, Nation.UK
|
||
)
|
||
|
||
assert game_state is not None
|
||
assert game_state.player1.name == "Player1"
|
||
assert game_state.player2.name == "Player2"
|
||
assert game_state.player1.major_nation == Nation.GERMANY
|
||
assert game_state.player1.minor_nation == Nation.ITALY
|
||
assert game_state.player2.major_nation == Nation.USA
|
||
assert game_state.player2.minor_nation == Nation.UK
|
||
|
||
def test_strategic_deployment_phase(self):
|
||
"""测试战略调度阶段"""
|
||
engine = GameEngine(debug_mode=True)
|
||
game_state = engine.create_test_game()
|
||
|
||
# 初始阶段应该是战略调度
|
||
from kards_battle.game.game_state import GameStatePhase
|
||
assert game_state.phase == GameStatePhase.STRATEGIC_DEPLOYMENT
|
||
|
||
# 玩家应该可以进行战略调度
|
||
assert game_state.can_perform_strategic_deployment(0)
|
||
assert game_state.can_perform_strategic_deployment(1)
|
||
|
||
# 玩家1进行战略调度(不重抽任何牌)
|
||
player1_hand = game_state.player1.card_manager.get_hand_copy()
|
||
new_cards = engine.perform_strategic_deployment(0, [])
|
||
assert len(new_cards) == 0
|
||
assert not game_state.can_perform_strategic_deployment(0)
|
||
|
||
# 玩家2进行战略调度(重抽1张牌)
|
||
player2_hand = game_state.player2.card_manager.get_hand_copy()
|
||
cards_to_mulligan = [player2_hand[0]]
|
||
new_cards = engine.perform_strategic_deployment(1, cards_to_mulligan)
|
||
assert len(new_cards) == 1
|
||
assert not game_state.can_perform_strategic_deployment(1)
|
||
|
||
# 现在应该可以开始正式游戏
|
||
engine.start_main_game()
|
||
assert game_state.phase == GameStatePhase.GAME_ACTIVE
|
||
|
||
def test_game_flow(self):
|
||
"""测试基本游戏流程"""
|
||
engine = GameEngine(debug_mode=True)
|
||
game_state = engine.create_test_game()
|
||
|
||
# 跳过战略调度,直接开始游戏
|
||
engine.start_main_game()
|
||
|
||
# 检查初始状态
|
||
assert game_state.current_turn == 1
|
||
assert game_state.active_player_id == 0 # 先手
|
||
|
||
# 当前玩家应该有kredits
|
||
current_player = game_state.get_current_player()
|
||
assert current_player.kredits > 0
|
||
assert current_player.kredits_slot > 0
|
||
|
||
# 获取可打出的卡牌
|
||
playable_cards = engine.get_playable_cards(0)
|
||
# 第一回合可能没有可打出的卡牌,这是正常的
|
||
assert isinstance(playable_cards, list)
|
||
|
||
# 结束回合
|
||
engine.end_turn(0)
|
||
|
||
# 应该轮到玩家2
|
||
assert game_state.active_player_id == 1
|
||
|
||
# 玩家2也应该有kredits
|
||
player2 = game_state.get_current_player()
|
||
assert player2.kredits > 0
|
||
|
||
def test_card_playing(self):
|
||
"""测试打牌功能"""
|
||
engine = GameEngine(debug_mode=True)
|
||
game_state = engine.create_test_game()
|
||
engine.start_main_game()
|
||
|
||
# 获取当前玩家的可打出卡牌
|
||
current_player_id = game_state.active_player_id
|
||
playable_cards = engine.get_playable_cards(current_player_id)
|
||
|
||
if playable_cards:
|
||
# 尝试打出一张单位卡
|
||
for card in playable_cards:
|
||
if hasattr(card, 'unit_definition_id'): # 是单位卡
|
||
initial_kredits = game_state.get_current_player().kredits
|
||
success = engine.play_unit_card(current_player_id, card)
|
||
|
||
if success:
|
||
# 检查kredits是否扣除
|
||
final_kredits = game_state.get_current_player().kredits
|
||
assert final_kredits == initial_kredits - card.stats.cost
|
||
|
||
# 检查卡牌是否从手牌移除
|
||
current_hand = engine.get_player_hand(current_player_id)
|
||
assert card not in current_hand
|
||
break |