Beispiel #1
0
    def test_add_user_to_cohort(self):
        """
        Make sure cohorts.add_user_to_cohort() properly adds a user to a cohort and
        handles errors.
        """
        course_user = UserFactory(username="******", email="*****@*****.**")
        UserFactory(username="******", email="*****@*****.**")
        course = modulestore().get_course(self.toy_course_key)
        CourseEnrollment.enroll(course_user, self.toy_course_key)
        first_cohort = CohortFactory(course_id=course.id, name="FirstCohort")
        second_cohort = CohortFactory(course_id=course.id, name="SecondCohort")

        # Success cases
        # We shouldn't get back a previous cohort, since the user wasn't in one
        self.assertEqual(cohorts.add_user_to_cohort(first_cohort, "Username"),
                         (course_user, None))
        # Should get (user, previous_cohort_name) when moved from one cohort to
        # another
        self.assertEqual(cohorts.add_user_to_cohort(second_cohort, "Username"),
                         (course_user, "FirstCohort"))

        # Error cases
        # Should get ValueError if user already in cohort
        self.assertRaises(
            ValueError,
            lambda: cohorts.add_user_to_cohort(second_cohort, "Username"))
        # UserDoesNotExist if user truly does not exist
        self.assertRaises(
            User.DoesNotExist, lambda: cohorts.add_user_to_cohort(
                first_cohort, "non_existent_username"))
Beispiel #2
0
    def test_delete_empty_cohort(self):
        """
        Make sure that cohorts.delete_empty_cohort() properly removes an empty cohort
        for a given course.
        """
        course = modulestore().get_course(self.toy_course_key)
        user = UserFactory(username="******", email="*****@*****.**")
        empty_cohort = CohortFactory(course_id=course.id, name="EmptyCohort")
        nonempty_cohort = CohortFactory(course_id=course.id,
                                        name="NonemptyCohort")
        nonempty_cohort.users.add(user)

        cohorts.delete_empty_cohort(course.id, "EmptyCohort")

        # Make sure we cannot access the deleted cohort
        self.assertRaises(
            CourseUserGroup.DoesNotExist,
            lambda: cohorts.get_cohort_by_id(course.id, empty_cohort.id))
        self.assertRaises(
            ValueError,
            lambda: cohorts.delete_empty_cohort(course.id, "NonemptyCohort"))
        self.assertRaises(
            CourseUserGroup.DoesNotExist, lambda: cohorts.delete_empty_cohort(
                SlashSeparatedCourseKey('course', 'does_not', 'exist'),
                "EmptyCohort"))
        self.assertRaises(
            CourseUserGroup.DoesNotExist, lambda: cohorts.delete_empty_cohort(
                course.id, "NonExistentCohort"))
Beispiel #3
0
    def test_get_cohort_by_id(self):
        """
        Make sure cohorts.get_cohort_by_id() properly finds a cohort by id for a given
        course.
        """
        course = modulestore().get_course(self.toy_course_key)
        cohort = CohortFactory(course_id=course.id, name="MyCohort")

        self.assertEqual(cohorts.get_cohort_by_id(course.id, cohort.id),
                         cohort)

        cohort.delete()

        self.assertRaises(
            CourseUserGroup.DoesNotExist,
            lambda: cohorts.get_cohort_by_id(course.id, cohort.id))
