class TestGame(TestCase): def setUp(self): minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() self.subject = Game(minefield_repository=minefield_repository, turn_repository=turn_repository, mine_planter=LazyBeeMinePlanter()) def test_play_with_invalid_row_count(self): assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game, row_count=4, column_count=5, expected_minimum_row_count=5, expected_minimum_column_count=5, test_case=self) def test_play_with_invalid_column_count(self): assert_invalid_board_parameters_should_raise_exception(create_board=self.subject.start_new_game, row_count=5, column_count=4, expected_minimum_row_count=5, expected_minimum_column_count=5, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_board(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) board = spy.game_did_create_board.call_args[1]['board'] expected_board = Board(row_count=5, column_count=5) assert_boards_equal(board=board, expected_board=expected_board, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) board_snapshot = spy.game_did_create_board.call_args[1]['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_create_minefield(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] board_snapshot = call_args['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_game_state(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Started) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_minefield_creation(self): first_turn = RawTurn(action=TurnAction.RevealCell, coordinate=Coordinate(row_index=0, column_index=4)) board_snapshot = self.simulate_start_game(row_count=5, column_count=5, turns=[first_turn]) expected_board_snapshot = [ [CellType.Unknown, CellType.Unknown, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=1) call_args = spy.game_did_take_turn.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Started) def test_play_with_valid_dimensions_should_notify_observer_with_game_state_started_after_second_turn_reveals_mine( self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=0) call_args = spy.game_did_take_turn.call_args[1] game_state = call_args['game_state'] self.assertEqual(game_state, GameState.Lost) def test_play_with_valid_dimensions_should_notify_observer_with_board_snapshot_after_second_turn(self): spy = Mock(GameObserver) self.subject.start_new_game(row_count=5, column_count=5, observer=spy) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=0, column_index=4) call_args = spy.game_did_create_minefield.call_args[1] reveal_cell = call_args['reveal_cell'] reveal_cell(row_index=0, column_index=1) call_args = spy.game_did_take_turn.call_args[1] board_snapshot = call_args['board_snapshot'] expected_board_snapshot = [ [CellType.Unknown, CellType.Two, CellType.One, CellType.Zero, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One, CellType.Zero], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Two, CellType.One], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], [CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown, CellType.Unknown], ] assert_board_snapshots_equal(board_snapshot=board_snapshot, expected_board_snapshot=expected_board_snapshot, test_case=self) def test_present_start_menu_with_no_minefields_should_notify_observer_with_correct_start_menu_options(self): spy = Mock(GameObserver) self.subject.present_start_menu(observer=spy) keyword_arguments = spy.game_did_present_start_menu.call_args[1] menu_options = keyword_arguments['menu_options'] expected_menu_options = MenuOptions(options=[StartMenuOptionType.StartNewGame, StartMenuOptionType.Quit], initially_selected_option=StartMenuOptionType.StartNewGame) self.assertEqual(menu_options, expected_menu_options) def test_present_start_menu_with_no_minefields_should_notify_observer_with_present_create_board_options(self): spy = Mock(GameObserver) self.subject.present_start_menu(observer=spy) keyword_arguments = spy.game_did_present_start_menu.call_args[1] present_create_board_options = keyword_arguments['present_create_board_options'] present_create_board_options() keyword_arguments = spy.game_did_present_create_board_options.call_args[1] minimum_row_count = keyword_arguments['minimum_row_count'] minimum_column_count = keyword_arguments['minimum_column_count'] self.assertEqual(minimum_row_count, 5) self.assertEqual(minimum_column_count, 5) create_board = keyword_arguments['create_board'] create_board(row_count=minimum_row_count, column_count=minimum_column_count) keyword_arguments = spy.game_did_create_board.call_args[1] board = keyword_arguments['board'] expected_board = Board(row_count=5, column_count=5) assert_boards_equal(board=board, expected_board=expected_board, test_case=self) # "Private" def simulate_start_game(self, row_count: int, column_count: int, turns: [RawTurn]) -> [[CellType]]: spy = Mock(GameObserver) self.subject.start_new_game(row_count=row_count, column_count=column_count, observer=spy) first_turn = turns.pop(0) create_minefield = spy.game_did_create_board.call_args[1]['create_minefield'] create_minefield(row_index=first_turn.coordinate.row_index, column_index=first_turn.coordinate.column_index) call_args = spy.game_did_create_minefield.call_args[1] for turn in turns: reveal_cell = call_args['reveal_cell'] toggle_flag = call_args['toggle_flag'] if turn.action == TurnAction.RevealCell: reveal_cell(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index) elif turn.action == TurnAction.ToggleFlag: toggle_flag(row_index=turn.coordinate.row_index, column_index=turn.coordinate.column_index) call_args = spy.did_take_turn.call_args[1] return call_args['board_snapshot']
#!/usr/bin/env python3 import argparse from minesweeper import Game from minesweeper.common.persistence import InMemoryMinefieldRepository, InMemoryTurnRepository from tui.game_observer import TUI if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-r', '--row-count', type=int, default=5) parser.add_argument('-c', '--column-count', type=int, default=10) args = parser.parse_args() tui = TUI() minefield_repository = InMemoryMinefieldRepository() turn_repository = InMemoryTurnRepository() game = Game(minefield_repository=minefield_repository, turn_repository=turn_repository) game.present_start_menu(observer=tui)