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) assert 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: assert set(userreport.keys()) == set(query_features) assert userreport['enrollment_mode'] in ['audit'] assert userreport['verification_status'] in ['N/A'] # make sure that the user report respects whatever value # is returned by verification and enrollment code with patch( "common.djangoapps.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) assert len(userreports) == len(self.users) for userreport in userreports: assert set(userreport.keys()) == set(query_features) assert userreport['enrollment_mode'] in ['verified'] assert userreport['verification_status'] in [ 'dummy verification status' ]
def test_enrolled_student_features_external_user_keys(self): query_features = ('username', 'name', 'email', 'city', 'country', 'external_user_key') username_with_external_user_key_dict = {} for i in range(len(self.users)): # Setup some users with ProgramEnrollments if i % 2 == 0: user = self.users[i] external_user_key = f'{user.username}_{i}' ProgramEnrollmentFactory.create( user=user, external_user_key=external_user_key) username_with_external_user_key_dict[ user.username] = external_user_key with self.assertNumQueries(2): userreports = enrolled_students_features(self.course_key, query_features) assert len(userreports) == 30 for report in userreports: username = report['username'] external_key = username_with_external_user_key_dict.get(username) if external_key: assert external_key == report['external_user_key'] else: assert '' == report['external_user_key']
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) enrolled_students = CourseEnrollment.objects.users_enrolled_in(course_id) task_progress = TaskProgress(action_name, enrolled_students.count(), 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 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 = f"Mos Eisley {user.id}" user.profile.country = f"Tatooine {user.id}" user.profile.save() for feature in query_features: assert feature in AVAILABLE_FEATURES with self.assertNumQueries(1): userreports = enrolled_students_features(self.course_key, query_features) assert 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): assert set(userreport.keys()) == set(query_features) assert userreport['username'] == user.username assert userreport['email'] == user.email assert userreport['name'] == user.profile.name assert userreport['city'] == user.profile.city assert userreport['country'] == user.profile.country
def test_enrolled_students_features_keys(self): query_features = ( 'username', 'name', 'email', 'city', 'country', ) for user in self.users: user.profile.city = u"Mos Eisley {}".format(user.id) user.profile.country = u"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 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) assert len([r for r in userreports if r['username'] in cohorted_usernames]) == len(cohorted_students) assert len([r for r in userreports if r['username'] == non_cohorted_student.username]) == 1 for report in userreports: assert set(report.keys()) == set(query_features) if report['username'] in cohorted_usernames: assert report['cohort'] == cohort.name else: assert report['cohort'] == '[unassigned]'
def test_enrolled_students_features_username(self): assert 'username' in AVAILABLE_FEATURES userreports = enrolled_students_features(self.course_key, ['username']) assert len(userreports) == len(self.users) for userreport in userreports: assert list(userreport.keys()) == ['username'] assert userreport['username'] in [user.username for user in self.users]
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 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. assert userreport['city'] == 'None' assert userreport['country'] == ''
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) assert len(userreports) == len(self.users) for userreport in userreports: assert set(userreport.keys()) == set(query_features) assert userreport['meta.position'] in [f"edX expert {user.id}" for user in self.users] assert userreport['meta.company'] in [f"Open edX Inc {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])