Beispiel #4
0
 def _create_cohorts(self):
     """Creates cohorts for testing"""
     self.cohort1_users = [UserFactory() for _ in range(3)]
     self.cohort2_users = [UserFactory() for _ in range(2)]
     self.cohort3_users = [UserFactory() for _ in range(2)]
     self.cohortless_users = [UserFactory() for _ in range(3)]
     self.unenrolled_users = [UserFactory() for _ in range(3)]
     self._enroll_users(
         self.cohort1_users + self.cohort2_users + self.cohort3_users +
         self.cohortless_users, self.course.id)
     self.cohort1 = CohortFactory(course_id=self.course.id,
                                  users=self.cohort1_users)
     self.cohort2 = CohortFactory(course_id=self.course.id,
                                  users=self.cohort2_users)
     self.cohort3 = CohortFactory(course_id=self.course.id,
                                  users=self.cohort3_users)
    def test_enrolled_students_features_keys_cohorted(self):
        course = CourseFactory.create(course_key=self.course_key)
        course.cohort_config = {'cohorted': True, 'auto_cohort': True, 'auto_cohort_groups': ['cohort']}
        self.store.update_item(course, self.instructor.id)
        cohort = CohortFactory.create(name='cohort', course_id=course.id)
        cohorted_students = [UserFactory.create() for _ in xrange(10)]
        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]')
Beispiel #6
0
    def test_get_cohort(self):
        """
        Make sure cohorts.get_cohort() does the right thing when the course is cohorted
        """
        course = modulestore().get_course(self.toy_course_key)
        self.assertEqual(course.id, self.toy_course_key)
        self.assertFalse(course.is_cohorted)

        user = UserFactory(username="******", email="*****@*****.**")
        other_user = UserFactory(username="******", email="*****@*****.**")

        self.assertIsNone(cohorts.get_cohort(user, course.id),
                          "No cohort created yet")

        cohort = CohortFactory(course_id=course.id, name="TestCohort")
        cohort.users.add(user)

        self.assertIsNone(cohorts.get_cohort(user, course.id),
                          "Course isn't cohorted, so shouldn't have a cohort")

        # Make the course cohorted...
        config_course_cohorts(course, discussions=[], cohorted=True)

        self.assertEquals(
            cohorts.get_cohort(user, course.id).id, cohort.id,
            "user should be assigned to the correct cohort")
        self.assertEquals(
            cohorts.get_cohort(other_user, course.id).id,
            cohorts.get_cohort_by_name(course.id,
                                       cohorts.DEFAULT_COHORT_NAME).id,
            "other_user should be assigned to the default cohort")
Beispiel #7
0
    def test_get_cohort_by_id(self):
        """
        Make sure cohorts.get_cohort_by_id() properly finds a cohort by id for a given
        course.
        """
        course = modulestore().get_course(self.toy_course_key)
        cohort = CohortFactory(course_id=course.id, name="MyCohort")

        self.assertEqual(cohorts.get_cohort_by_id(course.id, cohort.id), cohort)

        cohort.delete()

        self.assertRaises(
            CourseUserGroup.DoesNotExist,
            lambda: cohorts.get_cohort_by_id(course.id, cohort.id)
        )
Beispiel #8
0
    def test_cohort_membership_changed(self, mock_tracker):
        cohort_list = [CohortFactory() for _ in range(2)]
        non_cohort = CourseUserGroup.objects.create(name="dummy",
                                                    course_id=self.course_key,
                                                    group_type="dummy")
        user_list = [UserFactory() for _ in range(2)]
        mock_tracker.reset_mock()

        def assert_events(event_name_suffix, user_list, cohort_list):
            mock_tracker.emit.assert_has_calls([
                call(
                    "edx.cohort.user_" + event_name_suffix, {
                        "user_id": user.id,
                        "cohort_id": cohort.id,
                        "cohort_name": cohort.name,
                    }) for user in user_list for cohort in cohort_list
            ])

        # Add users to cohort
        cohort_list[0].users.add(*user_list)
        assert_events("added", user_list, cohort_list[:1])
        mock_tracker.reset_mock()

        # Remove users from cohort
        cohort_list[0].users.remove(*user_list)
        assert_events("removed", user_list, cohort_list[:1])
        mock_tracker.reset_mock()

        # Clear users from cohort
        cohort_list[0].users.add(*user_list)
        cohort_list[0].users.clear()
        assert_events("removed", user_list, cohort_list[:1])
        mock_tracker.reset_mock()

        # Clear users from non-cohort group
        non_cohort.users.add(*user_list)
        non_cohort.users.clear()
        self.assertFalse(mock_tracker.emit.called)

        # Add cohorts to user
        user_list[0].course_groups.add(*cohort_list)
        assert_events("added", user_list[:1], cohort_list)
        mock_tracker.reset_mock()

        # Remove cohorts from user
        user_list[0].course_groups.remove(*cohort_list)
        assert_events("removed", user_list[:1], cohort_list)
        mock_tracker.reset_mock()

        # Clear cohorts from user
        user_list[0].course_groups.add(*cohort_list)
        user_list[0].course_groups.clear()
        assert_events("removed", user_list[:1], cohort_list)
        mock_tracker.reset_mock()

        # Clear non-cohort groups from user
        user_list[0].course_groups.add(non_cohort)
        user_list[0].course_groups.clear()
        self.assertFalse(mock_tracker.emit.called)
