def tearDown(self):
     MockSender.clear_sent()
     messaging.ENABLED_IN_DEV_FOR_TESTING = False
     messaging.Sender = self.save_sender
     messaging.Message = self.save_message
     sites.reset_courses()
     super(UsageReportingTestBase, self).tearDown()
예제 #2
0
    def test_jobs_run(self):
        COURSE = 'test'
        app_context = actions.simple_add_course(COURSE, ADMIN_EMAIL, 'Test')
        actions.register(self, 'Joe Admin', COURSE)
        config.set_report_allowed(True)
        response = self.get(usage_reporting.StartReportingJobs.URL,
                            headers={'X-AppEngine-Cron': 'True'})
        self.assertEquals(200, response.status_int)
        self.assertEquals('OK.', response.body)
        now = int(time.time())
        self.execute_all_deferred_tasks(
            models.StudentLifecycleObserver.QUEUE_NAME)
        self.execute_all_deferred_tasks()

        expected = [{
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: FAKE_TIMESTAMP,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_STUDENT_COUNT,
            messaging.Message._VALUE: 1,
        }, {
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: now - (now % 3600),
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE: 1,
        }]
        actual = MockSender.get_sent()
        actual.sort(key=lambda x: x['timestamp'])
        self.assertEquals(expected, actual)
        sites.reset_courses()
예제 #3
0
 def tearDown(self):
     MockSender.clear_sent()
     messaging.ENABLED_IN_DEV_FOR_TESTING = False
     messaging.Sender = self.save_sender
     messaging.Message = self.save_message
     sites.reset_courses()
     super(UsageReportingTestBase, self).tearDown()
예제 #4
0
    def test_multiple_course(self):
        """Tests when multiple courses are available."""
        sites.setup_courses('course:/test::ns_test, course:/:/')
        name = 'Test completed course'
        email = 'Student'

        # Make the course available.
        get_environ_old = sites.ApplicationContext.get_environ

        def get_environ_new(self):
            environ = get_environ_old(self)
            environ['course']['now_available'] = True
            return environ

        sites.ApplicationContext.get_environ = get_environ_new

        actions.login(email)
        actions.register(self, name)
        response = self.get('/explorer/courses')
        # Assert if 'View course list' text is shown on my course page.
        actions.assert_contains('View course list', response.body)

        # Clean up app_context.
        sites.ApplicationContext.get_environ = get_environ_old
        sites.reset_courses()
예제 #5
0
 def tearDown(self):
     super(RolesTest, self).tearDown()
     sites.reset_courses()
     config.Registry.test_overrides.clear()
     # pylint: disable-msg=protected-access
     roles.Roles._REGISTERED_PERMISSIONS = self.old_registered_permission
     config.Registry.test_overrides[models.CAN_USE_MEMCACHE.name] = False
    def test_multiple_course(self):
        """Tests when multiple courses are available."""
        sites.setup_courses('course:/test::ns_test, course:/:/')
        name = 'Test completed course'
        email = 'Student'

        # Make the course available.
        get_environ_old = sites.ApplicationContext.get_environ

        def get_environ_new(self):
            environ = get_environ_old(self)
            environ['course']['now_available'] = True
            return environ

        sites.ApplicationContext.get_environ = get_environ_new

        actions.login(email)
        actions.register(self, name)
        response = self.get('/explorer/courses')
        # Assert if 'View course list' text is shown on my course page.
        actions.assert_contains('View course list', response.body)

        # Clean up app_context.
        sites.ApplicationContext.get_environ = get_environ_old
        sites.reset_courses()
