forked from dscsnu/pingv4
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.py
More file actions
227 lines (172 loc) · 6.44 KB
/
test.py
File metadata and controls
227 lines (172 loc) · 6.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
from pingv4._core import ConnectFourBoard, CellState
def test_initial_board():
"""Test initial board state."""
board = ConnectFourBoard()
assert board.num_rows == 6
assert board.num_cols == 7
assert board.column_heights == [0, 0, 0, 0, 0, 0, 0]
assert board.hash == 0
# All cells should be empty
# Access is column-major: board[col, row]
for col in range(7):
for row in range(6):
assert board[col, row] is None
def test_make_move_returns_new_board():
"""Test that make_move returns a new board (immutability)."""
board1 = ConnectFourBoard()
board2 = board1.make_move(3)
# Original board unchanged (col=3, row=0)
assert board1[3, 0] is None
assert board1.column_heights[3] == 0
# New board has the move (col=3, row=0)
assert board2[3, 0] == CellState.Red
assert board2.column_heights[3] == 1
def test_alternating_players():
"""Test that players alternate Red -> Yellow -> Red."""
board = ConnectFourBoard()
board = board.make_move(0) # Red in col 0
assert board[0, 0] == CellState.Red # col=0, row=0
board = board.make_move(1) # Yellow in col 1
assert board[1, 0] == CellState.Yellow # col=1, row=0
board = board.make_move(2) # Red in col 2
assert board[2, 0] == CellState.Red # col=2, row=0
def test_stacking_pieces():
"""Test that pieces stack in the same column."""
board = ConnectFourBoard()
board = board.make_move(0) # Red at row 0
board = board.make_move(0) # Yellow at row 1
board = board.make_move(0) # Red at row 2
# Access as board[col, row] - all in column 0
assert board[0, 0] == CellState.Red # col=0, row=0
assert board[0, 1] == CellState.Yellow # col=0, row=1
assert board[0, 2] == CellState.Red # col=0, row=2
assert board.column_heights[0] == 3
def test_column_full_error():
"""Test that filling a column raises ValueError."""
board = ConnectFourBoard()
# Fill column 0 (6 rows)
for _ in range(6):
board = board.make_move(0)
# Should raise ValueError on 7th move
try:
board.make_move(0)
assert False, "Expected ValueError"
except ValueError as e:
assert "column is at max capacity" in str(e)
def test_column_out_of_bounds_error():
"""Test that invalid column index raises ValueError."""
board = ConnectFourBoard()
try:
board.make_move(7) # Valid columns are 0-6
assert False, "Expected ValueError"
except ValueError as e:
assert "column index is out of bounds" in str(e)
try:
board.make_move(100)
assert False, "Expected ValueError"
except ValueError as e:
assert "column index is out of bounds" in str(e)
def test_hash_changes_with_moves():
"""Test that board hash changes after moves."""
board1 = ConnectFourBoard()
board2 = board1.make_move(0)
board3 = board2.make_move(1)
# Different board states should have different hashes
assert board1.hash != board2.hash
assert board2.hash != board3.hash
def test_cell_state_enum():
"""Test CellState enum values."""
assert CellState.Red != CellState.Yellow
board = ConnectFourBoard()
board = board.make_move(0)
cell = board[0, 0] # col=0, row=0
assert cell == CellState.Red
assert cell != CellState.Yellow
def test_getitem_bounds():
"""Test __getitem__ with various indices."""
board = ConnectFourBoard()
# Valid indices return None on empty board (col, row)
assert board[0, 0] is None
assert board[6, 5] is None # Corner: col=6, row=5
# Make a move and verify access
board = board.make_move(3) # Drop in col 3
assert board[3, 0] == CellState.Red # col=3, row=0
def test_column_heights_tracking():
"""Test column_heights updates correctly."""
board = ConnectFourBoard()
board = board.make_move(0)
assert board.column_heights == [1, 0, 0, 0, 0, 0, 0]
board = board.make_move(0)
assert board.column_heights == [2, 0, 0, 0, 0, 0, 0]
board = board.make_move(3)
assert board.column_heights == [2, 0, 0, 1, 0, 0, 0]
def test_game_not_in_progress_error():
"""Test that making a move after victory raises ValueError."""
board = ConnectFourBoard()
# Create a horizontal win for Red (4 in a row)
# Red plays cols 0,1,2,3 with Yellow playing cols 0,1,2 in between
board = board.make_move(0) # Red
board = board.make_move(0) # Yellow
board = board.make_move(1) # Red
board = board.make_move(1) # Yellow
board = board.make_move(2) # Red
board = board.make_move(2) # Yellow
board = board.make_move(3) # Red wins with 4 in a row
# Should raise ValueError when trying to move on finished game
try:
board.make_move(4)
assert False, "Expected ValueError"
except ValueError as e:
assert "game is not in progress" in str(e)
def test_draw_game_error():
"""Test that making a move after draw raises ValueError."""
board = ConnectFourBoard()
# fmt: off
draw_sequence = [
2, 0, 3, 1, 5, 4, 2, 6, 3, 0, 6, 5, 5, 4, 4, 1,
0, 2, 1, 3, 2, 6, 3, 5, 4, 0, 6, 1, 0, 0, 1, 1,
2, 2, 4, 3, 3, 4, 5, 5, 6, 0
]
# fmt: on
for move in draw_sequence:
# print(board)
board = board.make_move(move)
# Board is now full (draw state)
# Should raise ValueError "game is not in progress"
try:
board.make_move(3)
assert False, "Expected ValueError for move on drawn game"
except ValueError as e:
assert "game is not in progress" in str(e), (
f"Expected 'game is not in progress', got: {e}"
)
def run_all_tests():
"""Run all tests and report results."""
tests = [
test_initial_board,
test_make_move_returns_new_board,
test_alternating_players,
test_stacking_pieces,
test_column_full_error,
test_column_out_of_bounds_error,
test_hash_changes_with_moves,
test_cell_state_enum,
test_getitem_bounds,
test_column_heights_tracking,
test_game_not_in_progress_error,
# test_draw_game_error,
]
passed = 0
failed = 0
for test in tests:
try:
test()
print(f"✓ {test.__name__}")
passed += 1
except Exception as e:
print(f"✗ {test.__name__}: {e}")
failed += 1
print(f"\n{passed}/{passed + failed} tests passed")
return failed == 0
if __name__ == "__main__":
success = run_all_tests()