Beispiel #9
0
 def test_non_staff(self):
     """
     Verify that non-staff users cannot access `check_users_in_cohort`.
     """
     cohort = CohortFactory(course_id=self.course.id, users=[])
     self._verify_non_staff_cannot_access(
         remove_user_from_cohort, "POST",
         [self.course.id.to_deprecated_string(), cohort.id])
Beispiel #10
0
    def test_get_course_cohorts(self):
        """
        Tests that get_course_cohorts returns all cohorts, including auto cohorts.
        """
        course = modulestore().get_course(self.toy_course_key)
        config_course_cohorts(course, [],
                              cohorted=True,
                              auto_cohort_groups=["AutoGroup1", "AutoGroup2"])

        # add manual cohorts to course 1
        CohortFactory(course_id=course.id, name="ManualCohort")
        CohortFactory(course_id=course.id, name="ManualCohort2")

        cohort_set = {c.name for c in cohorts.get_course_cohorts(course)}
        self.assertEqual(
            cohort_set,
            {"AutoGroup1", "AutoGroup2", "ManualCohort", "ManualCohort2"})
Beispiel #11
0
 def test_can_remove_user_from_cohort(self):
     """
     Verify that we can remove a user from a cohort.
     """
     user = UserFactory()
     cohort = CohortFactory(course_id=self.course.id, users=[user])
     response_dict = self.request_remove_user_from_cohort(
         user.username, cohort)
     self.verify_removed_user_from_cohort(user.username, response_dict,
                                          cohort)
Beispiel #12
0
 def test_can_remove_user_not_in_cohort(self):
     """
     Verify that we can "remove" a user from a cohort even if they are not a
     member of that cohort.
     """
     user = UserFactory()
     cohort = CohortFactory(course_id=self.course.id, users=[])
     response_dict = self.request_remove_user_from_cohort(
         user.username, cohort)
     self.verify_removed_user_from_cohort(user.username, response_dict,
                                          cohort)
Beispiel #13
0
 def test_no_username_given(self):
     """
     Verify that we get an error message when omitting a username.
     """
     cohort = CohortFactory(course_id=self.course.id, users=[])
     response_dict = self.request_remove_user_from_cohort(None, cohort)
     self.verify_removed_user_from_cohort(
         None,
         response_dict,
         cohort,
         expected_error_msg='No username specified')
Beispiel #14
0
 def test_no_users(self):
     """
     Verify that we don't get back any users for a cohort with no users.
     """
     cohort = CohortFactory(course_id=self.course.id, users=[])
     response_dict = self.request_users_in_cohort(cohort, self.course, 1)
     self.verify_users_in_cohort_and_response(cohort,
                                              response_dict,
                                              expected_users=[],
                                              expected_page=1,
                                              expected_num_pages=1)
Beispiel #15
0
 def test_user_does_not_exist(self):
     """
     Verify that we get an error message when the requested user to remove
     does not exist.
     """
     username = "******"
     cohort = CohortFactory(course_id=self.course.id, users=[])
     response_dict = self.request_remove_user_from_cohort(username, cohort)
     self.verify_removed_user_from_cohort(
         username,
         response_dict,
         cohort,
         expected_error_msg='No user \'{0}\''.format(username))