예제 #7
0
 def tearDown(self):
     super(RolesTest, self).tearDown()
     sites.reset_courses()
     config.Registry.test_overrides.clear()
     # pylint: disable-msg=protected-access
     roles.Roles._REGISTERED_PERMISSIONS = self.old_registered_permission
     config.Registry.test_overrides[models.CAN_USE_MEMCACHE.name] = False
    def test_jobs_run(self):
        COURSE = 'test'
        app_context = actions.simple_add_course(COURSE, ADMIN_EMAIL, 'Test')
        actions.register(self, 'Joe Admin', COURSE)
        config.set_report_allowed(True)
        response = self.get(usage_reporting.StartReportingJobs.URL,
                            headers={'X-AppEngine-Cron': 'True'})
        self.assertEquals(200, response.status_int)
        self.assertEquals('OK.', response.body)
        now = int(time.time())
        self.execute_all_deferred_tasks(
            models.StudentLifecycleObserver.QUEUE_NAME)
        self.execute_all_deferred_tasks()

        expected = [{
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: FAKE_TIMESTAMP,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_STUDENT_COUNT,
            messaging.Message._VALUE: 1,
        }, {
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: now - (now % 3600),
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE: 1,
        }]
        actual = MockSender.get_sent()
        actual.sort(key=lambda x: x['timestamp'])
        self.assertEquals(expected, actual)
        sites.reset_courses()
예제 #9
0
    def test_end_to_end(self):
        """Actually enroll and unenroll students; verify reporting counts."""

        COURSE_NAME_BASE = 'test'
        NUM_COURSES = 2
        NUM_STUDENTS = 3
        THE_TIMESTAMP = 1427245200

        for course_num in range(NUM_COURSES):
            course_name = '%s_%d' % (COURSE_NAME_BASE, course_num)
            actions.simple_add_course(course_name, ADMIN_EMAIL, course_name)
            actions.update_course_config(course_name, {
                'course': {
                    'now_available': True,
                    'browsable': True,
                },
            })
            for student_num in range(NUM_STUDENTS):
                name = '%s_%d_%d' % (COURSE_NAME_BASE, course_num, student_num)
                actions.login(name + '@foo.com')
                actions.register(self, name, course_name)
                if student_num == 0:
                    actions.unregister(self, course_name)
                actions.logout()

        # Expect no messages yet; haven't run job.
        self.assertEquals([], MockSender.get_sent())

        # Run all counting jobs.
        usage_reporting.StartReportingJobs._submit_jobs()
        self.execute_all_deferred_tasks()

        # Verify counts.  (Ignore dates, these are fickle and subject to
        # weirdness on hour boundaries.  Also ignore course/instance IDs;
        # they are non-random and thus all the same.)
        num_enrolled_msgs = 0
        num_unenrolled_msgs = 0
        num_student_count_msgs = 0
        for message in MockSender.get_sent():
            if (message[messaging.Message._METRIC] ==
                    messaging.Message.METRIC_STUDENT_COUNT):
                num_student_count_msgs += 1
                self.assertEquals(NUM_STUDENTS,
                                  message[messaging.Message._VALUE])
            elif (message[messaging.Message._METRIC] ==
                  messaging.Message.METRIC_ENROLLED):
                num_enrolled_msgs += 1
                self.assertEquals(NUM_STUDENTS,
                                  message[messaging.Message._VALUE])
            elif (message[messaging.Message._METRIC] ==
                  messaging.Message.METRIC_UNENROLLED):
                num_unenrolled_msgs += 1
                self.assertEquals(1, message[messaging.Message._VALUE])

        self.assertEquals(NUM_COURSES, num_enrolled_msgs)
        self.assertEquals(NUM_COURSES, num_unenrolled_msgs)
        self.assertEquals(NUM_COURSES, num_student_count_msgs)
        sites.reset_courses()
