def test_game_id_not_found(self): score_object = services.get_frame_score(self.queryset, 'abcde12345') game_object = game_models.Game('abcde12345') game_object.errors = [ game_models.Error( error_code=404, error_message='No game was found for the game id: abcde12345.') ] assert score_object == game_object
def test_set_frame_score__invalid_score_format(self): score_object = services.set_frame_score(self.queryset, self.game_registration.game_id, 'XX') assert score_object.errors == [ game_models.Error(error_code=400, error_message='Score format: XX is invalid.') ] assert score_object.frame_score is None assert score_object.first_attempt_score is None assert score_object.second_attempt_score is None assert score_object.third_attempt_score is None
def test_set_frame_score__game_object_not_found(self): score_object = services.set_frame_score(self.queryset, 'abcde12345', 'X') assert score_object.errors == [ game_models.Error( error_code=404, error_message='No game was found for the game id: abcde12345.') ] assert score_object.frame_score is None assert score_object.first_attempt_score is None assert score_object.second_attempt_score is None assert score_object.third_attempt_score is None
def test_game_registration_serializer__error(self): self.game_object.add_error( game_models.Error(error_code=404, error_message='Game not found')) serializer_instance = serializers.GameRegistrationSerializer( self.game_object) errors = { 'errors': [{ 'error_code': 404, 'error_message': 'Game not found' }] } expected = collections.OrderedDict(errors) assert serializer_instance.data == expected
def register_game(): """Registers the game and returns the game instance.""" try: with transaction.atomic(savepoint=False): game_object = game_models.GameRegistration() game_object.save() return game_object except DatabaseError: logging.exception('Unable to register the game') game_object = game_models.GameRegistration() game_object.add_error( game_models.Error(error_code=500, error_message='Unable to register the game.')) return game_object
def test_set_frame_score__game_has_been_played(self): scores = ['X', '7/', '7-2', '9/', 'X', 'X', 'X', '2-3', '6/', '7/3'] for score in scores: services.set_frame_score(self.queryset, self.game_registration.game_id, score) score_object = services.set_frame_score(self.queryset, self.game_registration.game_id, 'X') assert score_object.errors == [ game_models.Error( error_code=400, error_message='Game:\'{}\' has already been played.'.format( self.game_registration.game_id)) ] assert score_object.frame_score is None assert score_object.first_attempt_score is None assert score_object.second_attempt_score is None assert score_object.third_attempt_score is None
def _get_game_object(game_id, clazz_instance): """Returns the game object by game id. Returns: a tuple of game object and boolean flag indicating that the game object was created or not """ try: with transaction.atomic(savepoint=False): game_object = game_models.GameRegistration.objects.get(pk=game_id) return game_object, True except game_models.GameRegistration.DoesNotExist: logging.error('No game was found for game id : {}'.format(game_id)) clazz_object = clazz_instance() clazz_object.add_error( game_models.Error( error_code=404, error_message='No game was found for the game id: {}.'.format( game_id))) return clazz_object, False
def test_score_per_frame__failure(self): score_per_frame = game_models.ScorePerFrame(first_attempt_score=5, second_attempt_score=5, third_attempt_score=0, frame=1, frame_version=1, frame_score=10) score_per_frame.add_error( game_models.Error(error_code=400, error_message='Game has already been played.')) errors = { 'errors': [{ 'error_code': 400, 'error_message': 'Game has already been played.' }] } expected = collections.OrderedDict(errors) serializer_instance = serializers.ScorePerFrameSerializer( score_per_frame) assert serializer_instance.data == expected
def test_set_frame_score__race_condition_version_raises_error(self): services.set_frame_score(self.queryset, self.game_registration.game_id, 'X') with mock.patch('django.db.models.query.QuerySet.values_list', return_value=mock_query.MockSet((0,))), \ mock.patch('django.db.models.query.QuerySet.aggregate', return_value={'frame_max': 0}): score_object = services.set_frame_score( self.queryset, self.game_registration.game_id, '2-3') assert score_object.errors == [ game_models.Error( error_code=500, error_message=('Unable to save score: \'2-3\' for ' 'game: \'{game}\'.'.format( game=self.game_registration.game_id))) ] assert score_object.frame_score is None assert score_object.first_attempt_score is None assert score_object.second_attempt_score is None assert score_object.third_attempt_score is None
def test_register_name__error(self): """Tests if the game registration fails.""" error_list = [] def add_error(err): error_list.append(err) expected_mock = mock.Mock() expected_mock.add_error = mock.MagicMock(side_effect=add_error) save_method = mock.MagicMock( side_effect=django_db.DatabaseError('test')) expected_mock.save = save_method with mock.patch('game.models.GameRegistration', side_effect=lambda: expected_mock): game_object = services.register_game() assert game_object == expected_mock assert game_object.save.call_count == 1 assert game_object.add_error.call_count == 1 assert error_list == [ game_models.Error(error_code=500, error_message='Unable to register the game.') ]
def set_frame_score(score_queryset, game_id, score): """Sets the frame score for a valid game. The implementation executes the following: 1. load the game object associated with game id; if the game does not exist then raise a 404 error. 2. fetch the number of frames that have been played so far. If the number of frames played equals "10", i.e. the game is over, then a 400 error is raised 3. If the score format is valid, then and no frames have been played, then a frame is created and the score calculated. """ try: with transaction.atomic(savepoint=False): # If the game has not been created, then return a 404. game_object, game_object_created = _get_game_object( game_id, game_models.ScorePerFrame) if not game_object_created: # Error object is returned return game_object if not _is_valid_score(score): frame_score = game_models.ScorePerFrame() frame_score.add_error( game_models.Error( error_code=400, error_message='Score format: {} is invalid.'.format( score))) return frame_score spf_qs = score_queryset.filter(game=game_object) if not spf_qs or len(spf_qs) == 0: # First frame. (first_score, second_score, third_score) = _parse_score(score, 1) bowling_frame = game_object.game_score.create( frame=1, first_attempt_score=first_score, second_attempt_score=second_score, third_attempt_score=third_score, frame_version=1) return bowling_frame # If the game has been completed, then return a 400. number_of_played_frames = spf_qs.aggregate( django_models.Max('frame')).get('frame__max', 0) if number_of_played_frames == 10: frame_score = game_models.ScorePerFrame() frame_score.add_error( game_models.Error( error_code=400, error_message='Game:\'{}\' has already been played.'. format(game_id))) return frame_score # Parse the score, and check if the version has been created. (first_score, second_score, third_score) = _parse_score(score, number_of_played_frames + 1) version_number_tuple = spf_qs.filter(game=game_object).filter( frame=number_of_played_frames + 1).values_list('frame_version').first() (version_number, ) = (version_number_tuple if version_number_tuple is not None else (0, )) # Update the frame by to indicate a new frame is being played. score_per_frame = game_object.game_score.create( first_attempt_score=first_score, second_attempt_score=second_score, third_attempt_score=third_score, frame=number_of_played_frames + 1, frame_version=version_number + 1) return score_per_frame except: logging.exception(('Unable to save the frame for score {}' ' and game:{}.'.format(score, game_id))) frame_score = game_models.ScorePerFrame() frame_score.add_error( game_models.Error( error_code=500, error_message=('Unable to save score: \'{score}\' for game: ' '\'{game}\'.'.format(game=game_id, score=score)))) return frame_score