Beispiel #16
0
 def test_few_users(self):
     """
     Verify that we get back all users for a cohort when the cohort has
     <=100 users.
     """
     users = [UserFactory() for _ in range(5)]
     cohort = CohortFactory(course_id=self.course.id, users=users)
     response_dict = self.request_users_in_cohort(cohort, self.course, 1)
     self.verify_users_in_cohort_and_response(cohort,
                                              response_dict,
                                              expected_users=users,
                                              expected_page=1,
                                              expected_num_pages=1)
Beispiel #17
0
 def test_non_positive_page(self):
     """
     Verify that we get a `HttpResponseBadRequest` (bad request) when the
     page we request isn't a positive integer.
     """
     users = [UserFactory() for _ in range(5)]
     cohort = CohortFactory(course_id=self.course.id, users=users)
     self.request_users_in_cohort(cohort,
                                  self.course,
                                  "invalid",
                                  should_return_bad_request=True)
     self.request_users_in_cohort(cohort,
                                  self.course,
                                  -1,
                                  should_return_bad_request=True)
Beispiel #18
0
 def test_non_existent_cohort(self):
     """
     Verify that an error is raised when trying to add users to a cohort
     which does not belong to the given course.
     """
     users = [UserFactory(username="******".format(i)) for i in range(3)]
     usernames = [user.username for user in users]
     wrong_course_key = SlashSeparatedCourseKey("some", "arbitrary",
                                                "course")
     wrong_course_cohort = CohortFactory(name="wrong_cohort",
                                         course_id=wrong_course_key,
                                         users=[])
     self.request_add_users_to_cohort(",".join(usernames),
                                      wrong_course_cohort,
                                      self.course,
                                      should_raise_404=True)
Beispiel #19
0
 def test_many_users(self):
     """
     Verify that pagination works correctly for cohorts with >100 users.
     """
     users = [UserFactory() for _ in range(101)]
     cohort = CohortFactory(course_id=self.course.id, users=users)
     response_dict_1 = self.request_users_in_cohort(cohort, self.course, 1)
     response_dict_2 = self.request_users_in_cohort(cohort, self.course, 2)
     self.verify_users_in_cohort_and_response(cohort,
                                              response_dict_1,
                                              expected_users=users[:100],
                                              expected_page=1,
                                              expected_num_pages=2)
     self.verify_users_in_cohort_and_response(cohort,
                                              response_dict_2,
                                              expected_users=users[100:],
                                              expected_page=2,
                                              expected_num_pages=2)
Beispiel #20
0
    def test_enrolled_students_features_keys_cohorted(self):
        course = CourseFactory.create(course_key=self.course_key)
        course.cohort_config = {
            'cohorted': True,
            'auto_cohort': True,
            'auto_cohort_groups': ['cohort']
        }
        self.store.update_item(course, self.instructor.id)
        cohort = CohortFactory.create(name='cohort', course_id=course.id)
        cohorted_students = [UserFactory.create() for _ in xrange(10)]
        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]')
Beispiel #21
0
 def test_out_of_range(self):
     """
     Verify that we get a blank page of users when requesting page 0 or a
     page greater than the actual number of pages.
     """
     users = [UserFactory() for _ in range(5)]
     cohort = CohortFactory(course_id=self.course.id, users=users)
     response = self.request_users_in_cohort(cohort, self.course, 0)
     self.verify_users_in_cohort_and_response(cohort,
                                              response,
                                              expected_users=[],
                                              expected_page=0,
                                              expected_num_pages=1)
     response = self.request_users_in_cohort(cohort, self.course, 2)
     self.verify_users_in_cohort_and_response(cohort,
                                              response,
                                              expected_users=[],
                                              expected_page=2,
                                              expected_num_pages=1)