예제 #10
0
 def tearDown(self):
     messaging.ENABLED_IN_DEV_FOR_TESTING = False
     messaging.Sender._report_settings_timestamp = 0
     urlfetch.fetch = self.save_urlfetch_fetch
     MessageCatcher.clear_sent()
     MessageCatcher.set_return_code(200)
     MessageCatcher.set_config(MessageCatcher.DEFAULT_CONFIG)
     sites.reset_courses()
     super(MessagingTests, self).tearDown()
 def tearDown(self):
     messaging.ENABLED_IN_DEV_FOR_TESTING = False
     messaging.Sender._report_settings_timestamp = 0
     urlfetch.fetch = self.save_urlfetch_fetch
     MessageCatcher.clear_sent()
     MessageCatcher.set_return_code(200)
     MessageCatcher.set_config(MessageCatcher.DEFAULT_CONFIG)
     sites.reset_courses()
     super(MessagingTests, self).tearDown()
 def tearDown(self):
     news.is_enabled = self.save_is_enabled
     del news.NewsItem.__eq__
     del news.NewsItem.__repr__
     del news.SeenItem.__eq__
     del news.SeenItem.__repr__
     news.I18nTitleRegistry.unregister('test')
     sites.reset_courses()
     namespace_manager.set_namespace(self.old_namespace)
     super(NewsTestBase, self).tearDown()
    def test_course_message_with_google_admin(self):
        actions.login('*****@*****.**')
        course_name = 'google_test_course'
        course_title = 'Google Test Course'
        course_namespace = 'ns_%s' % course_name
        course_slug = '/%s' % course_name

        def add_course_and_register_student(admin_email):
            google_app_context = actions.simple_add_course(
                course_name, admin_email, course_title)
            actions.update_course_config(course_name, {
                'course': {
                    'now_available': True,
                    'browsable': True,
                },
            })
            actions.register(self, 'John Smith', course_name)

            with actions.OverriddenConfig(config.REPORT_ALLOWED.name, True):
                usage_reporting.StartReportingJobs._for_testing_only_get()
            self.execute_all_deferred_tasks(
                models.StudentLifecycleObserver.QUEUE_NAME)
            self.execute_all_deferred_tasks()

        # With [email protected] - should get extra fields in reports.
        add_course_and_register_student('*****@*****.**')
        for message in MockSender.get_sent():
            self.assertEquals(message[messaging.Message._COURSE_TITLE],
                              course_title)
            self.assertEquals(message[messaging.Message._COURSE_SLUG],
                              course_slug)
            self.assertEquals(message[messaging.Message._COURSE_NAMESPACE],
                              course_namespace)
        MockSender.clear_sent()
        sites.reset_courses()

        # Without [email protected] - should not get extra fields in reports.
        add_course_and_register_student('*****@*****.**')
        for message in MockSender.get_sent():
            self.assertNotIn(messaging.Message._COURSE_TITLE, message)
            self.assertNotIn(messaging.Message._COURSE_SLUG, message)
            self.assertNotIn(messaging.Message._COURSE_NAMESPACE, message)
        MockSender.clear_sent()
        sites.reset_courses()
    def test_course_message_with_google_admin(self):
        actions.login('*****@*****.**')
        course_name = 'google_test_course'
        course_title = 'Google Test Course'
        course_namespace = 'ns_%s' % course_name
        course_slug = '/%s' % course_name

        def add_course_and_register_student(admin_email):
            google_app_context = actions.simple_add_course(
                course_name, admin_email, course_title)
            actions.update_course_config(
                course_name,
                {'course': {'now_available': True, 'browsable': True,},})
            actions.register(self, 'John Smith', course_name)

            with actions.OverriddenConfig(config.REPORT_ALLOWED.name, True):
                usage_reporting.StartReportingJobs._for_testing_only_get()
            self.execute_all_deferred_tasks(
                models.StudentLifecycleObserver.QUEUE_NAME)
            self.execute_all_deferred_tasks()

        # With [email protected] - should get extra fields in reports.
        add_course_and_register_student('*****@*****.**')
        for message in MockSender.get_sent():
            self.assertEquals(message[messaging.Message._COURSE_TITLE],
                              course_title)
            self.assertEquals(message[messaging.Message._COURSE_SLUG],
                              course_slug)
            self.assertEquals(message[messaging.Message._COURSE_NAMESPACE],
                              course_namespace)
        MockSender.clear_sent()
        sites.reset_courses()

        # Without [email protected] - should not get extra fields in reports.
        add_course_and_register_student('*****@*****.**')
        for message in MockSender.get_sent():
            self.assertNotIn(messaging.Message._COURSE_TITLE, message)
            self.assertNotIn(messaging.Message._COURSE_SLUG, message)
            self.assertNotIn(messaging.Message._COURSE_NAMESPACE, message)
        MockSender.clear_sent()
        sites.reset_courses()
