Coverage for app/pycardgame/tests/base/test_game.py: 100.0%
214 statements
« prev ^ index » next coverage.py v7.6.1, created at 2025-04-07 20:57 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2025-04-07 20:57 +0000
1# PyCardGame - A base library for creating card games in Python
2# Copyright (C) 2025 Popa-42
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <https://www.gnu.org/licenses/>.
17from typing import Literal
19import pytest
21from ...src.base import (
22 CardMeta,
23 DeckMeta,
24 GenericCard,
25 GenericDeck,
26 GenericGame,
27 GenericPlayer,
28)
30T_Ranks = Literal["1", "2", "3"]
31T_Suits = Literal["Red", "Green", "Blue"]
34class DummyCard(
35 GenericCard[T_Ranks, T_Suits],
36 metaclass=CardMeta,
37 rank_type=T_Ranks,
38 suit_type=T_Suits
39):
40 def effect(self, game, player, *args): # pragma: no cover
41 pass
44class DummyDeck(
45 GenericDeck[DummyCard],
46 metaclass=DeckMeta,
47 card_type=DummyCard
48):
49 pass
52class DummyPlayer(GenericPlayer[DummyCard]):
53 pass
56class DummyGame(GenericGame[DummyCard]):
57 def __init__(self, *players, draw_pile=None, discard_pile=None, trump=None,
58 hand_size=4, starting_player_index=0, do_not_shuffle=False):
59 super().__init__(DummyCard, DummyDeck, draw_pile, discard_pile, trump,
60 hand_size, starting_player_index, do_not_shuffle,
61 *players)
63 def check_valid_play(self, card1, card2):
64 return card1.suit == card2.suit or card1.rank == card2.rank
66 def start_game(self): ...
67 def end_game(self): ...
70def test_game_init():
71 deck = DummyDeck()
72 empty_deck = DummyDeck(cards=[])
73 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
75 game = DummyGame(*players, draw_pile=deck, discard_pile=empty_deck,
76 trump="Green", hand_size=2, starting_player_index=1)
77 assert game.draw_pile == deck
78 assert game.discard_pile == empty_deck
79 assert game.trump == "Green"
80 assert game.hand_size == 2
81 assert game.players == players
82 assert game.current_player_index == 1
84 # Invalid trump suit
85 with pytest.raises(ValueError):
86 DummyGame(*players, trump="InvalidSuit")
88 # Invalid player count
89 with pytest.raises(ValueError):
90 DummyGame(*players, starting_player_index=10)
93def test_game_check_valid_play():
94 card1 = DummyCard(0, 0)
95 card2 = DummyCard(0, 1)
96 card3 = DummyCard(1, 0)
97 game = DummyGame()
99 assert game.check_valid_play(card1, card2) is True
100 assert game.check_valid_play(card1, card3) is True
101 assert game.check_valid_play(card2, card3) is False
104def test_game_discard_cards():
105 game = DummyGame()
106 discard_card = DummyCard(0, 0)
107 game.discard_cards(discard_card)
108 assert discard_card in game.discard_pile
111def test_game_get_discard_pile():
112 deck = DummyDeck()
113 discard_pile = DummyDeck(cards=[])
114 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
115 game = DummyGame(*players, draw_pile=deck, discard_pile=discard_pile)
116 assert game.get_discard_pile() == discard_pile
119def test_game_get_top_card():
120 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
121 game = DummyGame(*players)
122 top_card = game.get_top_card()
123 assert top_card is None
124 game.discard_pile.add(DummyCard(0, 0))
125 top_card = game.get_top_card()
126 assert isinstance(top_card, DummyCard)
127 assert top_card in game.draw_pile
130def test_game_reshuffle_discard_pile():
131 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
132 deck = DummyDeck([])
133 discard_pile = DummyDeck([DummyCard(0, 0), DummyCard(1, 1)])
134 game = DummyGame(*players, draw_pile=deck, discard_pile=discard_pile)
135 game.reshuffle_discard_pile()
136 assert len(game.draw_pile) > 0
137 assert len(game.discard_pile) == 0
138 assert all(card in game.draw_pile for card in discard_pile.cards)
141def test_game_draw_cards():
142 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
143 deck = DummyDeck([DummyCard(0, 0), DummyCard(1, 1)])
144 discard_pile = DummyDeck([DummyCard(2, 2)])
145 game = DummyGame(*players, draw_pile=deck, discard_pile=discard_pile)
146 game.draw_cards(n=2)
147 assert len(players[0].hand) == 2
148 assert len(game.draw_pile) == 0
149 assert len(game.discard_pile) == 1
150 game.draw_cards(players[0])
151 assert len(players[0].hand) == 3
154def test_game_deal_initial_cards():
155 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
156 deck = DummyDeck()
157 game = DummyGame(*players, hand_size=2)
158 game.deal_initial_cards()
159 assert all(len(player.hand) == 2 for player in players)
160 assert len(game.draw_pile) < len(deck)
163def test_game_add_players():
164 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
165 game = DummyGame(*players, hand_size=2)
166 new_players = [DummyPlayer("Charlie"), DummyPlayer("David")]
167 game.add_players(*new_players)
168 assert game.players == players + new_players
171def test_game_remove_players():
172 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
173 game = DummyGame(*players, hand_size=2)
174 game.remove_players(players[0])
175 assert game.players == players[1:]
178def test_game_deal():
179 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
181 game = DummyGame(*players, hand_size=2)
182 game.deal(3)
183 assert all(len(player.hand) == 3 for player in game.players)
186def test_game_shuffle():
187 deck = DummyDeck()
188 game = DummyGame(draw_pile=deck)
189 game.shuffle()
190 assert list(game.draw_pile) != sorted(game.draw_pile)
191 assert len(game.draw_pile) == len(deck)
192 assert all(card in deck for card in game.draw_pile)
195def test_game_play():
196 player1 = DummyPlayer("Alice", [DummyCard(0, 0)])
197 player2 = DummyPlayer("Bob", [DummyCard(1, 1)])
198 players = [player1, player2]
199 game = DummyGame(*players, hand_size=2)
200 dealt_card = player1.hand[0]
201 game.discard_cards(dealt_card)
202 assert game.play_card(dealt_card, player1) is True
203 assert len(player1.hand) == 0
204 assert len(game.discard_pile) == 2
205 assert (dealt_card in game.discard_pile and dealt_card not in
206 player1.hand)
208 assert game.play_card(player2.hand[0], player2) is False
211def test_game_get_trump():
212 game1 = DummyGame()
213 assert game1.get_trump() is None
215 game2 = DummyGame(trump="Red")
216 assert game2.get_trump() == "Red"
219def test_game_set_trump():
220 game = DummyGame()
221 game.set_trump("Red")
222 assert game.trump == "Red"
224 with pytest.raises(ValueError):
225 game.set_trump("InvalidSuit")
228def test_game_apply_trump():
229 player1 = DummyPlayer("Alice", [DummyCard(0, 0)])
230 player2 = DummyPlayer("Bob", [DummyCard(1, 1)])
231 players = [player1, player2]
232 deck = DummyDeck([DummyCard(0, 0), DummyCard(1, 1)])
233 discard_pile = DummyDeck([DummyCard(0, 2), DummyCard(1, 2)])
234 game = DummyGame(*players, trump="Red", draw_pile=deck,
235 discard_pile=discard_pile)
237 game.apply_trump()
239 assert all(card.is_trump() for card in game.draw_pile
240 if card.get_suit() == "Red")
241 assert not any(card.is_trump() for card in game.draw_pile
242 if card.get_suit() != "Red")
244 assert all(card.is_trump() for card in game.discard_pile
245 if card.get_suit() == "Red")
246 assert not any(card.is_trump() for card in game.discard_pile
247 if card.get_suit() != "Red")
249 assert all(card.trump for player in game.players for card in player.hand
250 if card.get_suit() == "Red")
251 assert not any(card.trump for player in game.players for card in
252 player.hand if card.get_suit() != "Red")
255def test_game_change_trump():
256 player1 = DummyPlayer("Alice", [DummyCard(0, 0)])
257 player2 = DummyPlayer("Bob", [DummyCard(1, 1)])
258 players = [player1, player2]
259 deck = DummyDeck([DummyCard(0, 0), DummyCard(1, 1)])
260 discard_pile = DummyDeck([DummyCard(0, 2), DummyCard(1, 2)])
261 game = DummyGame(*players, trump="Red", draw_pile=deck,
262 discard_pile=discard_pile)
264 game.change_trump("Green")
265 assert game.trump == "Green"
267 assert all(card.trump for card in game.draw_pile
268 if card.get_suit() == "Green")
269 assert not any(card.trump for card in game.draw_pile
270 if card.get_suit() != "Green")
272 assert all(card.trump for card in game.discard_pile
273 if card.get_suit() == "Green")
274 assert not any(card.trump for card in game.discard_pile
275 if card.get_suit() != "Green")
277 assert all(card.trump for player in game.players for card in player.hand
278 if card.get_suit() == "Green")
279 assert not any(card.trump for player in game.players for card in
280 player.hand if card.get_suit() != "Green")
282 with pytest.raises(ValueError):
283 game.change_trump("InvalidSuit")
286def test_game_get_current_player():
287 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
288 game = DummyGame(*players, hand_size=2)
289 assert game.get_current_player() == players[0]
292def test_game_set_current_player():
293 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
294 game = DummyGame(*players, hand_size=2)
295 game.set_current_player(players[1])
296 assert game.current_player_index == 1
298 game.set_current_player(0)
299 assert game.current_player_index == 0
301 with pytest.raises(ValueError):
302 game.set_current_player(10)
304 with pytest.raises(TypeError):
305 game.set_current_player("InvalidPlayer") # type: ignore
308def test_game_get_players():
309 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
310 game = DummyGame(*players, hand_size=2)
311 assert game.get_players() == players
314def test_game_get_deck():
315 deck = DummyDeck()
316 game = DummyGame(draw_pile=deck)
317 assert game.get_draw_pile() == deck
320def test_game_set_deck():
321 deck = DummyDeck()
322 game = DummyGame(draw_pile=DummyDeck([]))
323 assert game.draw_pile != deck
324 game.set_draw_pile(deck)
325 assert game.draw_pile == deck
328def test_game_str():
329 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
330 game = DummyGame(*players, hand_size=2)
331 assert str(game) == "Game of 2 players"
334def test_game_repr():
335 deck = DummyDeck()
336 discard_pile = DummyDeck([])
337 players = [DummyPlayer("Alice"), DummyPlayer("Bob")]
338 game = DummyGame(*players, draw_pile=deck, discard_pile=discard_pile,
339 trump="Green", hand_size=2, starting_player_index=1)
340 game_repr = repr(game)
342 assert game_repr.startswith("DummyGame(card_type=<class ")
343 assert "deck_type=<class " in game_repr
344 assert "draw_pile=DummyDeck(card_type=<class " in game_repr
345 assert "cards=[DummyCard(" in game_repr
346 assert "DummyCard(rank=0, suit=0)" in game_repr
347 assert "discard_pile=DummyDeck(card_type=<class " in game_repr
348 assert "trump='Green'" in game_repr
349 assert "hand_size=2" in game_repr
350 assert "starting_player_index=1" in game_repr
351 assert "DummyPlayer('Alice', hand=[], score=0)" in game_repr
352 assert "DummyPlayer('Alice', hand=[], score=0)" in game_repr