def test_enrolled_students_enrollment_verification(self): """ Assert that we can get enrollment mode and verification status """ query_features = ('enrollment_mode', 'verification_status') userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) # by default all users should have "audit" as their enrollment mode # and "N/A" as their verification status for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['enrollment_mode'], ["audit"]) self.assertIn(userreport['verification_status'], ["N/A"]) # make sure that the user report respects whatever value # is returned by verification and enrollment code with patch("student.models.CourseEnrollment.enrollment_mode_for_user") as enrollment_patch: with patch( "lms.djangoapps.verify_student.services.IDVerificationService.verification_status_for_user" ) as verify_patch: enrollment_patch.return_value = ["verified"] verify_patch.return_value = "dummy verification status" userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['enrollment_mode'], ["verified"]) self.assertIn(userreport['verification_status'], ["dummy verification status"])
def test_enrolled_students_enrollment_verification(self): """ Assert that we can get enrollment mode and verification status """ query_features = ('enrollment_mode', 'verification_status') userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) # by default all users should have "audit" as their enrollment mode # and "N/A" as their verification status for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['enrollment_mode'], ["audit"]) self.assertIn(userreport['verification_status'], ["N/A"]) # make sure that the user report respects whatever value # is returned by verification and enrollment code with patch("student.models.CourseEnrollment.enrollment_mode_for_user") as enrollment_patch: with patch( "lms.djangoapps.verify_student.services.IDVerificationService.verification_status_for_user" ) as verify_patch: enrollment_patch.return_value = ["verified"] verify_patch.return_value = "dummy verification status" userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['enrollment_mode'], ["verified"]) self.assertIn(userreport['verification_status'], ["dummy verification status"])
def test_enrolled_students_features_keys_cohorted(self): course = CourseFactory.create(org="test", course="course1", display_name="run1") course.cohort_config = {'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort']} self.store.update_item(course, self.instructor.id) cohorted_students = [UserFactory.create() for _ in xrange(10)] cohort = CohortFactory.create(name='cohort', course_id=course.id, users=cohorted_students) cohorted_usernames = [student.username for student in cohorted_students] non_cohorted_student = UserFactory.create() for student in cohorted_students: cohort.users.add(student) CourseEnrollment.enroll(student, course.id) CourseEnrollment.enroll(non_cohorted_student, course.id) instructor = InstructorFactory(course_key=course.id) self.client.login(username=instructor.username, password='******') query_features = ('username', 'cohort') # There should be a constant of 2 SQL queries when calling # enrolled_students_features. The first query comes from the call to # User.objects.filter(...), and the second comes from # prefetch_related('course_groups'). with self.assertNumQueries(2): userreports = enrolled_students_features(course.id, query_features) self.assertEqual(len([r for r in userreports if r['username'] in cohorted_usernames]), len(cohorted_students)) self.assertEqual(len([r for r in userreports if r['username'] == non_cohorted_student.username]), 1) for report in userreports: self.assertEqual(set(report.keys()), set(query_features)) if report['username'] in cohorted_usernames: self.assertEqual(report['cohort'], cohort.name) else: self.assertEqual(report['cohort'], '[unassigned]')
def test_enrolled_students_features_username(self): self.assertIn('username', AVAILABLE_FEATURES) userreports = enrolled_students_features(self.course_key, ['username']) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(userreport.keys(), ['username']) self.assertIn(userreport['username'], [user.username for user in self.users])
def test_enrolled_students_features_keys_cohorted(self): course = CourseFactory.create(org="test", course="course1", display_name="run1") course.cohort_config = {'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort']} self.store.update_item(course, self.instructor.id) cohorted_students = [UserFactory.create() for _ in range(10)] cohort = CohortFactory.create(name='cohort', course_id=course.id, users=cohorted_students) cohorted_usernames = [student.username for student in cohorted_students] non_cohorted_student = UserFactory.create() for student in cohorted_students: cohort.users.add(student) CourseEnrollment.enroll(student, course.id) CourseEnrollment.enroll(non_cohorted_student, course.id) instructor = InstructorFactory(course_key=course.id) self.client.login(username=instructor.username, password='******') query_features = ('username', 'cohort') # There should be a constant of 2 SQL queries when calling # enrolled_students_features. The first query comes from the call to # User.objects.filter(...), and the second comes from # prefetch_related('course_groups'). with self.assertNumQueries(2): userreports = enrolled_students_features(course.id, query_features) self.assertEqual(len([r for r in userreports if r['username'] in cohorted_usernames]), len(cohorted_students)) self.assertEqual(len([r for r in userreports if r['username'] == non_cohorted_student.username]), 1) for report in userreports: self.assertEqual(set(report.keys()), set(query_features)) if report['username'] in cohorted_usernames: self.assertEqual(report['cohort'], cohort.name) else: self.assertEqual(report['cohort'], '[unassigned]')
def test_enrolled_students_features_username(self): self.assertIn('username', AVAILABLE_FEATURES) userreports = enrolled_students_features(self.course_key, ['username']) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(list(userreport.keys()), ['username']) self.assertIn(userreport['username'], [user.username for user in self.users])
def upload_students_csv(_xmodule_instance_args, _entry_id, course_id, task_input, action_name): """ For a given `course_id`, generate a CSV file containing profile information for all students that are enrolled, and store using a `ReportStore`. """ start_time = time() start_date = datetime.now(UTC) task_progress = TaskProgress(action_name, CourseEnrollment.num_enrolled_in(course_id), start_time) current_step = {'step': 'Calculating Profile Info'} task_progress.update_task_state(extra_meta=current_step) # compute the student features table and format it query_features = task_input.get('features') student_data = enrolled_students_features(course_id, query_features) header, rows = format_dictlist(student_data, query_features) task_progress.attempted = task_progress.succeeded = len(rows) task_progress.skipped = task_progress.total - task_progress.attempted rows.insert(0, header) current_step = {'step': 'Uploading CSV'} task_progress.update_task_state(extra_meta=current_step) # Perform the upload upload_csv_to_report_store(rows, 'student_profile_info', course_id, start_date) return task_progress.update_task_state(extra_meta=current_step)
def test_enrolled_students_features_keys(self): query_features = ( 'username', 'name', 'email', 'city', 'country', ) for user in self.users: user.profile.city = "Mos Eisley {}".format(user.id) user.profile.country = "Tatooine {}".format(user.id) user.profile.save() for feature in query_features: self.assertIn(feature, AVAILABLE_FEATURES) with self.assertNumQueries(1): userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) userreports = sorted(userreports, key=lambda u: u["username"]) users = sorted(self.users, key=lambda u: u.username) for userreport, user in zip(userreports, users): self.assertEqual(set(userreport.keys()), set(query_features)) self.assertEqual(userreport['username'], user.username) self.assertEqual(userreport['email'], user.email) self.assertEqual(userreport['name'], user.profile.name) self.assertEqual(userreport['city'], user.profile.city) self.assertEqual(userreport['country'], user.profile.country)
def upload_students_csv(_xmodule_instance_args, _entry_id, course_id, task_input, action_name): """ For a given `course_id`, generate a CSV file containing profile information for all students that are enrolled, and store using a `ReportStore`. """ start_time = time() start_date = datetime.now(UTC) task_progress = TaskProgress(action_name, CourseEnrollment.num_enrolled_in(course_id), start_time) current_step = {'step': 'Calculating Profile Info'} task_progress.update_task_state(extra_meta=current_step) # compute the student features table and format it query_features = task_input.get('features') student_data = enrolled_students_features(course_id, query_features) header, rows = format_dictlist(student_data, query_features) task_progress.attempted = task_progress.succeeded = len(rows) task_progress.skipped = task_progress.total - task_progress.attempted rows.insert(0, header) current_step = {'step': 'Uploading CSV'} task_progress.update_task_state(extra_meta=current_step) # Perform the upload upload_csv_to_report_store(rows, 'student_profile_info', course_id, start_date) return task_progress.update_task_state(extra_meta=current_step)
def test_enrolled_student_with_no_country_city(self): userreports = enrolled_students_features(self.course_key, ('username', 'city', 'country',)) for userreport in userreports: # This behaviour is somewhat inconsistent: None string fields # objects are converted to "None", but non-JSON serializable fields # are converted to an empty string. self.assertEqual(userreport['city'], "None") self.assertEqual(userreport['country'], "")
def test_enrolled_student_with_no_country_city(self): userreports = enrolled_students_features(self.course_key, ('username', 'city', 'country',)) for userreport in userreports: # This behaviour is somewhat inconsistent: None string fields # objects are converted to "None", but non-JSON serializable fields # are converted to an empty string. self.assertEqual(userreport['city'], "None") self.assertEqual(userreport['country'], "")
def test_enrolled_students_features_keys(self): query_features = ('username', 'name', 'email') for feature in query_features: self.assertIn(feature, AVAILABLE_FEATURES) userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['username'], [user.username for user in self.users]) self.assertIn(userreport['email'], [user.email for user in self.users]) self.assertIn(userreport['name'], [user.profile.name for user in self.users])
def test_enrolled_students_meta_features_keys(self): """ Assert that we can query individual fields in the 'meta' field in the UserProfile """ query_features = ('meta.position', 'meta.company') with self.assertNumQueries(1): userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['meta.position'], ["edX expert {}".format(user.id) for user in self.users]) self.assertIn(userreport['meta.company'], ["Open edX Inc {}".format(user.id) for user in self.users])
def test_enrolled_students_meta_features_keys(self): """ Assert that we can query individual fields in the 'meta' field in the UserProfile """ query_features = ('meta.position', 'meta.company') with self.assertNumQueries(1): userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) for userreport in userreports: self.assertEqual(set(userreport.keys()), set(query_features)) self.assertIn(userreport['meta.position'], [u"edX expert {}".format(user.id) for user in self.users]) self.assertIn(userreport['meta.company'], [u"Open edX Inc {}".format(user.id) for user in self.users])
def push_students_csv_to_s3(_xmodule_instance_args, _entry_id, course_id, task_input, _action_name): """ For a given `course_id`, generate a CSV file containing profile information for all students that are enrolled, and store using a `ReportStore`. """ # compute the student features table and format it query_features = task_input.get('features') student_data = enrolled_students_features(course_id, query_features) header, rows = format_dictlist(student_data, query_features) rows.insert(0, header) # Perform the upload upload_csv_to_report_store(rows, 'student_profile_info', course_id, datetime.now(UTC)) return UPDATE_STATUS_SUCCEEDED
def test_enrolled_students_features_keys(self): query_features = ('username', 'name', 'email', 'city', 'country',) for user in self.users: user.profile.city = "Mos Eisley {}".format(user.id) user.profile.country = "Tatooine {}".format(user.id) user.profile.save() for feature in query_features: self.assertIn(feature, AVAILABLE_FEATURES) with self.assertNumQueries(1): userreports = enrolled_students_features(self.course_key, query_features) self.assertEqual(len(userreports), len(self.users)) userreports = sorted(userreports, key=lambda u: u["username"]) users = sorted(self.users, key=lambda u: u.username) for userreport, user in zip(userreports, users): self.assertEqual(set(userreport.keys()), set(query_features)) self.assertEqual(userreport['username'], user.username) self.assertEqual(userreport['email'], user.email) self.assertEqual(userreport['name'], user.profile.name) self.assertEqual(userreport['city'], user.profile.city) self.assertEqual(userreport['country'], user.profile.country)