예제 #15
0
 def tearDown(self):
     sites.reset_courses()
     super(UnitTests, self).tearDown()
예제 #16
0
    def test_enrollment_map_reduce_job(self):
        self.maxDiff = None
        MOCK_NOW = 1427247511
        COURSE = 'xyzzy'
        NAMESPACE = 'ns_xyzzy'
        MIN_TIMESTAMP = (MOCK_NOW - (MOCK_NOW % enrollment.SECONDS_PER_HOUR) -
                         enrollment.StudentEnrollmentEventCounter.MAX_AGE)

        # Insert some bogus StudentEnrollmentEventEntity for the M/R job
        # to count or delete.
        very_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        very_old_enroll.timestamp = 0
        very_old_enroll.metric = messaging.Message.METRIC_ENROLLED

        very_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        very_old_unenroll.timestamp = 0
        very_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        just_too_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        just_too_old_enroll.timestamp = MIN_TIMESTAMP - 1
        just_too_old_enroll.metric = messaging.Message.METRIC_ENROLLED

        just_too_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        just_too_old_unenroll.timestamp = MIN_TIMESTAMP - 1
        just_too_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        young_enough_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        young_enough_enroll.timestamp = MIN_TIMESTAMP
        young_enough_enroll.metric = messaging.Message.METRIC_ENROLLED

        young_enough_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        young_enough_unenroll.timestamp = MIN_TIMESTAMP
        young_enough_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        now_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        now_enroll.timestamp = MOCK_NOW
        now_enroll.metric = messaging.Message.METRIC_ENROLLED

        now_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        now_unenroll.timestamp = MOCK_NOW
        now_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        dtos = [
            very_old_enroll,
            very_old_unenroll,
            just_too_old_enroll,
            just_too_old_unenroll,
            young_enough_enroll,
            young_enough_unenroll,
            now_enroll,
            now_unenroll,
        ]

        app_context = actions.simple_add_course(COURSE, ADMIN_EMAIL, 'Test')
        with common_utils.Namespace(NAMESPACE):
            enrollment.StudentEnrollmentEventDAO.save_all(dtos)

        # Run map/reduce job with a setup function replaced so that it will
        # always choose the same timestamp as the start time.
        job_class = enrollment.StudentEnrollmentEventCounter
        save_b_a_m_p = job_class.build_additional_mapper_params
        try:

            def fixed_time_b_a_m_p(self, app_context):
                return {self.MIN_TIMESTAMP: MIN_TIMESTAMP}

            job_class.build_additional_mapper_params = fixed_time_b_a_m_p

            # Actually run the job.
            enrollment.StudentEnrollmentEventCounter(app_context).submit()
            self.execute_all_deferred_tasks()
        finally:
            job_class.build_additional_mapper_params = save_b_a_m_p

        # Verify that the DTOs older than the cutoff have been removed from
        # the datastore.
        with common_utils.Namespace(NAMESPACE):
            dtos = enrollment.StudentEnrollmentEventDAO.get_all()
            dtos.sort(key=lambda dto: (dto.timestamp, dto.metric))
            self.assertEqual([
                young_enough_enroll.dict, young_enough_unenroll.dict,
                now_enroll.dict, now_unenroll.dict
            ], [d.dict for d in dtos])

        # Verify that we have messages for the new-enough items, and no
        # messages for the older items.
        messages = MockSender.get_sent()
        messages.sort(key=lambda m: (m['timestamp'], m['metric']))

        MOCK_NOW_HOUR = MOCK_NOW - (MOCK_NOW % enrollment.SECONDS_PER_HOUR)
        expected = [{
            messaging.Message._INSTALLATION:
            FAKE_INSTALLATION_ID,
            messaging.Message._COURSE:
            FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP:
            MIN_TIMESTAMP,
            messaging.Message._VERSION:
            os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC:
            messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE:
            1,
        }, {
            messaging.Message._INSTALLATION:
            FAKE_INSTALLATION_ID,
            messaging.Message._COURSE:
            FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP:
            MIN_TIMESTAMP,
            messaging.Message._VERSION:
            os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC:
            messaging.Message.METRIC_UNENROLLED,
            messaging.Message._VALUE:
            1,
        }, {
            messaging.Message._INSTALLATION:
            FAKE_INSTALLATION_ID,
            messaging.Message._COURSE:
            FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP:
            MOCK_NOW_HOUR,
            messaging.Message._VERSION:
            os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC:
            messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE:
            1,
        }, {
            messaging.Message._INSTALLATION:
            FAKE_INSTALLATION_ID,
            messaging.Message._COURSE:
            FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP:
            MOCK_NOW_HOUR,
            messaging.Message._VERSION:
            os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC:
            messaging.Message.METRIC_UNENROLLED,
            messaging.Message._VALUE:
            1,
        }]
        self.assertEquals(expected, messages)
        sites.reset_courses()
 def tearDown(self):
     namespace_manager.set_namespace(self.old_namespace)
     sites.reset_courses()
     super(AnnouncementsTests, self).tearDown()
