Skip to content

Commit ca21b98

Browse files
fix failing test + refactors to 2 tests to retrigger actions runs #13
1 parent 837809a commit ca21b98

File tree

3 files changed

+125
-58
lines changed

3 files changed

+125
-58
lines changed

tests/test_chmengine.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ def test_mod_level_imports(self) -> None:
5757
def test_from_imports(self) -> None:
5858
"""test from chmengine imports"""
5959
# pylint: disable=import-outside-toplevel
60-
from chmengine import CMHMEngine, CMHMEngine2, PlayCMHMEngine, Pick, Quartney
60+
from chmengine import CMHMEngine, CMHMEngine2, PlayCMHMEngine, Pick, Quartney, CMHMEngine2PoolExecutor
6161
_dir_1 = dir()
6262
self.assertEqual(sorted(_dir_1), sorted(self._engines + self._pick + self._engine_manager + self._dir))
6363
self.assertIsInstance(CMHMEngine, Callable)
6464
self.assertIsInstance(CMHMEngine2, Callable)
6565
self.assertIsInstance(PlayCMHMEngine, Callable)
6666
self.assertIsInstance(Pick, Callable)
6767
self.assertIsInstance(Quartney, Callable)
68+
self.assertIsInstance(CMHMEngine2PoolExecutor, Callable)
6869

6970
def test_star_imports(self) -> None:
7071
"""test from chmengine import *"""

tests/test_cmhmey2.py

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from io import StringIO
33
from os import path
44
from time import perf_counter
5-
from typing import Iterable, Optional
5+
from typing import Iterable, List, Optional, Tuple
66
from unittest import TestCase
77

88
from chess import Board, Move, pgn
@@ -150,37 +150,26 @@ def test_update_q_values(self) -> None:
150150

