def test_auto_cohorts(self): """ Verify that auto cohorts are included in the response. """ config_course_cohorts(self.course, [], cohorted=True, auto_cohort_groups=["AutoGroup1", "AutoGroup2"]) # Will create cohort1, cohort2, and cohort3. Auto cohorts remain uncreated. self._create_cohorts() # Get the cohorts from the course, which will cause auto cohorts to be created. actual_cohorts = self.request_list_cohorts(self.course) # Get references to the created auto cohorts. auto_cohort_1 = get_cohort_by_name(self.course.id, "AutoGroup1") auto_cohort_2 = get_cohort_by_name(self.course.id, "AutoGroup2") expected_cohorts = [ ListCohortsTestCase.create_expected_cohort( self.cohort1, 3, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort( self.cohort2, 2, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort( self.cohort3, 2, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort( auto_cohort_1, 0, CohortAssignmentType.RANDOM), ListCohortsTestCase.create_expected_cohort( auto_cohort_2, 0, CohortAssignmentType.RANDOM), ] self.verify_lists_expected_cohorts(expected_cohorts, actual_cohorts)
def users(self, request, pk): """ Add a User to a Workgroup """ if request.method == 'GET': users = User.objects.filter(workgroups=pk) response_data = [] if users: for user in users: serializer = UserSerializer(user) response_data.append(serializer.data) # pylint: disable=E1101 return Response(response_data, status=status.HTTP_200_OK) elif request.method == 'POST': user_id = request.DATA.get('id') try: user = User.objects.get(id=user_id) except ObjectDoesNotExist: message = 'User {} does not exist'.format(user_id) return Response({"detail": message}, status.HTTP_400_BAD_REQUEST) workgroup = self.get_object() workgroup.users.add(user) workgroup.save() # add user to the workgroup cohort, create it if it doesn't exist (for cases where there is a legacy # workgroup) course_descriptor, course_key, course_content = _get_course(self.request, user, workgroup.project.course_id) # pylint: disable=W0612 try: cohort = get_cohort_by_name(course_key, workgroup.cohort_name, CourseUserGroup.WORKGROUP) add_user_to_cohort(cohort, user.username) except ObjectDoesNotExist: # This use case handles cases where a workgroup might have been created before # the notion of a cohorted discussion. So we need to backfill in the data cohort = add_cohort(course_key, workgroup.cohort_name, CourseUserGroup.WORKGROUP) for workgroup_user in workgroup.users.all(): add_user_to_cohort(cohort, workgroup_user.username) return Response({}, status=status.HTTP_201_CREATED) else: user_id = request.DATA.get('id') try: user = User.objects.get(id=user_id) except ObjectDoesNotExist: message = 'User {} does not exist'.format(user_id) return Response({"detail": message}, status.HTTP_400_BAD_REQUEST) workgroup = self.get_object() course_descriptor, course_key, course_content = _get_course(self.request, user, workgroup.project.course_id) # pylint: disable=W0612 cohort = get_cohort_by_name(course_key, workgroup.cohort_name, CourseUserGroup.WORKGROUP) workgroup.users.remove(user) remove_user_from_cohort(cohort, user.username, CourseUserGroup.WORKGROUP) return Response({}, status=status.HTTP_204_NO_CONTENT)
def test_workgroups_users_post_with_cohort_backfill(self): """ This test asserts a case where a workgroup was created before the existence of a cohorted discussion """ data = { 'name': self.test_workgroup_name, 'project': self.test_project.id } response = self.do_post(self.test_workgroups_uri, data) self.assertEqual(response.status_code, 201) test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id'])) users_uri = '{}users/'.format(test_uri) data = {"id": self.test_user.id} response = self.do_post(users_uri, data) self.assertEqual(response.status_code, 201) response = self.do_get(test_uri) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['users'][0]['id'], self.test_user.id) cohort_name = Workgroup.cohort_name_for_workgroup( self.test_project.id, response.data['id'], self.test_workgroup_name ) # now let's remove existing cohort users cohort = get_cohort_by_name(self.test_course.id, cohort_name, CourseUserGroup.WORKGROUP) self.assertTrue(is_user_in_cohort(cohort, self.test_user.id, CourseUserGroup.WORKGROUP)) remove_user_from_cohort(cohort, self.test_user.username, CourseUserGroup.WORKGROUP) self.assertFalse(is_user_in_cohort(cohort, self.test_user.id, CourseUserGroup.WORKGROUP)) # delete cohort delete_empty_cohort(self.test_course.id, cohort_name, CourseUserGroup.WORKGROUP) self.assertEqual(0, len(get_course_cohort_names(self.test_course.id, CourseUserGroup.WORKGROUP))) # add a 2nd user and make sure a discussion cohort was created and users were backfilled test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id'])) users_uri = '{}users/'.format(test_uri) data = {"id": self.test_user2.id} response = self.do_post(users_uri, data) self.assertEqual(response.status_code, 201) # now inspect cohort and assert that things are as we anticipate (i.e. both users are in there) cohort = get_cohort_by_name(self.test_course.id, cohort_name, CourseUserGroup.WORKGROUP) self.assertIsNotNone(cohort) self.assertTrue(is_user_in_cohort(cohort, self.test_user.id, CourseUserGroup.WORKGROUP)) self.assertTrue(is_user_in_cohort(cohort, self.test_user2.id, CourseUserGroup.WORKGROUP))
def test_default_cohort(self): """ Verify that the default cohort is not created and included in the response until students are assigned to it. """ # verify the default cohort is not created when the course is not cohorted self.verify_lists_expected_cohorts([]) # create a cohorted course without any auto_cohort_groups config_course_cohorts(self.course, [], cohorted=True) # verify the default cohort is not yet created until a user is assigned self.verify_lists_expected_cohorts([]) # create enrolled users users = [UserFactory() for _ in range(3)] self._enroll_users(users, self.course.id) # mimic users accessing the discussion forum for user in users: get_cohort(user, self.course.id) # verify the default cohort is automatically created default_cohort = get_cohort_by_name(self.course.id, DEFAULT_COHORT_NAME) actual_cohorts = self.request_list_cohorts(self.course) self.verify_lists_expected_cohorts( [ ListCohortsTestCase.create_expected_cohort( default_cohort, len(users), CohortAssignmentType.RANDOM) ], actual_cohorts, ) # set auto_cohort_groups and verify the default cohort is no longer listed as RANDOM config_course_cohorts(self.course, [], cohorted=True, auto_cohort_groups=["AutoGroup"]) actual_cohorts = self.request_list_cohorts(self.course) auto_cohort = get_cohort_by_name(self.course.id, "AutoGroup") self.verify_lists_expected_cohorts( [ ListCohortsTestCase.create_expected_cohort( default_cohort, len(users), CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort( auto_cohort, 0, CohortAssignmentType.RANDOM), ], actual_cohorts, )
def test_workgroups_list_post(self): data = { 'name': self.test_workgroup_name, 'project': self.test_project.id } response = self.do_post(self.test_workgroups_uri, data) self.assertEqual(response.status_code, 201) self.assertGreater(response.data['id'], 0) confirm_uri = '{}{}{}/'.format( self.test_server_prefix, self.test_workgroups_uri, str(response.data['id']) ) self.assertEqual(response.data['url'], confirm_uri) self.assertGreater(response.data['id'], 0) self.assertEqual(response.data['name'], self.test_workgroup_name) self.assertEqual(response.data['project'], self.test_project.id) self.assertIsNotNone(response.data['users']) self.assertIsNotNone(response.data['groups']) self.assertIsNotNone(response.data['submissions']) self.assertIsNotNone(response.data['workgroup_reviews']) self.assertIsNotNone(response.data['peer_reviews']) self.assertIsNotNone(response.data['created']) self.assertIsNotNone(response.data['modified']) # make sure a discussion cohort was created cohort_name = Workgroup.cohort_name_for_workgroup( self.test_project.id, response.data['id'], self.test_workgroup_name ) cohort = get_cohort_by_name(self.test_course.id, cohort_name, CourseUserGroup.WORKGROUP) self.assertIsNotNone(cohort)
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" )
def test_auto_cohorting_randomization(self): """ Make sure get_cohort() randomizes properly. """ course = modulestore().get_course(self.toy_course_key) self.assertFalse(course.is_cohorted) groups = ["group_{0}".format(n) for n in range(5)] self.config_course_cohorts(course, [], cohorted=True, auto_cohort=True, auto_cohort_groups=groups) # Assign 100 users to cohorts for i in range(100): user = User.objects.create(username="******".format(i), email="a@b{0}.com".format(i)) get_cohort(user, course.id) # Now make sure that the assignment was at least vaguely random: # each cohort should have at least 1, and fewer than 50 students. # (with 5 groups, probability of 0 users in any group is about # .8**100= 2.0e-10) for cohort_name in groups: cohort = get_cohort_by_name(course.id, cohort_name) num_users = cohort.users.count() self.assertGreater(num_users, 1) self.assertLess(num_users, 50)
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")
def test_workgroups_users_post(self): data = { 'name': self.test_workgroup_name, 'project': self.test_project.id } response = self.do_post(self.test_workgroups_uri, data) self.assertEqual(response.status_code, 201) test_uri = '{}{}/'.format(self.test_workgroups_uri, str(response.data['id'])) users_uri = '{}users/'.format(test_uri) data = {"id": self.test_user.id} response = self.do_post(users_uri, data) self.assertEqual(response.status_code, 201) response = self.do_get(test_uri) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['users'][0]['id'], self.test_user.id) # make sure a discussion cohort was created cohort_name = Workgroup.cohort_name_for_workgroup( self.test_project.id, response.data['id'], self.test_workgroup_name ) cohort = get_cohort_by_name(self.test_course.id, cohort_name, CourseUserGroup.WORKGROUP) self.assertIsNotNone(cohort) self.assertTrue(is_user_in_cohort(cohort, self.test_user.id, CourseUserGroup.WORKGROUP))
def test_auto_cohorting_randomization(self): """ Make sure get_cohort() randomizes properly. """ course = modulestore().get_course("edX/toy/2012_Fall") self.assertEqual(course.id, "edX/toy/2012_Fall") self.assertFalse(course.is_cohorted) groups = ["group_{0}".format(n) for n in range(5)] self.config_course_cohorts(course, [], cohorted=True, auto_cohort=True, auto_cohort_groups=groups) # Assign 100 users to cohorts for i in range(100): user = User.objects.create(username="******".format(i), email="a@b{0}.com".format(i)) get_cohort(user, course.id) # Now make sure that the assignment was at least vaguely random: # each cohort should have at least 1, and fewer than 50 students. # (with 5 groups, probability of 0 users in any group is about # .8**100= 2.0e-10) for cohort_name in groups: cohort = get_cohort_by_name(course.id, cohort_name) num_users = cohort.users.count() self.assertGreater(num_users, 1) self.assertLess(num_users, 50)
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) )
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) )
def test_default_cohort(self): """ Verify that the default cohort is not created and included in the response until students are assigned to it. """ # verify the default cohort is not created when the course is not cohorted self.verify_lists_expected_cohorts([]) # create a cohorted course without any auto_cohort_groups config_course_cohorts(self.course, [], cohorted=True) # verify the default cohort is not yet created until a user is assigned self.verify_lists_expected_cohorts([]) # create enrolled users users = [UserFactory() for _ in range(3)] self._enroll_users(users, self.course.id) # mimic users accessing the discussion forum for user in users: get_cohort(user, self.course.id) # verify the default cohort is automatically created default_cohort = get_cohort_by_name(self.course.id, DEFAULT_COHORT_NAME) actual_cohorts = self.request_list_cohorts(self.course) self.verify_lists_expected_cohorts( [ListCohortsTestCase.create_expected_cohort(default_cohort, len(users), CohortAssignmentType.RANDOM)], actual_cohorts, ) # set auto_cohort_groups and verify the default cohort is no longer listed as RANDOM config_course_cohorts(self.course, [], cohorted=True, auto_cohort_groups=["AutoGroup"]) actual_cohorts = self.request_list_cohorts(self.course) auto_cohort = get_cohort_by_name(self.course.id, "AutoGroup") self.verify_lists_expected_cohorts( [ ListCohortsTestCase.create_expected_cohort(default_cohort, len(users), CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort(auto_cohort, 0, CohortAssignmentType.RANDOM), ], actual_cohorts, )
def test_auto_cohorts(self): """ Verify that auto cohorts are included in the response. """ config_course_cohorts(self.course, [], cohorted=True, auto_cohort_groups=["AutoGroup1", "AutoGroup2"]) # Will create cohort1, cohort2, and cohort3. Auto cohorts remain uncreated. self._create_cohorts() # Get the cohorts from the course, which will cause auto cohorts to be created. actual_cohorts = self.request_list_cohorts(self.course) # Get references to the created auto cohorts. auto_cohort_1 = get_cohort_by_name(self.course.id, "AutoGroup1") auto_cohort_2 = get_cohort_by_name(self.course.id, "AutoGroup2") expected_cohorts = [ ListCohortsTestCase.create_expected_cohort(self.cohort1, 3, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort(self.cohort2, 2, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort(self.cohort3, 2, CohortAssignmentType.NONE), ListCohortsTestCase.create_expected_cohort(auto_cohort_1, 0, CohortAssignmentType.RANDOM), ListCohortsTestCase.create_expected_cohort(auto_cohort_2, 0, CohortAssignmentType.RANDOM), ] self.verify_lists_expected_cohorts(expected_cohorts, actual_cohorts)
def verify_contains_added_cohort(self, response_dict, cohort_name, expected_error_msg=None): """ Check that `add_cohort`'s response correctly returns the newly added cohort (or error) in the response. Also verify that the cohort was actually created/exists. """ if expected_error_msg is not None: self.assertFalse(response_dict.get("success")) self.assertEqual(response_dict.get("msg"), expected_error_msg) else: self.assertTrue(response_dict.get("success")) self.assertEqual( response_dict.get("cohort").get("name"), cohort_name) self.assertIsNotNone(get_cohort_by_name(self.course.id, cohort_name))
def verify_contains_added_cohort(self, response_dict, cohort_name, expected_error_msg=None): """ Check that `add_cohort`'s response correctly returns the newly added cohort (or error) in the response. Also verify that the cohort was actually created/exists. """ if expected_error_msg is not None: self.assertFalse(response_dict.get("success")) self.assertEqual( response_dict.get("msg"), expected_error_msg ) else: self.assertTrue(response_dict.get("success")) self.assertEqual( response_dict.get("cohort").get("name"), cohort_name ) self.assertIsNotNone(get_cohort_by_name(self.course.id, cohort_name))
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")
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" )