예제 #18
0
 def tearDown(self):
     sites.reset_courses()
     etl._LOG.handlers = self.old_log_handlers
     super(EtlTestBase, self).tearDown()
예제 #19
0
 def tearDown(self):
     sites.reset_courses()
     etl._LOG.handlers = self.old_log_handlers
     super(EtlTestBase, self).tearDown()
    def test_end_to_end(self):
        """Actually enroll and unenroll students; verify reporting counts."""

        COURSE_NAME_BASE = 'test'
        NUM_COURSES = 2
        NUM_STUDENTS = 3
        THE_TIMESTAMP = 1427245200

        for course_num in range(NUM_COURSES):
            course_name = '%s_%d' % (COURSE_NAME_BASE, course_num)
            actions.simple_add_course(course_name, ADMIN_EMAIL, course_name)
            actions.update_course_config(
                course_name,
                {
                    'course': {
                        'now_available': True,
                        'browsable': True,
                    },
                })
            for student_num in range(NUM_STUDENTS):
                name = '%s_%d_%d' % (COURSE_NAME_BASE, course_num, student_num)
                actions.login(name + '@foo.com')
                actions.register(self, name, course_name)
                if student_num == 0:
                    actions.unregister(self, course_name)
                actions.logout()

        # Expect no messages yet; haven't run job.
        self.assertEquals([], MockSender.get_sent())

        # Run all counting jobs.
        with actions.OverriddenConfig(config.REPORT_ALLOWED.name, True):
            usage_reporting.StartReportingJobs._for_testing_only_get()
        self.execute_all_deferred_tasks(
            models.StudentLifecycleObserver.QUEUE_NAME)
        self.execute_all_deferred_tasks()

        # Verify counts.  (Ignore dates, these are fickle and subject to
        # weirdness on hour boundaries.  Also ignore course/instance IDs;
        # they are non-random and thus all the same.)
        num_enrolled_msgs = 0
        num_unenrolled_msgs = 0
        num_student_count_msgs = 0
        for message in MockSender.get_sent():
            if (message[messaging.Message._METRIC] ==
                messaging.Message.METRIC_STUDENT_COUNT):
                num_student_count_msgs += 1
                self.assertEquals(
                    NUM_STUDENTS, message[messaging.Message._VALUE])
            elif (message[messaging.Message._METRIC] ==
                  messaging.Message.METRIC_ENROLLED):
                num_enrolled_msgs += 1
                self.assertEquals(
                    NUM_STUDENTS, message[messaging.Message._VALUE])
            elif (message[messaging.Message._METRIC] ==
                  messaging.Message.METRIC_UNENROLLED):
                num_unenrolled_msgs += 1
                self.assertEquals(
                    1, message[messaging.Message._VALUE])

        self.assertEquals(NUM_COURSES, num_enrolled_msgs)
        self.assertEquals(NUM_COURSES, num_unenrolled_msgs)
        self.assertEquals(NUM_COURSES, num_student_count_msgs)
        sites.reset_courses()
