Esempio n. 1
0
 def setUp(self):
     self.ui = TerminalUi()
     self.board = Board()
     self.board_helper = BoardHelper(self.board.all_ships)
     self.missed_marker = consts.MISS_MARKER
     self.hit_marker = consts.HIT_MARKER
     self.sunk_marker = consts.SUNK_MARKER
Esempio n. 2
0
 def setUp(self):
     self.board = Board()
     self.validate = Validate()
     self.board_helper = BoardHelper(self.board.all_ships)
     self.human_board = Board()
     self.ui = TerminalUi()
     self.ai = Ai(self.validate)
Esempio n. 3
0
class TestFormat(TestCase):
    def setUp(self):
        self.ui = TerminalUi()
        self.board = Board()
        self.board_helper = BoardHelper(self.board.all_ships)
        self.missed_marker = consts.MISS_MARKER
        self.hit_marker = consts.HIT_MARKER
        self.sunk_marker = consts.SUNK_MARKER

    def test_less_then_board_len_add_row_numbers_returns_correctly_formatted_row(
            self):
        current_row = 0
        total_rows = 10
        row_number = ' 1 '

        formatted_row_number = self.ui._add_row_number(current_row, total_rows)
        self.assertEqual(formatted_row_number, row_number)

    def test_add_row_numbers_returns_correctly_formats_dbl_digit_rows(self):
        current_row = 9
        total_rows = 10
        row_number = '10 '

        formatted_row_number = self.ui._add_row_number(current_row, total_rows)
        self.assertEqual(formatted_row_number, row_number)

    def test_add_shot_marker_returns_M_when_a_ship_is_missed(self):
        missed_marker = self.missed_marker
        row = 1
        column = 0
        board_with_hit_and_miss = self.board_helper.generate_board_with_hit_and_miss(
        )
        board = MagicMock(state=board_with_hit_and_miss,
                          all_ships=self.board.all_ships)
        formated_marker = self.ui._add_shot_marker(board, row, column)

        self.assertEqual(formated_marker, missed_marker)

    def test_add_shot_marker_returns_H_when_a_ship_is_hit(self):
        hit_marker = self.hit_marker
        row = 0
        column = 0
        board_with_hit_and_miss = self.board_helper.generate_board_with_hit_and_miss(
        )
        board = MagicMock(state=board_with_hit_and_miss,
                          all_ships=self.board.all_ships)
        formated_marker = self.ui._add_shot_marker(board, row, column)

        self.assertEqual(formated_marker, hit_marker)

    def test_add_shot_marker_returns_brakets_when_a_spot_is_empty(self):
        sunk_marker = self.sunk_marker
        row = 0
        column = 0
        board_with_a_sunken_ship = self.board_helper.generate_board_with_a_sunken_ship(
        )
        board = MagicMock(state=board_with_a_sunken_ship,
                          all_ships=self.board.all_ships)
        formated_marker = self.ui._add_shot_marker(board, row, column)

        self.assertEqual(formated_marker, sunk_marker)

    def test_board_is_formatted_correctly_with_ships_before_moves(self):
        board_with_hidden_ships = """
    A  B  C  D  E  F  G  H  I  J
 1 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 2 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 3 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 4 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 5 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 6 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 7 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 8 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 9 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
10 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
"""
        board_with_ships = self.board_helper.generate_board_with_ships()
        board = MagicMock(state=board_with_ships,
                          all_ships=self.board.all_ships)
        formatted_board = self.ui.game_board(board)
        self.assertEqual(formatted_board, board_with_hidden_ships)

    def test_board_is_formatted_correctly_with_a_sunken_ship(self):
        S = self.sunk_marker
        occupied_board = """
    A  B  C  D  E  F  G  H  I  J
 1 %s%s%s%s%s[ ][ ][ ][ ][ ]
 2 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 3 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 4 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 5 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 6 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 7 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 8 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 9 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
10 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
""" % (S, S, S, S, S)
        board_with_sunken_ship = self.board_helper.generate_board_with_a_sunken_ship(
        )
        board = MagicMock(state=board_with_sunken_ship,
                          all_ships=self.board.all_ships)
        formatted_board = self.ui.game_board(board)

        self.assertEqual(formatted_board, occupied_board)

    def test_board_is_formatted_correctly_with_an_shots_taken(self):
        M = self.missed_marker
        H = self.hit_marker
        occupied_board = """
    A  B  C  D  E  F  G  H  I  J
 1 %s[ ][ ][ ][ ][ ][ ][ ][ ][ ]
 2 %s[ ][ ][ ][ ][ ][ ][ ][ ][ ]
 3 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 4 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 5 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 6 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 7 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 8 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
 9 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
10 [ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]
""" % (H, M)
        board_with_hit_and_miss = self.board_helper.generate_board_with_hit_and_miss(
        )
        board = MagicMock(state=board_with_hit_and_miss,
                          all_ships=self.board.all_ships)
        formatted_board = self.ui.game_board(board)

        self.assertEqual(formatted_board, occupied_board)
