def test_record_many_answers(self): state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertIsNone(state_answers) submitted_answer_list = [ stats_domain.SubmittedAnswer( 'answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer( 'answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer( 'answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] stats_services.record_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list) # The order of the answers returned depends on the size of the answers. state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(state_answers.exploration_id, 'exp_id0') self.assertEqual(state_answers.exploration_version, 1) self.assertEqual( state_answers.state_name, feconf.DEFAULT_INIT_STATE_NAME) self.assertEqual(state_answers.interaction_id, 'TextInput') self.assertEqual(state_answers.get_submitted_answer_dict_list(), [{ 'answer': 'answer a', 'time_spent_in_sec': 10.0, 'answer_group_index': 0, 'rule_spec_index': 1, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }, { 'answer': 'answer ccc', 'time_spent_in_sec': 3.0, 'answer_group_index': 1, 'rule_spec_index': 1, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }, { 'answer': 'answer bbbbb', 'time_spent_in_sec': 7.5, 'answer_group_index': 1, 'rule_spec_index': 0, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }])
def test_record_many_answers(self): state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertIsNone(state_answers) submitted_answer_list = [ stats_domain.SubmittedAnswer('answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer('answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer('answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] stats_services.record_answers(self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list) # The order of the answers returned depends on the size of the answers. state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(state_answers.exploration_id, 'exp_id0') self.assertEqual(state_answers.exploration_version, 1) self.assertEqual(state_answers.state_name, feconf.DEFAULT_INIT_STATE_NAME) self.assertEqual(state_answers.interaction_id, 'TextInput') self.assertEqual(state_answers.get_submitted_answer_dict_list(), [{ 'answer': 'answer a', 'time_spent_in_sec': 10.0, 'answer_group_index': 0, 'rule_spec_index': 1, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }, { 'answer': 'answer ccc', 'time_spent_in_sec': 3.0, 'answer_group_index': 1, 'rule_spec_index': 1, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }, { 'answer': 'answer bbbbb', 'time_spent_in_sec': 7.5, 'answer_group_index': 1, 'rule_spec_index': 0, 'classification_categorization': 'explicit', 'session_id': 'session_id_v', 'interaction_id': 'TextInput', 'params': {} }])
def test_record_answers_exceeding_one_shard(self): # Use a smaller max answer list size so less answers are needed to # exceed a shard. with self.swap(stats_models.StateAnswersModel, '_MAX_ANSWER_LIST_BYTE_SIZE', 100000): state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertIsNone(state_answers) submitted_answer_list = [ stats_domain.SubmittedAnswer( 'answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer( 'answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer( 'answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] stats_services.record_answers(self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list * 200) # Verify more than 1 shard was stored. The index shard (shard_id 0) # is not included in the shard count. model = stats_models.StateAnswersModel.get( '%s:%s:%s:%s' % (self.exploration.id, str(self.exploration.version), self.exploration.init_state_name, '0')) self.assertEqual(model.shard_count, 1) # The order of the answers returned depends on the size of the # answers. state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(state_answers.exploration_id, 'exp_id0') self.assertEqual(state_answers.exploration_version, 1) self.assertEqual(state_answers.state_name, feconf.DEFAULT_INIT_STATE_NAME) self.assertEqual(state_answers.interaction_id, 'TextInput') self.assertEqual( len(state_answers.get_submitted_answer_dict_list()), 600)
def test_record_answers_exceeding_one_shard(self): # Use a smaller max answer list size so less answers are needed to # exceed a shard. with self.swap( stats_models.StateAnswersModel, '_MAX_ANSWER_LIST_BYTE_SIZE', 100000): state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertIsNone(state_answers) submitted_answer_list = [ stats_domain.SubmittedAnswer( 'answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer( 'answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer( 'answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] stats_services.record_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list * 200) # Verify more than 1 shard was stored. The index shard (shard_id 0) # is not included in the shard count. model = stats_models.StateAnswersModel.get('%s:%s:%s:%s' % ( self.exploration.id, str(self.exploration.version), self.exploration.init_state_name, '0')) self.assertEqual(model.shard_count, 1) # The order of the answers returned depends on the size of the # answers. state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(state_answers.exploration_id, 'exp_id0') self.assertEqual(state_answers.exploration_version, 1) self.assertEqual( state_answers.state_name, feconf.DEFAULT_INIT_STATE_NAME) self.assertEqual(state_answers.interaction_id, 'TextInput') self.assertEqual( len(state_answers.get_submitted_answer_dict_list()), 600)
def test_exactly_100_answers_returned_if_main_shard_has_100_answers(self): submitted_answer_list = [ stats_domain.SubmittedAnswer('answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0) ] # Record 100 answers. stats_services.record_answers(self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list * 100) sample_answers = stats_services.get_sample_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(sample_answers, ['answer a'] * 100)
def test_that_state_answers_sharded_models_accumulate_stats(self): with self.swap(stats_models.StateAnswersModel, '_MAX_ANSWER_LIST_BYTE_SIZE', 100000): submitted_answer_list = [ stats_domain.SubmittedAnswer( 'answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer( 'answer ccc', 'TextInput', 1, 1, exp_domain.DEFAULT_OUTCOME_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer( 'answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] stats_services.record_answers(self.exp_id, self.exploration.version, 'Home', 'TextInput', submitted_answer_list * 200) job_id = stats_jobs_one_off.GenerateV1StatisticsJob.create_new() stats_jobs_one_off.GenerateV1StatisticsJob.enqueue(job_id) self.assertEqual( self.count_jobs_in_taskqueue( taskqueue_services.QUEUE_NAME_ONE_OFF_JOBS), 1) self.process_and_flush_pending_tasks() exploration_stats = stats_services.get_exploration_stats_by_id( self.exp_id, self.exploration.version) # There are an additional two answers from the setup function. self.assertEqual( exploration_stats.state_stats_mapping['Home']. total_answers_count_v1, 602) # There is an additional answer from the setup function. self.assertEqual( exploration_stats.state_stats_mapping['Home']. useful_feedback_count_v1, 401)
def test_at_most_100_answers_returned_even_if_there_are_lots(self): submitted_answer_list = [ stats_domain.SubmittedAnswer('answer a', 'TextInput', 0, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 10.0), stats_domain.SubmittedAnswer('answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), stats_domain.SubmittedAnswer('answer bbbbb', 'TextInput', 1, 0, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 7.5), ] # Record 600 answers. stats_services.record_answers(self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list * 200) sample_answers = stats_services.get_sample_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertEqual(len(sample_answers), 100)
def test_only_sample_answers_in_main_shard_returned(self): # Use a smaller max answer list size so fewer answers are needed to # exceed a shard. with self.swap(stats_models.StateAnswersModel, '_MAX_ANSWER_LIST_BYTE_SIZE', 15000): state_answers = stats_services.get_state_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertIsNone(state_answers) submitted_answer_list = [ stats_domain.SubmittedAnswer( 'answer ccc', 'TextInput', 1, 1, exp_domain.EXPLICIT_CLASSIFICATION, {}, 'session_id_v', 3.0), ] stats_services.record_answers(self.EXP_ID, self.exploration.version, self.exploration.init_state_name, 'TextInput', submitted_answer_list * 100) # Verify more than 1 shard was stored. The index shard (shard_id 0) # is not included in the shard count. Since a total of 100 answers were # submitted, there must therefore be fewer than 100 answers in the # index shard. model = stats_models.StateAnswersModel.get( '%s:%s:%s:%s' % (self.exploration.id, str(self.exploration.version), self.exploration.init_state_name, '0')) self.assertEqual(model.shard_count, 1) # Verify that the list of sample answers returned contains fewer than # 100 answers, although a total of 100 answers were submitted. sample_answers = stats_services.get_sample_answers( self.EXP_ID, self.exploration.version, self.exploration.init_state_name) self.assertLess(len(sample_answers), 100)