def test_run_exception_question_generator(self, generate): """Tests that run() method eliminates everyone without winner """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question generate.side_effect = Exception("Network Error!!!") # Both players give wrong answer, but not important since Question.generate will throw exception (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('A') (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player('B') game = GameSession(0, [player1, player2]) with self.assertRaises(Exception): asyncio.run(game.run()) self.assertEqual(len(game.players), 0, "No one should remain in the game") # Check that these message were sent last send_announcement1.assert_called_once_with( MESSAGE_NETWORK_ERROR_OCCURRED) send_announcement2.assert_called_once_with( MESSAGE_NETWORK_ERROR_OCCURRED)
def test_question_when_http_request_gets_400(self): """Test when the HTTP GET returns 400 from the Trivia server """ # Point to a server that always returns 400 self.backup_api = config.CONFIG_QUESTION_GENERATOR_API config.CONFIG_QUESTION_GENERATOR_API = 'http://httpbin.org/status/400' try: with self.assertRaises(Exception): asyncio.run(Question.generate()) finally: config.CONFIG_QUESTION_GENERATOR_API = self.backup_api
def test_send_question(self): """Tests that Player.send_question() calls websocket send() """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') websocket = MagicMock() send = AsyncMock() websocket.attach_mock(send, 'send') player = Player(None, websocket) asyncio.run(player.send_question(question)) send.assert_called_once_with( '{"id": 1, "method": "ask_question", "params": {"question": "Question 1", "choices": ["A", "B", "C", "D"]}}' )
def test_send_answers(self): """Tests that Player.send_answers() calls websocket send() """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') websocket = MagicMock() send = AsyncMock() websocket.attach_mock(send, 'send') player = Player(None, websocket) counts = [1, 0, 1, 0] asyncio.run(player.send_answers(question, counts)) send.assert_called_once_with( '{"id": 1, "method": "answers", "params": {"question": {"question": "Question 1", "choices": ["A", "B", "C", "D"], "answer": "C"}, "choice_counts": [1, 0, 1, 0]}}' )
def test_execute_next_round_player_times_out(self, generate): """Tests that execute_next_round() eliminates player who did not respond within timeout. """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question # Create player 1 with the wrong answer, and player 2 will timeout (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('D') async def over_sleep(): await asyncio.sleep(config.CONFIG_ROUND_DURATION + 1) (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player(None) player2.attach_mock(over_sleep, 'recv_answer') game = GameSession(0, [player1, player2]) result = asyncio.run(game.execute_next_round()) self.assertFalse( result, "execute_next_round() should return False since game ended.") self.assertEqual(len(game.players), 0, "No player should remain in the game") # Check that the question was sent to the players # Check that the question was sent to the players send_question1.assert_any_call(question) send_question2.assert_any_call(question) # Check that the count of the answers from each participant was sent send_answers1.assert_any_call(question, [0, 0, 0, 1]) send_answers2.assert_any_call(question, [0, 0, 0, 1]) # Check that these message were sent last send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED) send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED)
def test_execute_next_round_player_recvMessage_exception(self, generate): """Tests that execute_next_round() eliminates player who did not respond within timeout. """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question # Create player 1 with wrong answer, and player 2 with the right answer (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('D') (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player('C') recv_answer2 = AsyncMock( side_effect=Exception('General Error during recv_answer()')) player2.attach_mock(recv_answer2, 'recv_answer') game = GameSession(0, [player1, player2]) result = asyncio.run(game.execute_next_round()) self.assertFalse( result, "execute_next_round() should return False since game ended.") self.assertEqual(len(game.players), 0, "No player should remain in the game") # Check that the question was sent to the players send_question1.assert_any_call(question) send_question2.assert_any_call(question) # Check that the count of the answers from each participant was sent send_answers1.assert_any_call(question, [0, 0, 0, 1]) send_answers2.assert_any_call(question, [0, 0, 0, 1]) # Check that these message were sent last send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED) send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED)
def test_question(self): """Test the actual question retrieval and checks the validity of the Question instance. """ question = asyncio.run(Question.generate()) string = "Question is " + str([question]) self.assertGreater(len(question.choices), 1, "Choices returned must be greater than 1") self.assertEqual(len(question.choices), len(set(question.choices)), "Choices returned are not unique") self.assertIsNotNone(question.answer, "Answer returned must not be None") count = 0 for c in question.choices: if (c == question.answer): count += 1 self.assertEqual(count, 1, "Only one choice must be an answer")
def test_execute_next_round_identifies_winner(self, generate): """Tests that execute_next_round() method correctly identifies winner from the game. """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question # Create player 1 with wrong answer, and player 2 with the right answer (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('D') (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player('C') game = GameSession(0, [player1, player2]) result = asyncio.run(game.execute_next_round()) self.assertFalse( result, "execute_next_round() should return False since game ended with a winner." ) self.assertEqual(len(game.players), 0, "No player should remain in the game") # Check that the question was sent to the players send_question1.assert_any_call(question) send_question2.assert_any_call(question) # Check that the count of the answers from each participant was sent send_answers1.assert_any_call(question, [0, 0, 1, 1]) send_answers2.assert_any_call(question, [0, 0, 1, 1]) # Check that these message were sent last send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED) send_announcement2.assert_called_with(MESSAGE_YOU_ARE_THE_WINNER)
def test_execute_next_round_all_eliminated(self, generate): """Tests that execute_next_round() method eliminates everyone without winner """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question # Both players gives wrong answer (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('A') (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player('B') game = GameSession(0, [player1, player2]) result = asyncio.run(game.execute_next_round()) self.assertFalse( result, "execute_next_round() should return False since everyone eliminated." ) self.assertEqual(len(game.players), 0, "No one should remain in the game") # Check that the question was sent to the players send_question1.assert_any_call(question) send_question2.assert_any_call(question) # Check that the count of the answers from each participant was sent send_answers1.assert_any_call(question, [1, 1, 0, 0]) send_answers2.assert_any_call(question, [1, 1, 0, 0]) # Check that these message were sent last send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED) send_announcement1.assert_called_with(MESSAGE_YOU_ARE_ELIMINATED)
def test_execute_next_round_move_to_next_round(self, generate): """Tests that execute_next_round() method has to continue to the next round. """ question = Question('Question 1', ['A', 'B', 'C', 'D'], 'C') generate.return_value = question # Both players gives the correct answer (player1, send_announcement1, send_question1, send_answers1, recv_answer1) = self.get_mocked_player('C') (player2, send_announcement2, send_question2, send_answers2, recv_answer2) = self.get_mocked_player('C') game = GameSession(0, [player1, player2]) result = asyncio.run(game.execute_next_round()) self.assertTrue( result, "execute_next_round() should return True since no single winner yet." ) self.assertEqual(len(game.players), 2, "Two players should still be in the game") # Check that the question was sent to the players send_question1.assert_any_call(question) send_question2.assert_any_call(question) # Check that the count of the answers from each participant was sent send_answers1.assert_any_call(question, [0, 0, 2, 0]) send_answers2.assert_any_call(question, [0, 0, 2, 0]) # Check that these message were sent last send_announcement1.assert_called_with(MESSAGE_CORRECT_ANSWER) send_announcement1.assert_called_with(MESSAGE_CORRECT_ANSWER)