Esempio n. 4
0
 def setUp(self):
     self.board = Board()
     self.board_helper = BoardHelper(self.board.all_ships)
Esempio n. 5
0
class TestBoardHelper(TestCase):
    def setUp(self):
        self.board = Board()
        self.board_helper = BoardHelper(self.board.all_ships)

    def test_generate_all_spots_returns_a_list_of_all_spaces(self):
        all_spots_list = [
            'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'B1',
            'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'C1', 'C2',
            'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'D1', 'D2', 'D3',
            'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'D10', 'E1', 'E2', 'E3', 'E4',
            'E5', 'E6', 'E7', 'E8', 'E9', 'E10', 'F1', 'F2', 'F3', 'F4', 'F5',
            'F6', 'F7', 'F8', 'F9', 'F10', 'G1', 'G2', 'G3', 'G4', 'G5', 'G6',
            'G7', 'G8', 'G9', 'G10', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'H7',
            'H8', 'H9', 'H10', 'I1', 'I2', 'I3', 'I4', 'I5', 'I6', 'I7', 'I8',
            'I9', 'I10', 'J1', 'J2', 'J3', 'J4', 'J5', 'J6', 'J7', 'J8', 'J9',
            'J10'
        ]

        self.assertEqual(self.board_helper.generate_all_spots(),
                         all_spots_list)

    def test_generate_empty_board_returns_an_empty_board(self):
        empty_board = [
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_empty_board(), empty_board)

    def test_generate_all_occupied_but_one_returns_a_board_with_one_open_spot(
            self):
        all_occupied_but_one = [
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                None, 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
            [
                'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss', 'Miss',
                'Miss', 'Miss'
            ],
        ]

        self.assertEqual(self.board_helper.generate_all_but_one(),
                         all_occupied_but_one)

    def test_generate_full_board_returns_a_board_with_all_spots_filled(self):
        full_board = [
            [
                'Sunk', "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                'Sunk', "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                'Sunk', "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                'Sunk', "Miss", "Miss", "Miss", 'Sunk', "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                'Sunk', 'Sunk', "Miss", "Miss", 'Sunk', "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                "Miss", 'Sunk', "Miss", "Miss", 'Sunk', "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", 'Sunk', 'Sunk',
                'Sunk', 'Sunk'
            ],
            [
                "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
            [
                'Sunk', 'Sunk', 'Sunk', "Miss", "Miss", "Miss", "Miss", "Miss",
                "Miss", "Miss"
            ],
        ]

        self.assertEqual(self.board_helper.generate_full_board(), full_board)

    def test_generate_board_with_ships_returns_a_board_with_ships(self):
        board_with_ships = [
            [
                self.board.all_ships[0], self.board.all_ships[0],
                self.board.all_ships[0], self.board.all_ships[0],
                self.board.all_ships[0], None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, self.board.all_ships[2], None, None,
                None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [
                None, None, None, None, None, None, self.board.all_ships[1],
                self.board.all_ships[1], self.board.all_ships[1],
                self.board.all_ships[1]
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_board_with_ships(),
                         board_with_ships)

    def test_generate_board_with_hit_returns_a_board_with_a_hit(self):
        board_with_a_hit = [
            [
                self.board.all_ships[0], 'Hit', self.board.all_ships[0],
                self.board.all_ships[0], self.board.all_ships[0], None, None,
                None, None, self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, self.board.all_ships[2], None, None,
                None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [
                None, None, None, None, None, None, self.board.all_ships[1],
                self.board.all_ships[1], self.board.all_ships[1],
                self.board.all_ships[1]
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_board_with_hit(),
                         board_with_a_hit)

    def test_generate_board_with_a_miss_returns_a_board_with_a_miss(self):
        board_with_a_miss = [
            [
                self.board.all_ships[0], self.board.all_ships[0],
                self.board.all_ships[0], self.board.all_ships[0],
                self.board.all_ships[0], None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                'Miss', None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, self.board.all_ships[2], None, None,
                None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [
                None, None, None, None, None, None, self.board.all_ships[1],
                self.board.all_ships[1], self.board.all_ships[1],
                self.board.all_ships[1]
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_board_with_a_miss(),
                         board_with_a_miss)

    def test_generate_board_with_hit_and_miss_returns_a_board_with_a_hit_and_miss(
            self):
        board_with_hit_and_miss = [
            [
                'Hit', self.board.all_ships[0], self.board.all_ships[0],
                self.board.all_ships[0], self.board.all_ships[0], None, None,
                None, None, self.board.all_ships[3]
            ],
            [
                'Miss', None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, self.board.all_ships[2], None, None,
                None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [
                None, None, None, None, None, None, self.board.all_ships[1],
                self.board.all_ships[1], self.board.all_ships[1],
                self.board.all_ships[1]
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_board_with_hit_and_miss(),
                         board_with_hit_and_miss)

    def test_generate_board_with_sunken_ship_returns_a_board_with_a_sunken_ship(
            self):
        board_with_a_sunken_ship = [
            [
                'Sunk', 'Sunk', 'Sunk', 'Sunk', 'Sunk', None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, None, None, None, None, None,
                self.board.all_ships[3]
            ],
            [
                None, None, None, None, self.board.all_ships[2], None, None,
                None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [
                None, self.board.all_ships[4], None, None,
                self.board.all_ships[2], None, None, None, None, None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [
                None, None, None, None, None, None, self.board.all_ships[1],
                self.board.all_ships[1], self.board.all_ships[1],
                self.board.all_ships[1]
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        self.assertEqual(self.board_helper.generate_board_with_a_sunken_ship(),
                         board_with_a_sunken_ship)
Esempio n. 6
0
class TestAi(TestCase):
    def setUp(self):
        self.board = Board()
        self.validate = Validate()
        self.board_helper = BoardHelper(self.board.all_ships)
        self.human_board = Board()
        self.ui = TerminalUi()
        self.ai = Ai(self.validate)

    def test_ai_shoots_at_board_runs_the_correct_methods(self):
        ai_shot = 'A2'
        result = (HIT, {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [[0, 0]]
        })
        shot_result, current_ship = result
        board_with_ships = self.board_helper.generate_board_with_ships()
        self.human_board = MagicMock(state=board_with_ships,
                                     all_ships=self.human_board.all_ships)
        self.ai._choose_random_spot = MagicMock(return_value=ai_shot)
        self.validate.shot_result = MagicMock(return_value=result)
        self.ai.shoot_at_board(self.human_board)

        self.ai._choose_random_spot.assert_called()
        self.human_board.update.assert_called_with(ai_shot, shot_result)

    def test_legal_spot_returns_the_spot_if_it_exists(self):
        spot = 'A1'
        self.assertEqual(spot, self.ai._legal_space(spot))

    def test_legal_spot_returns_None_if_spot_does_not_exist(self):
        spot = 'Z1'
        self.assertEqual(None, self.ai._legal_space(spot))

    def test_remove_none_from_list_returns_a_list_without_nones(self):
        list_with_nones = ['B1', 'B2', None, None]
        list_without_nones = ['B1', 'B2']
        result = self.ai._remove_none_from_list(list_with_nones)

        self.assertEqual(result, list_without_nones)

    def test_get_surrounding_spots_adds_the_spots_to_the_next_shot_list(self):
        selected_spot = 'B2'
        correct_spots = ['B1', 'B3', 'A2', 'C2']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_get_surrounding_spots_at_upper_left_corner(self):
        selected_spot = 'A1'
        correct_spots = ['A2', 'B1']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_get_surrounding_spots_at_upper_right_corner(self):
        selected_spot = 'J1'
        correct_spots = ['J2', 'I1']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_get_surrounding_spots_at_bottom_right_corner(self):
        selected_spot = 'J10'
        correct_spots = ['J9', 'I10']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_get_surrounding_spots_at_bottom_left_corner(self):
        selected_spot = 'A10'
        correct_spots = ['A9', 'B10']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_get_surrounding_spots_at_bottom_edge_returns_current_spot(self):
        selected_spot = 'B10'
        correct_spots = ['B9', 'A10', 'C10']
        self.ai._get_surrounding_spots(selected_spot)

        self.assertEqual(self.ai.next_shots_list, correct_spots)

    def test_choose_random_spot_picks_a_spot_chooses_spaces_from_available_spaces(
            self):
        all_spots_list = self.board_helper.generate_all_spots()
        random_spot = self.ai._choose_random_spot()

        self.assertIn(random_spot, all_spots_list)

    def test_unified_shot_updates_the_board_with_shots_from_nxt_shot_list(
            self):
        self.ai.next_shots_list = ['B1']
        spot = 'B1'
        board_with_a_hit = self.board_helper.generate_board_with_hit()
        self.board.state = self.board_helper.generate_board_with_ships()
        self.ai._computer_shot(self.board, spot)

        self.assertEqual(self.board.state, board_with_a_hit)

    @patch('core.ai.Ai._choose_random_spot', return_value='B1')
    def test_unified_shot_updates_the_board_with_a_random_shot(self, mock):
        board_with_a_hit = self.board_helper.generate_board_with_hit()
        self.board.state = self.board_helper.generate_board_with_ships()
        random_spot = 'B1'
        self.ai._computer_shot(self.board, random_spot)

        self.assertEqual(self.board.state, board_with_a_hit)
Esempio n. 7
0
 def setUp(self):
     self.board = Board()
     self.place = Place()
     self.board_helper = BoardHelper(self.board.all_ships)
     self.zero_to_nine_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
     self.empty_board = self.board_helper.generate_empty_board()
Esempio n. 8
0
class TestPlace(TestCase):
    def setUp(self):
        self.board = Board()
        self.place = Place()
        self.board_helper = BoardHelper(self.board.all_ships)
        self.zero_to_nine_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        self.empty_board = self.board_helper.generate_empty_board()

    def test_get_random_row_and_column_returns_numbers_within_board_size(self):
        row, column = self.place._get_random_row_and_column(self.empty_board)
        self.assertIn(row, self.zero_to_nine_list)
        self.assertIn(column, self.zero_to_nine_list)

    @patch('core.placement.Place._get_random_row_and_column',
           side_effect=[(0, 0)])
    def test_space_for_ship_in_row_returns_location_where_ship_fit_if_there_is_space(
            self, mock):
        ship_size = 5
        orientation = 'row'
        row_coordinate, column_coordinate = self.place.find_space_for_ship(
            self.empty_board, ship_size, orientation)

        self.assertEqual(row_coordinate, 0)
        self.assertEqual(column_coordinate, 0)

    @patch('core.placement.Place._get_random_row_and_column',
           side_effect=[(1, 0), (2, 2)])
    def test_if_there_is_no_space_in_row_method_loops_until_it_finds_space(
            self, mock_board_spaces):
        ship_size = 5
        orientation = 'row'
        self.board.state = [
            [None, None, None, None, None, None, None, None, None, None],
            [
                'ship', 'ship', None, 'ship', None, 'ship', None, None, None,
                None
            ],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]

        row_coordinate, column_coordinate = self.place.find_space_for_ship(
            self.board.state, ship_size, orientation)
        self.assertEqual(row_coordinate, 2)
        self.assertEqual(column_coordinate, 2)

    @patch('core.placement.Place._get_random_row_and_column',
           side_effect=[(4, 1)])
    def test_space_for_ship_in_column_returns_coordinates_where_ship_fit_when_there_is_space(
            self, mock_coordinates):
        ship_size = 5
        orientation = 'column'
        row_coordinate, column_coordinate = self.place.find_space_for_ship(
            self.empty_board, ship_size, orientation)

        self.assertEqual(row_coordinate, 4)
        self.assertEqual(column_coordinate, 1)

    @patch('core.placement.Place._get_random_row_and_column',
           side_effect=[(0, 0), (0, 2)])
    def test_if_there_is_no_space_in_column_method_loops_until_it_finds_space(
            self, mock_coordinates):
        ship_size = 5
        orientation = 'column'
        self.board.state = [
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
        ]

        row_coordinate, column_coordinate = self.place.find_space_for_ship(
            self.board.state, ship_size, orientation)

        self.assertEqual(row_coordinate, 0)
        self.assertEqual(column_coordinate, 2)

    @patch('core.placement.Place._get_random_row_and_column',
           side_effect=[(0, 2), (0, 3)])
    def test_if_ships_will_not_hang_off_the_edge(self, mock_coordinates):
        ship_size = 5
        orientation = 'column'
        self.board.state = [
            [
                'ship', 'ship', None, None, 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, None, 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, None, 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, None, 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
            [
                'ship', 'ship', None, 'ship', 'ship', 'ship', 'ship', 'ship',
                'ship', 'ship'
            ],
        ]

        row_coordinate, column_coordinate = self.place.find_space_for_ship(
            self.board.state, ship_size, orientation)

        self.assertEqual(row_coordinate, 0)
        self.assertEqual(column_coordinate, 3)
class TestValidations(TestCase):
    def setUp(self):
        self.board = Board()
        self.board_helper = BoardHelper(self.board.all_ships)
        self.validate = Validate()
        self.ui = TerminalUi()

    def test_split_user_row_and_returns_a_single_letter_and_a_number_as_strings(
            self):
        user_shot_choice = 'A2'
        split_choice = ('A', '2')
        answer = self.validate.split_user_shot(user_shot_choice)

        self.assertEqual(answer, split_choice)

    def test_Validate_is_initialized_with_a_letters_list(self):
        col_letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

        self.assertEqual(self.validate.col_letters, col_letters)

    def test_Validate_is_initialized_with_a_numbers_list(self):
        row_nums = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

        self.assertEqual(self.validate.row_nums, row_nums)

    def test_Validate_is_initialized_with_a_all_spots_list(self):
        all_spots_list = self.board_helper.generate_all_spots()

        self.assertEqual(self.validate.all_spots, all_spots_list)

    def test_spot_exists_returns_True_if_spot_exists(self):
        user_shot_choice = 'A1'

        self.assertTrue(self.validate._spot_exists(user_shot_choice))

    def test_spot_exists_returns_False_if_the_spot_is_invalid(self):
        user_shot_choice = 'J4000'

        self.assertFalse(self.validate._spot_exists(user_shot_choice))

    def test_get_current_spot_returns_the_value_of_the_selected_spot_on_the_board(
            self):
        user_shot_choice = 'A1'
        board_with_ships = self.board_helper.generate_board_with_ships()
        spot_value = self.validate.get_current_spot(board_with_ships,
                                                    user_shot_choice)
        aircraft_carrier = self.board.all_ships[0]

        self.assertEqual(spot_value, aircraft_carrier)

    def test_spot_occupied_returns_False_if_spot_is_not_occupied(self):
        user_shot_choice = 'A2'
        all_but_one = self.board_helper.generate_all_but_one()
        board = MagicMock(state=all_but_one, all_ships=self.board.all_ships)
        spot_occupied = self.validate._spot_occupied(board, user_shot_choice)

        self.assertEqual(False, spot_occupied)

    def test_spot_occupied_returns_true_if_spot_is_occupied(self):
        user_shot_choice = 'A1'
        all_but_one = self.board_helper.generate_all_but_one()
        board = MagicMock(state=all_but_one, all_ships=self.board.all_ships)
        spot_occupied = self.validate._spot_occupied(board, user_shot_choice)

        self.assertEqual(True, spot_occupied)

    def test_all_ships_sunk_returns_True_if_there_are_no_ships_left(self):
        full_board = self.board_helper.generate_full_board()
        all_sunken_ships = self.board_helper.generate_sunken_ships()
        board = MagicMock(state=full_board, all_ships=all_sunken_ships)
        all_ships_sunk = self.validate.all_ships_sunk(board)

        self.assertEqual(all_ships_sunk, True)

    def test_all_ships_sunk_returns_False_if_there_are_ships_left(self):
        board_with_ships = self.board_helper.generate_board_with_ships()
        board = MagicMock(state=board_with_ships,
                          all_ships=self.board.all_ships)
        all_ships_sunk = self.validate.all_ships_sunk(board)

        self.assertEqual(all_ships_sunk, False)

    def test_hitting_a_ship_displays_msg_and_returns_str_Hit(self):
        shot = 'A1'
        board_with_ships = self.board_helper.generate_board_with_ships()
        board = MagicMock(state=board_with_ships,
                          all_ships=self.board.all_ships)
        shot_result = self.validate.shot_result(board, shot)
        result = (consts.HIT, {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [[0, 0]]
        })

        self.assertEqual(shot_result, result)

    def test_missing_a_ship_returns_str_Miss_and_None(self):
        shot = 'A9'
        board_with_ships = self.board_helper.generate_board_with_ships()
        board = MagicMock(state=board_with_ships,
                          all_ships=self.board.all_ships)
        shot_result = self.validate.shot_result(board, shot)
        result = (consts.MISS, None)

        self.assertEqual(shot_result, result)

    def test_ship_is_sunk_when_len_hit_locations_equals_ship_size(self):
        sunken_ship = {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [[1, 1], [1, 2], [1, 3], [1, 4], [1, 5]],
        }
        is_sunk = self.validate._is_ship_sunk(sunken_ship)

        self.assertEqual(is_sunk, True)

    def test_ship_is_not_sunk_when_len_hit_locations_doesnt_equal_ship_size(
            self):
        ship_with_no_hits = {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [],
        }

        self.assertFalse(self.validate._is_ship_sunk(ship_with_no_hits))

    def test_when_a_ship_is_hit_it_stores_the_location_of_the_hit(self):
        current_ship = {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [],
        }
        ship_after_hit = {
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [[0, 0]]
        }
        shot = 'A1'

        self.assertEqual(self.validate._store_hits(current_ship, shot),
                         ship_after_hit)
class TestBoard(TestCase):

    def setUp(self):
        self.board = Board()
        self.board_helper = BoardHelper(self.board.all_ships)

    def test_all_ships_contains_all_5_ships(self):
        self.assertEqual(len(self.board.all_ships), 5)

    def test_each_ship_has_a_hit_location_array(self):
        hit_locations = []

        self.assertEqual(self.board.aircraft_carrier['hit_locations'], hit_locations)
        self.assertEqual(self.board.destroyer['hit_locations'], hit_locations)
        self.assertEqual(self.board.cruiser['hit_locations'], hit_locations)
        self.assertEqual(self.board.submarine['hit_locations'], hit_locations)
        self.assertEqual(self.board.battleship['hit_locations'], hit_locations)

    def test_each_ship_has_a_size(self):
        aircraft_carrier_size = 5
        battleship_size = 4
        cruiser_size = 3
        submarine_size = 3
        destroyer_size = 2

        self.assertEqual(self.board.aircraft_carrier['size'], aircraft_carrier_size)
        self.assertEqual(self.board.battleship['size'], battleship_size)
        self.assertEqual(self.board.cruiser['size'], cruiser_size)
        self.assertEqual(self.board.submarine['size'], submarine_size)
        self.assertEqual(self.board.destroyer['size'], destroyer_size)

    def test_each_ship_has_a_name(self):
        aircraft_carrier_name = 'Aircraft Carrier'
        battleship_name = 'Battleship'
        cruiser_name = 'Cruiser'
        submarine_name = 'Submarine'
        destroyer_name = 'Destroyer'

        self.assertEqual(self.board.aircraft_carrier['name'], aircraft_carrier_name)
        self.assertEqual(self.board.battleship['name'], battleship_name)
        self.assertEqual(self.board.cruiser['name'], cruiser_name)
        self.assertEqual(self.board.submarine['name'], submarine_name)
        self.assertEqual(self.board.destroyer['name'], destroyer_name)

    def test_Hit_is_added_to_board_if_the_user_hit_a_ship(self):
        user_shot_choice = 'B1'
        self.board.state = self.board_helper.generate_board_with_ships()
        shot_result = 'Hit'
        self.board.update(user_shot_choice, shot_result)

        self.assertEqual(self.board.state, self.board_helper.generate_board_with_hit())

    def test_Miss_is_added_to_board_if_the_user_Misses_a_ship(self):
        user_shot_choice = 'A2'
        self.board.state = self.board_helper.generate_board_with_ships()
        shot_result = 'Miss'
        self.board.update(user_shot_choice, shot_result)

        self.assertEqual(self.board.state, self.board_helper.generate_board_with_a_miss())

    def test_when_ship_sinks_all_positions_where_ship_was_are_updated_to_str_Sunk(self):
        user_shot_choice = 'A1'
        self.board.state = self.board_helper.generate_board_with_ships()
        row = 0
        column = 0
        self.board.state[row][column] = {
            'name': 'Aircraft Carrier',
            'size': 5,
            'sunk': True,
            'hit_locations': [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]],
        }
        shot_result = 'Sunk'
        self.board.update(user_shot_choice, shot_result)

        self.assertEqual(self.board.state, self.board_helper.generate_board_with_a_sunken_ship())

    @patch('core.placement.Place._get_random_row_and_column', side_effect=[(0, 0)])
    def test_a_ship_is_added_to_row_if_there_is_room(self, mock_coordinates):
        place = Place()
        self.board.all_ships = [{
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [],
        }]
        state_after_move = [
            [self.board.all_ships[0], self.board.all_ships[0], self.board.all_ships[0], self.board.all_ships[0], self.board.all_ships[0], None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]
        ship_orientation = 'row'
        self.board.add_to_board(place, ship_orientation)

        self.assertEqual(self.board.state, state_after_move)

    @patch('core.placement.Place._get_random_row_and_column', side_effect=[(0, 0)])
    def test_ship__added_to_column_if_there_is_room(self, mock_coordinates):
        place = Place()
        self.board.all_ships = [{
            'name': 'Aircraft Carrier',
            'size': 5,
            'hit_locations': [],
        }]
        state_after_move = [
            [self.board.all_ships[0], None, None, None, None, None, None, None, None, None],
            [self.board.all_ships[0], None, None, None, None, None, None, None, None, None],
            [self.board.all_ships[0], None, None, None, None, None, None, None, None, None],
            [self.board.all_ships[0], None, None, None, None, None, None, None, None, None],
            [self.board.all_ships[0], None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
            [None, None, None, None, None, None, None, None, None, None],
        ]
        ship_orientation = 'column'
        self.board.add_to_board(place, ship_orientation)
        self.maxDiff = None

        self.assertEqual(self.board.state, state_after_move)