예제 #21
0
 def tearDown(self):
     sites.reset_courses()
     super(EtlTestBase, self).tearDown()
예제 #22
0
 def tearDown(self):
     del admin.BaseAdminHandler.ADDITIONAL_COLUMN_HOOKS[
         self.__class__.__name__]
     del config.Registry.test_overrides[sites.GCB_COURSES_CONFIG.name]
     sites.reset_courses()
     super(AdminCourseListTests, self).tearDown()
 def tearDown(self):
     namespace_manager.set_namespace(self.old_namespace)
     sites.reset_courses()
     super(AnnouncementsTests, self).tearDown()
    def test_enrollment_map_reduce_job(self):
        self.maxDiff = None
        MOCK_NOW = 1427247511
        COURSE = 'xyzzy'
        NAMESPACE = 'ns_xyzzy'
        MIN_TIMESTAMP = (
            MOCK_NOW
            - (MOCK_NOW % enrollment.SECONDS_PER_HOUR)
            - enrollment.StudentEnrollmentEventCounter.MAX_AGE)

        # Insert some bogus StudentEnrollmentEventEntity for the M/R job
        # to count or delete.
        very_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        very_old_enroll.timestamp = 0
        very_old_enroll.metric = messaging.Message.METRIC_ENROLLED

        very_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        very_old_unenroll.timestamp = 0
        very_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        just_too_old_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        just_too_old_enroll.timestamp = MIN_TIMESTAMP - 1
        just_too_old_enroll.metric = messaging.Message.METRIC_ENROLLED

        just_too_old_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        just_too_old_unenroll.timestamp = MIN_TIMESTAMP - 1
        just_too_old_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        young_enough_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        young_enough_enroll.timestamp = MIN_TIMESTAMP
        young_enough_enroll.metric = messaging.Message.METRIC_ENROLLED

        young_enough_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        young_enough_unenroll.timestamp = MIN_TIMESTAMP
        young_enough_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        now_enroll = enrollment.StudentEnrollmentEventDTO(None, {})
        now_enroll.timestamp = MOCK_NOW
        now_enroll.metric = messaging.Message.METRIC_ENROLLED

        now_unenroll = enrollment.StudentEnrollmentEventDTO(None, {})
        now_unenroll.timestamp = MOCK_NOW
        now_unenroll.metric = messaging.Message.METRIC_UNENROLLED

        dtos = [
            very_old_enroll,
            very_old_unenroll,
            just_too_old_enroll,
            just_too_old_unenroll,
            young_enough_enroll,
            young_enough_unenroll,
            now_enroll,
            now_unenroll,
        ]

        app_context = actions.simple_add_course(COURSE, ADMIN_EMAIL, 'Test')
        with common_utils.Namespace(NAMESPACE):
            enrollment.StudentEnrollmentEventDAO.save_all(dtos)

        # Run map/reduce job with a setup function replaced so that it will
        # always choose the same timestamp as the start time.
        job_class = enrollment.StudentEnrollmentEventCounter
        save_b_a_m_p = job_class.build_additional_mapper_params
        try:
            def fixed_time_b_a_m_p(self, app_context):
                return {self.MIN_TIMESTAMP: MIN_TIMESTAMP}
            job_class.build_additional_mapper_params = fixed_time_b_a_m_p

            # Actually run the job.
            enrollment.StudentEnrollmentEventCounter(app_context).submit()
            self.execute_all_deferred_tasks(
                models.StudentLifecycleObserver.QUEUE_NAME)
            self.execute_all_deferred_tasks()
        finally:
            job_class.build_additional_mapper_params = save_b_a_m_p

        # Verify that the DTOs older than the cutoff have been removed from
        # the datastore.
        with common_utils.Namespace(NAMESPACE):
            dtos = enrollment.StudentEnrollmentEventDAO.get_all()
            dtos.sort(key=lambda dto: (dto.timestamp, dto.metric))
            self.assertEqual(
                [young_enough_enroll.dict,
                 young_enough_unenroll.dict,
                 now_enroll.dict,
                 now_unenroll.dict],
                [d.dict for d in dtos])

        # Verify that we have messages for the new-enough items, and no
        # messages for the older items.
        messages = MockSender.get_sent()
        messages.sort(key=lambda m: (m['timestamp'], m['metric']))

        MOCK_NOW_HOUR = MOCK_NOW - (MOCK_NOW % enrollment.SECONDS_PER_HOUR)
        expected = [{
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: MIN_TIMESTAMP,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE: 1,
        }, {
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: MIN_TIMESTAMP,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_UNENROLLED,
            messaging.Message._VALUE: 1,
        }, {
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: MOCK_NOW_HOUR,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_ENROLLED,
            messaging.Message._VALUE: 1,
        }, {
            messaging.Message._INSTALLATION: FAKE_INSTALLATION_ID,
            messaging.Message._COURSE: FAKE_COURSE_ID,
            messaging.Message._TIMESTAMP: MOCK_NOW_HOUR,
            messaging.Message._VERSION: os.environ['GCB_PRODUCT_VERSION'],
            messaging.Message._METRIC: messaging.Message.METRIC_UNENROLLED,
            messaging.Message._VALUE: 1,
        }]
        self.assertEquals(expected, messages)
        sites.reset_courses()
