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']
Ejemplo n.º 3
0
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
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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]'
Ejemplo n.º 7
0
 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]
Ejemplo n.º 8
0
 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])
Ejemplo n.º 9
0
 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'] == ''
Ejemplo n.º 10
0
 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]
Ejemplo n.º 11
0
 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])