Beispiel #22
0
    def test_get_cohort_id(self):
        """
        Make sure that cohorts.get_cohort_id() correctly returns the cohort id, or raises a ValueError when given an
        invalid course key.
        """
        course = modulestore().get_course(self.toy_course_key)
        self.assertFalse(course.is_cohorted)

        user = UserFactory(username="******", email="*****@*****.**")
        self.assertIsNone(cohorts.get_cohort_id(user, course.id))

        config_course_cohorts(course, discussions=[], cohorted=True)
        cohort = CohortFactory(course_id=course.id, name="TestCohort")
        cohort.users.add(user)
        self.assertEqual(cohorts.get_cohort_id(user, course.id), cohort.id)

        self.assertRaises(
            ValueError, lambda: cohorts.get_cohort_id(
                user, SlashSeparatedCourseKey("course", "does_not", "exist")))
Beispiel #23
0
    def test_get_cohort_by_name(self):
        """
        Make sure cohorts.get_cohort_by_name() properly finds a cohort by name for a given course.  Also verify that it
        raises an error when the cohort is not found.
        """
        course = modulestore().get_course(self.toy_course_key)

        self.assertRaises(
            CourseUserGroup.DoesNotExist, lambda: cohorts.get_cohort_by_name(
                course.id, "CohortDoesNotExist"))

        cohort = CohortFactory(course_id=course.id, name="MyCohort")

        self.assertEqual(cohorts.get_cohort_by_name(course.id, "MyCohort"),
                         cohort)

        self.assertRaises(
            CourseUserGroup.DoesNotExist, lambda: cohorts.get_cohort_by_name(
                SlashSeparatedCourseKey("course", "does_not", "exist"), cohort)
        )
Beispiel #24
0
    def test_auto_cohorting(self):
        """
        Make sure cohorts.get_cohort() does the right thing with auto_cohort_groups
        """
        course = modulestore().get_course(self.toy_course_key)
        self.assertFalse(course.is_cohorted)

        user1 = UserFactory(username="******", email="*****@*****.**")
        user2 = UserFactory(username="******", email="*****@*****.**")
        user3 = UserFactory(username="******", email="*****@*****.**")
        user4 = UserFactory(username="******", email="*****@*****.**")

        cohort = CohortFactory(course_id=course.id, name="TestCohort")

        # user1 manually added to a cohort
        cohort.users.add(user1)

        # Add an auto_cohort_group to the course...
        config_course_cohorts(course,
                              discussions=[],
                              cohorted=True,
                              auto_cohort_groups=["AutoGroup"])

        self.assertEquals(
            cohorts.get_cohort(user1, course.id).id, cohort.id,
            "user1 should stay put")

        self.assertEquals(
            cohorts.get_cohort(user2, course.id).name, "AutoGroup",
            "user2 should be auto-cohorted")

        # Now make the auto_cohort_group list empty
        config_course_cohorts(course,
                              discussions=[],
                              cohorted=True,
                              auto_cohort_groups=[])

        self.assertEquals(
            cohorts.get_cohort(user3, course.id).id,
            cohorts.get_cohort_by_name(course.id,
                                       cohorts.DEFAULT_COHORT_NAME).id,
            "No groups->default cohort")

        # Now set the auto_cohort_group to something different
        config_course_cohorts(course,
                              discussions=[],
                              cohorted=True,
                              auto_cohort_groups=["OtherGroup"])

        self.assertEquals(
            cohorts.get_cohort(user4, course.id).name, "OtherGroup",
            "New list->new group")
        self.assertEquals(
            cohorts.get_cohort(user1, course.id).name, "TestCohort",
            "user1 should still be in originally placed cohort")
        self.assertEquals(
            cohorts.get_cohort(user2, course.id).name, "AutoGroup",
            "user2 should still be in originally placed cohort")
        self.assertEquals(
            cohorts.get_cohort(user3, course.id).name,
            cohorts.get_cohort_by_name(course.id,
                                       cohorts.DEFAULT_COHORT_NAME).name,
            "user3 should still be in the default cohort")