예제 #25
0
 def tearDown(self):
     sites.reset_courses()
     super(LessonTests, self).tearDown()
예제 #26
0
 def tearDown(self):
     sites.reset_courses()
     super(TextFileUploadTagTestCase, self).tearDown()
예제 #27
0
 def tearDown(self):
     sites.reset_courses()
     super(UnitTests, self).tearDown()
예제 #28
0
 def tearDown(self):
     sites.reset_courses()
     super(TextFileUploadTagTestCase, self).tearDown()
예제 #29
0
 def tearDown(self):
     del admin.BaseAdminHandler.ADDITIONAL_COLUMN_HOOKS[
         self.__class__.__name__]
     del config.Registry.test_overrides[sites.GCB_COURSES_CONFIG.name]
     sites.reset_courses()
     super(AdminCourseListTests, self).tearDown()
예제 #30
0
 def tearDown(self):
     super(StudentTracksTest, self).tearDown()
     sites.reset_courses()
예제 #31
0
 def tearDown(self):
     sites.reset_courses()
     super(MapReduceMethodTypeTests, self).tearDown()
예제 #32
0
 def tearDown(self):
     sites.reset_courses()
     super(LessonTests, self).tearDown()
예제 #33
0
 def tearDown(self):
     super(WhitelistTest, self).tearDown()
     sites.reset_courses()
     WhitelistTest._whitelist = ''
     config.Registry.test_overrides.clear()
예제 #34
0
 def tearDown(self):
     super(WhitelistTest, self).tearDown()
     sites.reset_courses()
     WhitelistTest._whitelist = ''
     config.Registry.test_overrides.clear()
예제 #35
0
 def tearDown(self):
     super(StudentTracksTest, self).tearDown()
     sites.reset_courses()