From 90945f2e60e6f90969fe1ffef21ab02c544fa941 Mon Sep 17 00:00:00 2001 From: Rh17S15 Date: Mon, 22 Sep 2025 19:43:52 +0200 Subject: [PATCH] continued unittesting --- minimax.py | 8 ---- model.py | 15 +----- printer.py | 3 +- savestate.py | 1 + tests/__init__.py | 0 tests/test_minimax.py | 71 ++++++++++++++++++++++++++++ tests/test_model.py | 97 ++++++++++++++++++++++++++++++++++++++ tests/test_tictactoe.py | 102 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 275 insertions(+), 22 deletions(-) create mode 100644 savestate.py create mode 100644 tests/__init__.py create mode 100644 tests/test_minimax.py create mode 100644 tests/test_model.py create mode 100644 tests/test_tictactoe.py diff --git a/minimax.py b/minimax.py index a5b3ae2..e58210e 100644 --- a/minimax.py +++ b/minimax.py @@ -30,21 +30,13 @@ class Minimax: best_score = score best_move = j, k - '''if best_score == 0 and best_move == (0, 0): # is None: - empty_cells = [(j, k) for j in range(0, len(current_field), 2) for k in range(0, len(current_field), 2) if - current_field[j][k] == " "] - random.seed() - random_move = random.choice(empty_cells) - return 0, random_move[0], random_move[1]''' # else: if best_move is None: return 0, -1, -1 # No available moves else: - # print('The next best move is:', best_move, "score: ", best_score) return best_score, best_move[1], best_move[0] def check_win(self, ifield, player1_char, player2_char): - # nothing 0, 0; draw 1, 1; win player1 1, 0; win player2 0, 1 for j in range(0, len(ifield), 2): if ifield[j][0] == ifield[j][2] == ifield[j][4] == player1_char: return 1, 0 diff --git a/model.py b/model.py index c9b6a3c..dab6dff 100644 --- a/model.py +++ b/model.py @@ -15,16 +15,7 @@ class Model: def do_move(self, x, y, player1, player1_char, player2_char): self.field[y*2][x*2] = (player1_char if player1 else player2_char) - # printer() - # win = check_win(field) - # if win == (0, 0): - # savetosavestate - """player1 = not player1 - turn() controller""" - '''elif win == (1, 1): - elif win == (1, 0): - elif win == (0, 1): - ''' + def loadsavestate(self): if os.path.isfile('./savestate.py'): @@ -51,9 +42,7 @@ class Model: y = int(y * 2) if not self.field[y][x] == " ": if verbose: - # self.printer.occupied() return False else: return True - # else: - # do_move(x, y) + diff --git a/printer.py b/printer.py index 5e04d73..ab06d8c 100644 --- a/printer.py +++ b/printer.py @@ -21,7 +21,8 @@ class Printer: def playermove(self, player1, player1_char, player2_char): while True: - next_move_x = int(input(f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), please choose the x (horizontal) coordinates of your next move: ")) + next_move_x = int(input(f"Player {1 if player1 else 2} ({player1_char if player1 else player2_char}), " + f"please choose the x (horizontal) coordinates of your next move: ")) if next_move_x in list(range(3)): break else: diff --git a/savestate.py b/savestate.py new file mode 100644 index 0000000..787c8b6 --- /dev/null +++ b/savestate.py @@ -0,0 +1 @@ +save = [['X', '|', ' ', '|', ' '], ['—', '+', '—', '+', '—'], [' ', '|', ' ', '|', ' '], ['—', '+', '—', '+', '—'], [' ', '|', ' ', '|', ' ']] \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_minimax.py b/tests/test_minimax.py new file mode 100644 index 0000000..4c4fcf9 --- /dev/null +++ b/tests/test_minimax.py @@ -0,0 +1,71 @@ +import unittest +from minimax import Minimax + +class TestMinimax(unittest.TestCase): + def setUp(self): + self.minimax = Minimax() # Create an instance of your Minimax class + + def test_minimax(self): + current_field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", "X", "|", " "], + ["—", "+", "—", "+", "—"], + ["O", "|", "O", "|", " "]] # Set the current field state + player1_char = 'X' + player2_char = 'O' + + score, x, y = self.minimax.minimax(current_field, True, "X", "O") # Call the minimax method + expected_score = 1 # Adjust the expected score based on the game rules and the field state + expected_x = 4 # Adjust the expected x-coordinate of the best move + expected_y = 4 # Adjust the expected y-coordinate of the best move + + self.assertEqual(score, expected_score) # Check if the score matches the expected value + self.assertEqual(x, expected_x) # Check if the x-coordinate of the best move matches the expected value + self.assertEqual(y, expected_y) # Check if the y-coordinate of the best move matches the expected value + + def test_check_win(self) -> None: + player1_char = 'X' + player2_char = 'O' + + # Testing player 1 win condition + field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["X", "|", " ", "|", " "]] + + result = self.minimax.check_win(field, player1_char, player2_char) + self.assertEqual(result, (1, 0)) + + # Testing player 2 win condition + field = [["O", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["O", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["O", "|", " ", "|", " "]] + + result = self.minimax.check_win(field, player1_char, player2_char) + self.assertEqual(result, (0, 1)) + + # Testing draw condition + field = [["X", "|", "O", "|", "X"], + ["—", "+", "—", "+", "—"], + ["X", "|", "O", "|", "O"], + ["—", "+", "—", "+", "—"], + ["O", "|", "X", "|", "X"]] + + result = self.minimax.check_win(field, player1_char, player2_char) + self.assertEqual(result, (1, 1)) + + # Testing no win condition + field = [[" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + + result = self.minimax.check_win(field, player1_char, player2_char) + self.assertEqual(result, (0, 0)) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_model.py b/tests/test_model.py new file mode 100644 index 0000000..3802ca3 --- /dev/null +++ b/tests/test_model.py @@ -0,0 +1,97 @@ +import unittest +from model import Model +import os.path + + +class TestModel(unittest.TestCase): + def setUp(self) -> None: + # self.model = model.Model() + self.field = [[" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + self.field2 = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + self.model = Model() # Create an instance of your Model class + + def tearDown(self): + if os.path.isfile('./savestate.py'): + os.remove("savestate.py") # Remove the savestate file if it exists + + def test_loadsavestate(self): + f = open("savestate.py", "w") # Create a savestate file + f.write('save = [["X", "|", " ", "|", " "],' + '["—", "+", "—", "+", "—"],' + '[" ", "|", " ", "|", " "],' + '["—", "+", "—", "+", "—"],' + '[" ", "|", " ", "|", " "]]') + f.close() + + self.model.loadsavestate() # Call the loadsavestate method + expected_field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + self.assertEqual(self.model.field, expected_field) # Check if the field matches the expected state + + def test_checksavestate(self): + self.assertFalse(self.model.checksavestate()) # Check if savestate does not exist + + f = open("savestate.py", "w") # Create a savestate file + f.write('save = [["X", "|", " ", "|", " "],' + '["—", "+", "—", "+", "—"],' + '[" ", "|", " ", "|", " "],' + '["—", "+", "—", "+", "—"],' + '[" ", "|", " ", "|", " "]]') + f.close() + + self.assertTrue(self.model.checksavestate()) # Check if savestate exists + + def test_savetosavestate(self): + self.model.field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] # Set the field to a specific state + + self.model.savetosavestate() # Call the savetosavestate method + + f = open("savestate.py", "r") # Read the content of the savestate file + content = f.read() + f.close() + + expected_content = "save = [['X', '|', ' ', '|', ' ']," \ + " ['—', '+', '—', '+', '—'], [' ', '|', ' ', '|', ' ']," \ + " ['—', '+', '—', '+', '—'], [' ', '|', ' ', '|', ' ']]" + self.assertEqual(content, expected_content) # Check if the content matches the expected value + + def test_deletesavestate(self): + f = open("savestate.py", "w") # Create a savestate file + f.close() + + self.model.deletesavestate() # Call the deletesavestate method + + self.assertFalse(os.path.isfile('./savestate.py')) # Check if the savestate file does not exist + + def test_check_move(self): + model = Model() # Create an instance of your Model class + self.assertEqual(model.check_move(0, 0, True), True) + + def test_do_move(self): + model = Model() # Create an instance of your Model class + model.do_move(0, 0, True, "X", "O") # Call the do_move method + expected_field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + self.assertEqual(model.field, expected_field) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_tictactoe.py b/tests/test_tictactoe.py new file mode 100644 index 0000000..8f15c11 --- /dev/null +++ b/tests/test_tictactoe.py @@ -0,0 +1,102 @@ +from unittest.mock import Mock +import unittest +import tictactoe +from unittest.mock import patch + + +class MockPrinter: + # Define mock methods here that mimic the behavior of the Printer class... + def printfield(self, ifield): + pass # Mock methods do nothing + + def occupied(self): + pass + + def aicalc(self): + pass + + def aimoved(self, best_moev): + pass + + def playermove(self, player1, player1_char, player2_char): + next_move = (0, 1) + return next_move + +class TestTicTacToe(unittest.TestCase): + + def setUp(self): + self.game = tictactoe.Tictactoe() + self.game.printer = MockPrinter() + ''' + @patch('builtins.input', side_effect=[0, 1]) # Mock user inputs 0 for x and 1 for y + def test_turn(self, mock_input): + # Initialize the field with empty spots + self.game.ifield = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " mock_input"]] + + + + player1 = True + player1_char = "X" + player2_char = "O" + calling_1 = mock_input() + expected_result = (0, 1) + #result = self.game.turn(player1, player1_char, player2_char) + result = self.game.turn() + + self.assertEqual(result, expected_result)''' + + def test_check_win(self) -> None: + player1_char = 'X' + player2_char = 'O' + + # Testing player 1 win condition + field = [["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["X", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["X", "|", " ", "|", " "]] + + result = self.game.check_win(field, player1_char, player2_char) + self.assertEqual(result, (1, 0)) + + # Testing player 2 win condition + field = [["O", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["O", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + ["O", "|", " ", "|", " "]] + + result = self.game.check_win(field, player1_char, player2_char) + self.assertEqual(result, (0, 1)) + + # Testing draw condition + field = [["X", "|", "O", "|", "X"], + ["—", "+", "—", "+", "—"], + ["X", "|", "O", "|", "O"], + ["—", "+", "—", "+", "—"], + ["O", "|", "X", "|", "X"]] + + result = self.game.check_win(field, player1_char, player2_char) + self.assertEqual(result, (1, 1)) + + # Testing no win condition + field = [[" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "], + ["—", "+", "—", "+", "—"], + [" ", "|", " ", "|", " "]] + + result = self.game.check_win(field, player1_char, player2_char) + self.assertEqual(result, (0, 0)) + + +def test_play_game(self): + expected_result = True + # Call the method you want to test + result = self.tictactoe.play_game() + # Add assertions to check the result + self.assertEqual(result, expected_result) + + +if __name__ == '__main__': + unittest.main()