def test__filter_notified(self): num_previous = 2 # Instantiate so can use its dao for setup obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) self.create_preexisting_review_pairings(self.activity_id, self.students, obj.dao.session) self.make_feedback_received_records(num_previous, session=obj.dao.session) self.workRepo = MagicMock() obj.work_repo = self.workRepo reviewers_with_notified_authors = [ r.assessor_id for r in self.pairings if r.assessee_id in self.previously_sent ] # print(reviewers_with_authors_sent_feedback) # ra = obj.dao.session.query(ReviewAssociation).all() # fb = obj.dao.session.query(FeedbackReceivedRecord).all() # call obj._filter_notified() # check self.assertIsInstance(obj.statusRepos[0], FeedbackStatusRepository, "Correct status repo used") self.workRepo.remove_student_records.assert_called() call_args = [ c[0][0] for c in self.workRepo.remove_student_records.call_args_list ] print(call_args) expected = [ r for r in self.student_ids if r in reviewers_with_notified_authors ] self.assertEqual( expected, call_args[0], "Submitters whose authors have already been sent feedback were removed" )
def test_instantiates_w_correct_values(self): """Dummy checking in case some of the main variables used change""" obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) self.assertIsInstance(obj.statusRepos[0], FeedbackStatusRepository, "Correct status repo instantiated") self.assertEqual(obj.statusRepos[0].activity, self.activity, "Status repo instantiated with correct activity") self.assertIsInstance(obj.activity_notifying_about, DiscussionReview, "Notifying about expected type of activity") self.assertEqual(obj.activity_notifying_about, self.unit.discussion_review, "Expected activity") self.assertIsInstance( obj.activity_for_review_pairings, DiscussionReview, "Review pairings based on expected activity type: Discussion review" ) self.assertEqual(obj.activity_for_review_pairings, self.unit.discussion_review, "Expected activity") self.assertIsInstance( obj.activity, DiscussionReview, "Working on results from expected activity type") self.assertEqual(obj.activity, self.unit.discussion_review, "Expected activity")
def test__load_step(self, workLoaderMock, displayManagerMock): self.workRepo.remove_student_records = MagicMock() workLoaderMock.make = MagicMock(return_value=self.workRepo) obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) # obj.display_manager = create_autospec(DisplayManager) # obj.statusRepos = create_autospec(FeedbackStatusRepository, previously_sent_students=self.preexisting_student_ids) # call obj._load_step() # check workLoaderMock.make.assert_called() displayManagerMock.assert_called() call_args = [c[0][0] for c in workLoaderMock.call_args_list] print(call_args)
def test_instantiates_correct_status_repos(self): """The sending of metareview results requires a special status repository""" obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) self.assertIsInstance(obj.statusRepos, list, "status repos is a list") self.assertTrue(len(obj.statusRepos) == 1) self.assertIsInstance(obj.feedback_status_repo, FeedbackStatusRepository, "Invite repo instantiated")
def test__assign_step(self, displayManagerMock): # self.workRepo.remove_student_records = MagicMock() # workLoaderMock.make = MagicMock( return_value=self.workRepo ) obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) obj.work_repo = MagicMock(submitter_ids=self.preexisting_student_ids) obj._filter_notified = MagicMock() self.preexisting_pairings = self.create_preexisting_review_pairings( self.activity_id, self.students, obj.dao.session) # call obj._assign_step() # check obj._filter_notified.assert_called() self.assertEqual(len(self.preexisting_student_ids), len(obj.associations))
def test__message_step(self, workLoaderMock, studentRepoMock, messengerMock, statusRepoMock): students = {s.student_id: s for s in self.students} def se(sid): return students.get(sid) obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) # setup work repository (use all students since no filtering occurs here) self.workRepo.submitter_ids = self.student_ids obj.work_repo = self.workRepo # setup students obj.studentRepo.get_student = MagicMock(side_effect=se) obj.studentRepo.download = MagicMock(return_value=self.students) # setup review pairings preexisting_pairings = self.create_preexisting_review_pairings( self.activity_id, self.students, obj.dao.session) obj.associations = preexisting_pairings # call obj._message_step() # ================== Events on Messenger # Check that mocked objects were called with expected data messengerMock.assert_called() self.assertEqual(messengerMock.call_count, len(self.student_ids), "Send method called expected number of times") messenger_args = [(c[1]['student_id'], c[1]['subject'], c[1]['body']) for c in messengerMock.call_args_list] # print(args) # Check that all messages have the correct subject for sid, subj, body in messenger_args: expect_subj = FeedbackFromDiscussionReviewMessenger.email_subject_templ.format( self.unit.unit_number) self.assertEqual(expect_subj, subj, "Correct subject line") # Status repo calls on messenger obj.messenger.status_repositories[0].record.assert_called() call_list = obj.messenger.status_repositories[0].record.call_args_list status_args = [c[0][0] for c in call_list] self.assertEqual(len(self.students), len(call_list), "Status repo record called expected number of times") for sid in self.student_ids: self.assertIn(sid, status_args, "StatusRepo.record called on all students") # student repo calls on messenger for sid in self.student_ids: obj.messenger.student_repository.get_student.assert_any_call(sid) # Check the content sent for record in obj.associations: # This is the review which the assessor has submitted author_text = self.workRepo.get_formatted_work_by( record.assessor_id) # which we are sending to the person who created the posts sent_text = [ t[2] for t in messenger_args if t[0] == record.assessee_id ][0] rx = r'{}'.format(author_text) self.assertRegex(sent_text, rx, "Author's work in message sent to reviewer")
def test_run_previously_sent(self, workLoaderMock, studentRepoMock, messengerMock): authors_who_have_not_been_notified = self.new_students_ids authors_who_have_been_previously_notified = self.preexisting_student_ids students = {s.student_id: s for s in self.students} def se(sid): return students.get(sid) obj = SendDiscussionReviewToPoster(course=self.course, unit=self.unit, is_test=True, send=True) # setup students obj.studentRepo.get_student = MagicMock(side_effect=se) obj.studentRepo.download = MagicMock(return_value=self.students) # setup review pairings preexisting_pairings = self.create_preexisting_review_pairings( self.activity_id, self.students, obj.dao.session) reviewers_with_notified_authors = [ r.assessor_id for r in preexisting_pairings if r.assessee_id in authors_who_have_been_previously_notified ] reviewers_without_notified_authors = [ s for s in self.student_ids if s not in reviewers_with_notified_authors ] obj.statusRepos = [ create_autospec( FeedbackStatusRepository, reviewers_with_notified_authors=reviewers_with_notified_authors ) ] # This will be handled by the _filter_notified step. But since # we are using a dummy work repo, calling remove_student_records won't do anything # Thus we need to pretend that it did its job. (We've tested it elsewhere) self.workRepo.submitter_ids = reviewers_without_notified_authors workLoaderMock.make = MagicMock(return_value=self.workRepo) # call obj.run() # ================== Events on Messenger # Check that mocked objects were called with expected data messengerMock.assert_called() self.assertEqual(messengerMock.call_count, len(authors_who_have_not_been_notified), "Send method called expected number of times") messenger_args = [(c[1]['student_id'], c[1]['subject'], c[1]['body']) for c in messengerMock.call_args_list] # Check that all messages have the correct subject for sid, subj, body in messenger_args: expect_subj = FeedbackFromDiscussionReviewMessenger.email_subject_templ.format( self.unit.unit_number) self.assertEqual(expect_subj, subj, "Correct subject line") # Status repo calls on messenger which # record the message having been sent to authors obj.messenger.status_repositories[0].record.assert_called() call_list = obj.messenger.status_repositories[0].record.call_args_list status_args = [c[0][0] for c in call_list] self.assertEqual(len(authors_who_have_not_been_notified), len(call_list), "Status repo record called expected number of times") for sid in authors_who_have_not_been_notified: self.assertIn( sid, status_args, "StatusRepo.record called on authors who have now received their feedback (i.e., from newly submitted reviewers)" ) # student repo calls on messenger for sid in authors_who_have_not_been_notified: obj.messenger.student_repository.get_student.assert_any_call(sid) # Check the content sent for record in obj.associations: # This is the review which the assessor has submitted author_text = self.workRepo.get_formatted_work_by( record.assessor_id) # which we are sending to the person who created the posts sent_text = [ t[2] for t in messenger_args if t[0] == record.assessee_id ][0] rx = r'{}'.format(author_text) self.assertRegex(sent_text, rx, "Author's work in message sent to reviewer")