2019-11-30 15:21:33 +01:00
|
|
|
"""All tests for the Sudoku Solver."""
|
|
|
|
|
|
|
|
import unittest
|
2019-12-03 12:00:32 +01:00
|
|
|
import copy
|
2019-12-02 15:21:49 +01:00
|
|
|
from main import iterate_board
|
2019-12-01 19:27:38 +01:00
|
|
|
from board import Board
|
2019-11-30 15:21:33 +01:00
|
|
|
from square import Square
|
|
|
|
|
|
|
|
|
2019-12-02 15:21:49 +01:00
|
|
|
class TestMain(unittest.TestCase):
|
|
|
|
"""TestCase for the main file."""
|
|
|
|
|
|
|
|
def test_iterate_over_various_board_difficulties(self):
|
|
|
|
"""Run the solver on different boards."""
|
|
|
|
|
|
|
|
strings = [(
|
|
|
|
".2..785..\n"
|
|
|
|
"4...52...\n"
|
|
|
|
"..1..3.2.\n"
|
|
|
|
".....1...\n"
|
|
|
|
"7348.526.\n"
|
|
|
|
"2.9.67..5\n"
|
|
|
|
".687..3.9\n"
|
|
|
|
"342.1.7..\n"
|
|
|
|
"19..86..2\n"
|
|
|
|
), (
|
|
|
|
"..1..6435\n"
|
|
|
|
".....1...\n"
|
|
|
|
".5.47.98.\n"
|
|
|
|
"..2.8.7.9\n"
|
|
|
|
"..87..612\n"
|
|
|
|
".64.1..5.\n"
|
|
|
|
"91.3428.7\n"
|
|
|
|
".27....9.\n"
|
|
|
|
"6.3.9.5..\n"
|
|
|
|
), (
|
|
|
|
".....6...\n"
|
|
|
|
"..2.35.8.\n"
|
|
|
|
"....2..13\n"
|
|
|
|
".2....19.\n"
|
|
|
|
"93....7..\n"
|
|
|
|
"5....4...\n"
|
|
|
|
"1......7.\n"
|
|
|
|
".7...142.\n"
|
|
|
|
".9.4.3...\n"
|
|
|
|
), (
|
|
|
|
"...82....\n"
|
|
|
|
"...6.9..1\n"
|
|
|
|
"9.4..1...\n"
|
|
|
|
".9.7..28.\n"
|
|
|
|
".......57\n"
|
|
|
|
"7.5......\n"
|
|
|
|
".78962..5\n"
|
|
|
|
".2..8.7.3\n"
|
|
|
|
".6..74.2.\n"
|
|
|
|
), (
|
|
|
|
"4......1.\n"
|
|
|
|
".15.4.6..\n"
|
|
|
|
".....7...\n"
|
|
|
|
"...21...8\n"
|
|
|
|
"...734..2\n"
|
|
|
|
".3..8....\n"
|
|
|
|
"8.19...45\n"
|
|
|
|
".4....7..\n"
|
|
|
|
"2....3...\n"
|
|
|
|
), (
|
|
|
|
"3........\n"
|
|
|
|
".6...791.\n"
|
|
|
|
".....325.\n"
|
|
|
|
".19.645..\n"
|
|
|
|
".......6.\n"
|
|
|
|
".85......\n"
|
|
|
|
"...8.....\n"
|
|
|
|
"..1..97..\n"
|
|
|
|
"47..5....\n"
|
|
|
|
)]
|
|
|
|
|
|
|
|
for string in strings[:-4]:
|
|
|
|
while '.' in string:
|
|
|
|
new_string = iterate_board(string)
|
|
|
|
self.assertNotEqual(new_string, string)
|
|
|
|
string = new_string
|
|
|
|
|
|
|
|
|
2019-12-01 19:27:38 +01:00
|
|
|
class TestBoard(unittest.TestCase):
|
2019-12-02 15:21:49 +01:00
|
|
|
"""TestCase for Board."""
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
self.string = (
|
|
|
|
".2..785..\n"
|
|
|
|
"4...52...\n"
|
|
|
|
"..1..3.2.\n"
|
|
|
|
".....1...\n"
|
|
|
|
"7348.526.\n"
|
|
|
|
"2.9.67..5\n"
|
|
|
|
".687..3.9\n"
|
|
|
|
"342.1.7..\n"
|
|
|
|
"19..86..2\n"
|
|
|
|
)
|
2019-12-03 12:00:32 +01:00
|
|
|
|
2019-12-02 17:34:39 +01:00
|
|
|
self.board = Board(self.string, debug=False)
|
2019-12-02 15:21:49 +01:00
|
|
|
|
|
|
|
def test_lines_are_correctly_initialized(self):
|
|
|
|
"""There should be 9 lines, each a set of its values."""
|
|
|
|
|
|
|
|
self.assertIsInstance(self.board.lines, list)
|
|
|
|
self.assertEqual(len(self.board.lines), 9)
|
|
|
|
|
|
|
|
for line in self.board.lines:
|
|
|
|
self.assertIsInstance(line, set)
|
|
|
|
self.assertNotEqual(len(line), 0)
|
|
|
|
|
|
|
|
def test_columns_are_correctly_initialized(self):
|
|
|
|
"""There should be 9 columns, each a set of its values."""
|
|
|
|
|
|
|
|
self.assertIsInstance(self.board.columns, list)
|
|
|
|
self.assertEqual(len(self.board.columns), 9)
|
|
|
|
|
|
|
|
for column in self.board.columns:
|
|
|
|
self.assertIsInstance(column, set)
|
|
|
|
self.assertNotEqual(len(column), 0)
|
|
|
|
|
|
|
|
def test_grids_are_correctly_initialized(self):
|
|
|
|
"""There should be 9 grids, each a set of its values."""
|
|
|
|
|
|
|
|
self.assertIsInstance(self.board.grids, list)
|
|
|
|
self.assertEqual(len(self.board.grids), 9)
|
|
|
|
|
|
|
|
for grid in self.board.grids:
|
|
|
|
self.assertIsInstance(grid, set)
|
|
|
|
self.assertNotEqual(len(grid), 0)
|
|
|
|
|
|
|
|
def test_squares_are_correctly_initialized(self):
|
2019-12-02 17:34:39 +01:00
|
|
|
"""There should be 81 squares, each a Square object."""
|
2019-12-02 15:21:49 +01:00
|
|
|
|
|
|
|
self.assertIsInstance(self.board.squares, list)
|
2019-12-02 17:34:39 +01:00
|
|
|
self.assertEqual(len(self.board.squares), 81)
|
|
|
|
|
|
|
|
for square in self.board.squares:
|
|
|
|
self.assertIsInstance(square, Square)
|
|
|
|
self.assertIsInstance(square.values, set)
|
|
|
|
self.assertLess(len(square.values), 2)
|
|
|
|
|
|
|
|
def test_compute_possible_values(self):
|
|
|
|
"""For each square, values are added if the square was empty.
|
|
|
|
|
|
|
|
If the square was not empty, it had only one value. Values should not
|
|
|
|
be added if the square was not empty.
|
|
|
|
"""
|
|
|
|
|
|
|
|
empty_squares = 0
|
|
|
|
squares_with_one_value = 0
|
|
|
|
|
|
|
|
for square in self.board.squares:
|
|
|
|
if len(square.values) == 0:
|
|
|
|
empty_squares += 1
|
|
|
|
# We already tested that if len(square.values) != 0 it must be 1
|
|
|
|
else:
|
|
|
|
squares_with_one_value += 1
|
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
old_squares = copy.deepcopy(self.board.squares)
|
|
|
|
|
2019-12-02 17:34:39 +01:00
|
|
|
self.board.compute_possible_values()
|
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
new_squares = copy.deepcopy(self.board.squares)
|
|
|
|
|
|
|
|
self.assertEqual(len(old_squares), 81)
|
|
|
|
self.assertEqual(len(new_squares), 81)
|
2019-12-02 17:34:39 +01:00
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
for i in range(81):
|
|
|
|
if len(old_squares[i].values) != 1:
|
|
|
|
self.assertLess(
|
|
|
|
len(old_squares[i].values), len(new_squares[i].values)
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
self.assertEqual(
|
|
|
|
len(old_squares[i].values), len(new_squares[i].values)
|
|
|
|
)
|
|
|
|
|
|
|
|
squares_with_more_than_one_value = 0
|
2019-12-02 17:34:39 +01:00
|
|
|
for square in self.board.squares:
|
|
|
|
self.assertGreater(len(square.values), 0)
|
|
|
|
if len(square.values) > 1:
|
|
|
|
squares_with_more_than_one_value += 1
|
|
|
|
|
|
|
|
# Maybe only one value was computed.
|
|
|
|
self.assertLessEqual(
|
|
|
|
squares_with_more_than_one_value, empty_squares
|
|
|
|
)
|
|
|
|
|
2019-12-03 09:06:16 +01:00
|
|
|
def test_compute_obligated(self):
|
|
|
|
"""Method works."""
|
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
def test_update_board(self):
|
|
|
|
"""Updated board is consistent with board.string."""
|
2019-12-02 17:34:39 +01:00
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
old_string: str = self.board.string
|
2019-12-02 17:34:39 +01:00
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
self.board.update_board()
|
|
|
|
self.assertEqual(old_string, self.board.string)
|
2019-12-02 17:34:39 +01:00
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
old_string = old_string.replace('\n', '')
|
|
|
|
self.assertEqual(len(old_string), 81)
|
|
|
|
|
|
|
|
for square_nb, square in enumerate(self.board.squares):
|
|
|
|
if len(square.values) == 1:
|
|
|
|
self.assertEqual(
|
|
|
|
str(square.values)[2:-2],
|
|
|
|
old_string[square_nb]
|
|
|
|
)
|
|
|
|
|
|
|
|
def test_update_string(self):
|
|
|
|
"""Updated board.string is consistent with board."""
|
|
|
|
|
|
|
|
old_string: str = self.board.string
|
2019-12-03 09:06:16 +01:00
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
self.board.update_string()
|
|
|
|
|
|
|
|
self.assertEqual(len(self.string), 90)
|
|
|
|
self.assertEqual(len(old_string), 90)
|
|
|
|
self.assertEqual(len(self.board.string), 90)
|
|
|
|
|
|
|
|
empty_squares = 0
|
2019-12-03 09:06:16 +01:00
|
|
|
for square in self.board.squares:
|
|
|
|
if len(square.values) != 1:
|
|
|
|
empty_squares += 1
|
|
|
|
|
2019-12-03 12:00:32 +01:00
|
|
|
self.assertEqual(empty_squares, self.board.string.count('.'))
|
2019-12-01 19:27:38 +01:00
|
|
|
|
|
|
|
|
2019-11-30 15:21:33 +01:00
|
|
|
class TestSquare(unittest.TestCase):
|
2019-12-02 15:21:49 +01:00
|
|
|
"""TestCase for Square."""
|
2019-11-30 15:21:33 +01:00
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
content = '.'
|
|
|
|
self.board = [
|
|
|
|
Square(line, column, content)
|
|
|
|
for line in range(9)
|
|
|
|
for column in range(9)
|
|
|
|
]
|
|
|
|
|
|
|
|
self.assertEqual(len(self.board), 81)
|
|
|
|
|
|
|
|
def test_grid_is_correctly_computed(self):
|
|
|
|
"""Square.grid is correctly computed for all values."""
|
|
|
|
|
|
|
|
correct_grids = (
|
|
|
|
"000111222"
|
|
|
|
"000111222"
|
|
|
|
"000111222"
|
|
|
|
"333444555"
|
|
|
|
"333444555"
|
|
|
|
"333444555"
|
|
|
|
"666777888"
|
|
|
|
"666777888"
|
|
|
|
"666777888"
|
|
|
|
)
|
|
|
|
|
|
|
|
for i, square in enumerate(self.board):
|
2019-12-02 17:34:39 +01:00
|
|
|
self.assertEqual(square.grid, int(correct_grids[i]))
|
2019-11-30 15:21:33 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|