151151
def test_pick_move(self) -> None:
152152
"""Tests pick_move method."""
153-
start = perf_counter()
154-
pick = self.engine.pick_move()
155-
duration_first = (perf_counter() - start) / self.engine.board.legal_moves.count()
156-
print(f"{self.engine.fen()} pick_move call: ({pick[0].uci()}, {pick[1]:.2f}) {duration_first:.3f}s/branch")
157-
init_w_moves = list(self.engine.board.legal_moves)
153+
pick: Pick
154+
duration_per_branch: float
155+
duration: float
156+
branch_count: int
157+
pick, duration_per_branch, duration, branch_count = self.measure_pick(message=1)
158+
init_w_moves: List[Move] = list(self.engine.board.legal_moves)
158159
move: Move
159-
first_time_pick_times = [duration_first]
160-
init_board_pick_times = [duration_first]
161-
revisit_pick_times = []
160+
first_time_pick_times = [duration_per_branch] # list of all times a position was seen for the first time.
161+
init_board_pick_times = [duration_per_branch] # list of all times the first board position was seen.
162+
revisit_pick_times = [] # lists all the times the init board position was revisited.
162163
new_duration = 999999.99
163-
for i, move in enumerate(init_w_moves[:len(init_w_moves) // 2], 2):
164+
for i, move in enumerate(init_w_moves[:len(init_w_moves) // 2], 1):
164165
self.engine.board.push(move)
165-
start = perf_counter()
166-
response_pick = self.engine.pick_move()
167-
duration_rep_pick = (perf_counter() - start) / self.engine.board.legal_moves.count()
166+
response_pick, duration_rep_pick, duration, branch_count = self.measure_pick(move=move, message=2)
168167
first_time_pick_times.append(duration_rep_pick)
169-
print(
170-
f"'{move.uci()}' -> '{self.engine.fen()}' pick_move call: "
171-
f"({response_pick[0].uci()}, {response_pick[1]:.2f}) {duration_rep_pick:.3f}s/branch"
172-
)
173168
self.engine.board.pop()
174-
start = perf_counter()
175-
new_pick = self.engine.pick_move()
176-
new_duration = (perf_counter() - start) / self.engine.board.legal_moves.count()
169+
new_pick, new_duration, duration, branch_count = self.measure_pick(i=i, message=3)
177170
init_board_pick_times.append(new_duration)
178171
revisit_pick_times.append(new_duration)
179-
print(
180-
f"{self.engine.fen()} pick_move call {i}: ({new_pick[0].uci()},"
181-
f" {new_pick[1]:.2f}) {new_duration:.3f}s/branch"
182-
)
183-
self.assertLess(new_duration, duration_first)
172+
self.assertLess(new_duration, duration_per_branch)
184173
avg_duration = mean(init_board_pick_times)
185174
avg_response = mean(first_time_pick_times)
186175
avg_revisit = mean(revisit_pick_times)
@@ -196,6 +185,52 @@ def test_pick_move(self) -> None:
196185
f"mean revisit time: {avg_revisit:.3f}s\npercentiles (0, 1, 10, 25, 50, 75, 90, 99, 100):\n{pre_revisit}"
197186
)
198187

188+
def measure_pick(
189+
self,
190+
i: Optional[int] = None,
191+
move: Optional[Move] = None,
192+
message: int = 0
193+
) -> Tuple[Pick, float, float, int]:
194+
"""
195+
196+
Parameters
197+
----------
198+
i : Optional[int]
199+
move : Optional[Move]
200+
message : int
201+
202+
Returns
203+
-------
204+
Tuple[Pick, float]
205+
"""
206+
branch_count: int = self.engine.board.legal_moves.count()
207+
start: float = perf_counter()
208+
pick: Pick = self.engine.pick_move()
209+
end: float = perf_counter()
210+
duration: float = (end - start)
211+
duration_per_branch: float = duration / branch_count
212+
if message == 1:
213+
print(
214+
f"{self.engine.fen()} initial pick_move call: "
215+
f"({pick[0].uci()}, {pick[1]:.2f}) {duration_per_branch:.3f}s/branch"
216+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
217+
)
218+
elif message == 2:
219+
if move is not None:
220+
print(
221+
f"{move} -> {self.engine.fen()} initial pick_move call: "
222+
f"({pick[0].uci()}, {pick[1]:.2f}) {duration_per_branch:.3f}s/branch"
223+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
224+
)
225+
elif message == 3:
226+
if i is not None:
227+
print(
228+
f"{self.engine.fen()} revisit {i} pick_move call: "
229+
f"({pick[0].uci()}, {pick[1]:.2f}) {duration_per_branch:.3f}s/branch"
230+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
231+
)
232+
return pick, duration_per_branch, duration, branch_count
233+
199234
def test_false_positive_fen(self) -> None:
200235
"""Tests a regression position where a queen was sac-ed to by playing 'e7c5' to defend against a check:
201236

tests/test_cmhmey2_pool_executor.py

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Test Cmhmey Jr.'s Uncle Poole"""
2-
from os import path
2+
from os import cpu_count, path
33
from time import perf_counter
4+
from typing import List, Optional, Tuple
45
from unittest import TestCase
56
from unittest.mock import patch
67

@@ -52,7 +53,6 @@ def test_initialization_default(self):
5253
self.assertIsInstance(self.executor.engine.board, Board)
5354
self.assertEqual(self.executor.engine.board.fen(), self.starting_board.fen())
5455
self.assertEqual(self.executor.engine.depth, 1)
55-
self.assertIsNone(self.executor.max_workers)
5656
self.assertIsInstance(self.executor.engine, CMHMEngine2)
5757

5858
def test_initialization_custom(self):
@@ -61,10 +61,9 @@ def test_initialization_custom(self):
6161
with self.assertRaises(ValueError):
6262
_ = CMHMEngine2PoolExecutor(board=custom_board, depth=3, max_workers=4)
6363
custom_board = Board(MATE_IN_ONE_4)
64-
executor = CMHMEngine2PoolExecutor(board=custom_board, depth=0, max_workers=0)
64+
executor = CMHMEngine2PoolExecutor(board=custom_board, depth=0, max_workers=1)
6565
self.assertEqual(executor.engine.board, custom_board)
6666
self.assertEqual(executor.engine.depth, 0)
67-
self.assertEqual(executor.max_workers, 0)
6867

6968
@patch("chmengine.engines.cmhmey2_pool_executor.CMHMEngine2.pick_move")
7069
def test_pick_move_valid(self, mock_pick_move):
@@ -95,40 +94,26 @@ def test_debug_output(self):
9594

9695
def test_pick_move(self) -> None:
9796
"""Tests pick_move method."""
98-
start = perf_counter()
99-
pick = self.executor.pick_move()
100-
duration_first = (perf_counter() - start) / self.executor.engine.board.legal_moves.count()
101-
print(
102-
f"{self.executor.engine.fen()} pick_move call: ({pick[0].uci()},"
103-
f" {pick[1]:.2f}) {duration_first:.3f}s/branch"
104-
)
105-
init_w_moves = list(self.executor.engine.board.legal_moves)
97+
pick: Pick
98+
duration_per_branch: float
99+
duration: float
100+
branch_count: int
101+
pick, duration_per_branch, duration, branch_count = self.measure_pick(message=1)
102+
init_w_moves: List[Move] = list(self.executor.engine.board.legal_moves)
106103
move: Move
107-
first_time_pick_times = [duration_first]
108-
init_board_pick_times = [duration_first]
109-
revisit_pick_times = []
104+
first_time_pick_times = [duration_per_branch] # list of all times a position was seen for the first time.
105+
init_board_pick_times = [duration_per_branch] # list of all times the first board position was seen.
106+
revisit_pick_times = [] # lists all the times the init board position was revisited.
110107
new_duration = 999999.99
111-
for i, move in enumerate(init_w_moves[:len(init_w_moves) // 2], 2):
112-
self.executor.engine.board.push(move)
113-
start = perf_counter()
114-
response_pick = self.executor.pick_move()
115-
duration_rep_pick = (perf_counter() - start) / self.executor.engine.board.legal_moves.count()
108+
for i, move in enumerate(init_w_moves[:len(init_w_moves) // 2], 1):
109+
self.executor.push(move)
110+
response_pick, duration_rep_pick, duration, branch_count = self.measure_pick(move=move, message=2)
116111
first_time_pick_times.append(duration_rep_pick)
117-
print(
118-
f"'{move.uci()}' -> '{self.executor.engine.fen()}' pick_move call: "
119-
f"({response_pick[0].uci()}, {response_pick[1]:.2f}) {duration_rep_pick:.3f}s/branch"
120-
)
121112
self.executor.engine.board.pop()
122-
start = perf_counter()
123-
new_pick = self.executor.pick_move()
124-
new_duration = (perf_counter() - start) / self.executor.engine.board.legal_moves.count()
113+
new_pick, new_duration, duration, branch_count = self.measure_pick(i=i, message=3)
125114
init_board_pick_times.append(new_duration)
126115
revisit_pick_times.append(new_duration)
127-
print(
128-
f"{self.executor.engine.fen()} pick_move call {i}: ({new_pick[0].uci()},"
129-
f" {new_pick[1]:.2f}) {new_duration:.3f}s/branch"
130-
)
131-
self.assertLess(new_duration, duration_first)
116+
self.assertLess(new_duration, duration_per_branch)
132117
avg_duration = mean(init_board_pick_times)
133118
avg_response = mean(first_time_pick_times)
134119
avg_revisit = mean(revisit_pick_times)
@@ -143,3 +128,49 @@ def test_pick_move(self) -> None:
143128
print(
144129
f"mean revisit time: {avg_revisit:.3f}s\npercentiles (0, 1, 10, 25, 50, 75, 90, 99, 100):\n{pre_revisit}"
145130
)
131+
132+
def measure_pick(
133+
self,
134+
i: Optional[int] = None,
135+
move: Optional[Move] = None,
136+
message: int = 0
137+
) -> Tuple[Pick, float, float, int]:
138+
"""
139+
140+
Parameters
141+
----------
142+
i : Optional[int]
143+
move : Optional[Move]
144+
message : int
145+
146+
Returns
147+
-------
148+
Tuple[Pick, float]
149+
"""
150+
branch_count: int = self.executor.engine.board.legal_moves.count()
151+
start: float = perf_counter()
152+
pick: Pick = self.executor.pick_move()
153+
end: float = perf_counter()
154+
duration: float = (end - start)
155+
duration_per_branch: float = duration / branch_count
156+
if message == 1:
157+
print(
158+
f"{self.executor.engine.fen()} initial pick_move call: "
159+
f"({pick:+.2f}) {duration_per_branch:.3f}s/branch"
160+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
161+
)
162+
elif message == 2:
163+
if move is not None:
164+
print(
165+
f"{move} -> {self.executor.engine.fen()} initial pick_move call: "
166+
f"({pick:+.2f}) {duration_per_branch:.3f}s/branch"
167+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
168+
)
169+
elif message == 3:
170+
if i is not None:
171+
print(
172+
f"{self.executor.engine.fen()} revisit {i} pick_move call: "
173+
f"({pick:+.2f}) {duration_per_branch:.3f}s/branch"
174+
f" (branch_count={branch_count}, duration={duration:.3f}s)"
175+
)
176+
return pick, duration_per_branch, duration, branch_count

0 commit comments

Comments
 (0)