def test_students_one_page(self):
        course_offering = CourseOfferingFactory(start_date=self.course_offering.start_date, no_weeks=2)
        course_offering.owners.add(self.user)
        self.api_url = reverse('olap:communication_students', kwargs={'course_id': course_offering.id})
        # Two pages, two users
        page1 = PageFactory(course_offering=course_offering, content_type='resource/x-bb-discussionboard')
        page2 = PageFactory(course_offering=course_offering, content_type='resource/x-bb-discussionboard')
        lms_user1 = LMSUserFactory(course_offering=course_offering)
        lms_user2 = LMSUserFactory(course_offering=course_offering)

        # 2 pages and 2 weeks gives a 2x2 grid.
        # Top left: 1xU1, 2xU2
        visit_dt = self.course_offering.start_datetime + datetime.timedelta(days=3)
        visit = PageVisitFactory(page=page1, lms_user=lms_user1, visited_at=visit_dt)
        visit = PageVisitFactory(page=page1, lms_user=lms_user2, visited_at=visit_dt)
        visit = PageVisitFactory(page=page2, lms_user=lms_user2, visited_at=visit_dt)
        # Top right: 1xU1
        visit_dt = self.course_offering.start_datetime + datetime.timedelta(days=10)
        visit = PageVisitFactory(page=page1, lms_user=lms_user1, visited_at=visit_dt)
        # Bottom left: 1xU2
        visit_dt = self.course_offering.start_datetime + datetime.timedelta(days=5)
        visit = PageVisitFactory(page=page2, lms_user=lms_user2, visited_at=visit_dt)
        # Nothing in bottom right

        # Call the API endpoint
        response = self.client.get(self.api_url)
        self.assertEqual(response.status_code, HTTP_200_OK)
        expected = {
            'pageSet': [
                {
                    'id': page1.id,
                    'title': page1.title,
                    'content_type': page1.content_type,
                    'weeks': [2, 1],
                    'total': 2,
                    'percent': 100.0, # 100% of users interacted with this page
               },
                {
                    'id': page2.id,
                    'title': page2.title,
                    'content_type': page2.content_type,
                    'weeks': [1, 0],
                    'total': 1,
                    'percent': 50.0, # 50% of users (u2) interacted with this page
                },
            ],
            'totalsByWeek': [
                2, # 2 users (u1, u2) viewed the two pages in week 1
                1, # 1 users viewed the two pages in week 2
                2,
            ],
        }
        response_dict = json.loads(response.content.decode('utf-8'))
        self.assertEqual(response_dict, expected)
Exemple #2
0
    def test_only_include_pages_for_a_given_user(self):
        # Have four pages split across two users.  Make sure the calculated sessions for both users are correct,
        # especially the aspect that visits due to one user are ignored when calculating the session for another user.

        u1 = LMSUserFactory(course_offering=self.offering)
        u1_p1 = PageFactory()
        u1_p2 = PageFactory()

        u2 = LMSUserFactory(course_offering=self.offering)
        u2_p1 = PageFactory()
        u2_p2 = PageFactory()

        orphan = PageFactory()

        # Visits for u1 which should result in a session starting at test_start_dt, lasting 25 mins
        u1_expected_session_start_dt = self.test_start_datetime
        v_u1_p1 = PageVisitFactory(lms_user=u1,
                                   page=u1_p1,
                                   visited_at=u1_expected_session_start_dt)
        v_u1_p2 = PageVisitFactory(lms_user=u1,
                                   page=u1_p2,
                                   visited_at=u1_expected_session_start_dt +
                                   datetime.timedelta(minutes=25))
        # Visits for u2 which should result in a session starting at test_start_dt+10mins, and lasting 21 mins
        u2_expected_session_start_dt = self.test_start_datetime + datetime.timedelta(
            minutes=10)
        v_u2_p1 = PageVisitFactory(lms_user=u2,
                                   page=u2_p1,
                                   visited_at=u2_expected_session_start_dt)
        v_u2_p2 = PageVisitFactory(lms_user=u2,
                                   page=u2_p2,
                                   visited_at=u2_expected_session_start_dt +
                                   datetime.timedelta(minutes=21))

        importer = ImportLmsData(self.offering, 'ignore.txt')
        importer._calculate_sessions()

        sessions = LMSSession.objects.all()
        session_info_extractor = lambda s: (
            s.first_visit.lms_user, s.first_visit.visited_at, s.
            session_length_in_mins, s.pageviews)
        extracted_session_info = tuple(
            session_info_extractor(session) for session in sessions)

        expected_session_info = (
            (u1, u1_expected_session_start_dt, 25, 2),
            (u2, u2_expected_session_start_dt, 21, 2),
        )

        self.assertEqual(expected_session_info, extracted_session_info)
    def test_accesses_one_page(self):
        self.api_url = reverse('olap:communication_accesses', kwargs={'course_id': self.course_offering.id})
        page = PageFactory(course_offering=self.course_offering, content_type='course/x-bb-collabsession')
        # For this one page, generate one visit per week for the duration of the course
        for week_no in range(self.course_offering.no_weeks):
            week_start_dt = self.course_offering.start_datetime + datetime.timedelta(weeks=week_no)
            week_end_dt = week_start_dt + datetime.timedelta(days=7)
            visit_dt = fuzzy.FuzzyDateTime(week_start_dt, week_end_dt)
            visit = PageVisitFactory(page=page, module='course/x-bb-collabsession', lms_user=self.lms_user, visited_at=visit_dt)

        # Call the API endpoint
        response = self.client.get(self.api_url)
        self.assertEqual(response.status_code, HTTP_200_OK)
        totals = [1] * self.course_offering.no_weeks # One visit per week
        totals.append(self.course_offering.no_weeks) # Add a final number for the total visits
        expected = {
            'pageSet': [
                {
                    # These keys aren't getting camel cased.  No idea why.
                    'id': page.id,
                    'title': page.title,
                    'content_type': page.content_type,
                    'weeks': [1] * self.course_offering.no_weeks, # One visit per week
                    'total': self.course_offering.no_weeks, # One visit per week
                    'percent': 100.0,
               },
            ],
            'totalsByWeek': totals,
        }
        response_dict = json.loads(response.content.decode('utf-8'))
        self.assertEqual(response_dict, expected)
Exemple #4
0
    def test_multiusers_same_pages(self):
        # Have two users accessing almost the same pages.  Make sure the sessions calculated for both users include
        #  the common pages, and the distinct ones.

        u1 = LMSUserFactory(course_offering=self.offering)
        u2 = LMSUserFactory(course_offering=self.offering)

        pre_page = PageFactory()
        common_visit_pages = PageFactory.create_batch(3)
        post_page = PageFactory()

        user_visit_info = {
            u1.pk: ((-2, pre_page), (0, common_visit_pages[0]),
                    (15, common_visit_pages[1]), (30, common_visit_pages[2]),
                    (39, post_page)),
            u2.pk: (
                (-1, pre_page),
                (5, common_visit_pages[0]),
                (25, common_visit_pages[1]),
                (45, common_visit_pages[2]),
                (89, post_page),
            )
        }

        for user_pk, visit_list in user_visit_info.items():
            user = LMSUser.objects.get(pk=user_pk)
            for visit_offset_mins, page in visit_list:
                visit_obj = PageVisitFactory(
                    lms_user=user,
                    page=page,
                    visited_at=self.test_start_datetime +
                    datetime.timedelta(minutes=visit_offset_mins))

        importer = ImportLmsData(self.offering, 'ignore.txt')
        importer._calculate_sessions()

        sessions = LMSSession.objects.all()
        session_info_extractor = lambda s: (
            s.first_visit.lms_user, s.first_visit.visited_at, s.
            session_length_in_mins, s.pageviews)
        extracted_session_info = tuple(
            session_info_extractor(session) for session in sessions)

        expected_session_info = (
            (u1, self.test_start_datetime + datetime.timedelta(minutes=-2), 41,
             5),
            (u2, self.test_start_datetime + datetime.timedelta(minutes=-1), 46,
             4),
            (u2, self.test_start_datetime + datetime.timedelta(minutes=89), 0,
             1),
        )

        self.assertEqual(expected_session_info, extracted_session_info)
    def events_setUp(self):
        self.course_offering_start = datetime.datetime(2016, 2, 1, 8, 0, 10, tzinfo=self.our_tz) # Mon
        assert self.course_offering_start.weekday() == 0 # Date chosen to be a monday.  Test won't work otherwise.

        course_offering = CourseOfferingFactory(start_date=self.course_offering_start, no_weeks=2)
        course_offering.owners.add(self.user)
        self.page = PageFactory(course_offering=course_offering, content_type='resource/x-bb-discussionboard')

        visit_dt = self.course_offering_start + datetime.timedelta(days=3) # Thu
        visit = PageVisitFactory(page=self.page, lms_user=self.lms_user, visited_at=visit_dt)

        # Default to Monday, but each test will change this to each side of the page visit
        self.repeating_event = CourseRepeatingEventFactory(course_offering=course_offering, start_week=1, end_week=2, day_of_week=0)

        self.api_url = reverse('olap:communication_events', kwargs={'course_id': course_offering.id, 'event_id': self.repeating_event.id})
    def test_accesses_shedload_of_pages(self):
        self.api_url = reverse('olap:communication_accesses', kwargs={'course_id': self.course_offering.id})
        NR_PAGES = 5
        NR_PAGEVISITS = 100
        all_pages = PageFactory.create_batch(NR_PAGES, course_offering=self.course_offering, content_type='course/x-bb-collabsession')
        # Pick a random page, and create a visit to that page.
        for visit in range(NR_PAGEVISITS):
            end_dt = self.course_offering.start_datetime + datetime.timedelta(weeks=self.course_offering.no_weeks)
            random_visit_dt = fuzzy.FuzzyDateTime(self.course_offering.start_datetime, end_dt)
            random_page = all_pages[random.randint(0, NR_PAGES - 1)]
            visit = PageVisitFactory(page=random_page, module='course/x-bb-collabsession', lms_user=self.lms_user, visited_at=random_visit_dt)

        # Call the API endpoint
        response = self.client.get(self.api_url)
        self.assertEqual(response.status_code, HTTP_200_OK)
        response_dict = json.loads(response.content.decode('utf-8'))
        # FIXME: This could be greatly expanded to check the numbers in the response.
        self.assertEqual(len(response_dict), 2)
        self.assertIn('pageSet', response_dict)
        self.assertIn('totalsByWeek', response_dict)
        page_set = response_dict['pageSet']
        self.assertEqual(len(page_set), NR_PAGES)
    def test_events_one_page_view_before_event_in_week1_one_page_view_after_event_in_week2(self):
        self.events_setUp()
        # At this moment, we have one visit on the Thursday of the first week.  This will make the visit before
        # the event (Friday)
        self.repeating_event.day_of_week = 4 # Every friday
        self.repeating_event.save()
        # Now create a second visit that's on the Saturday of week 2.  This will make the visit after the event.
        visit2_dt = self.course_offering_start + datetime.timedelta(weeks=1, days=5) # Sat
        visit2 = PageVisitFactory(page=self.page, lms_user=self.lms_user, visited_at=visit2_dt)

        response = self.client.get(self.api_url)
        self.assertEqual(response.status_code, HTTP_200_OK)
        expected = [
            {
                'id': self.page.id,
                'title': self.page.title,
                'contentType': self.page.content_type,
                'weeks': [[1, 0], [0, 1]],
            }
        ]
        response_dict = json.loads(response.content.decode('utf-8'))
        self.assertEqual(response_dict, expected)
Exemple #8
0
    def test_session_calculation(self):
        mins_in_24h10m = 24 * 60 + 10

        cases = (
            # PageVisit t= Inputs # Expected session starts, durations and pageviews
            ((), []),  # No visits => no sessions
            ((0, ), [(0, 0, 1)]),  # One visit => one session of 0 mins
            ((0, 20), [(0, 20, 2)
                       ]),  # Two visits 20m apart => one session of 20 mins
            ((0, 50), [(0, 0, 1), (50, 0, 1)
                       ]),  # Two visits 50m apart => two sessions of 0 mins
            ((0, 20, 30), [
                (0, 30, 3)
            ]),  # Three visits 20 then 10 mins apart => one session of 30 mins
            ((0, 20, 50), [
                (0, 50, 3)
            ]),  # Three visits 20 then 30 mins apart => one session of 50 mins
            ((0, 40, 80), [
                (0, 80, 3)
            ]),  # Three visits 40 then 40 mins apart => one session of 80 mins
            ((0, 40, 90), [
                (0, 40, 2), (90, 0, 1)
            ]),  # Three visits 40 then 50 mins apart => two sessions
            ((0, mins_in_24h10m), [
                (0, 0, 1), (mins_in_24h10m, 0, 1)
            ]),  # Two visits 1d10m apart => two sessions
        )

        lms_user = LMSUserFactory(course_offering=self.offering)
        page = PageFactory()

        importer = ImportLmsData(self.offering, 'ignore.txt')

        for visit_event_times, expected_outputs in cases:
            # Erase results from last case
            PageVisit.objects.all().delete()
            LMSSession.objects.all().delete()
            # Turn tuple of time-in-minutes between views, into a tuple of visit datetimes
            visit_datetimes = (self.test_start_datetime +
                               datetime.timedelta(minutes=int(m))
                               for m in visit_event_times)

            # Create the series of visits, spaced apart by the event times
            for dt in visit_datetimes:
                visit = PageVisitFactory(lms_user=lms_user,
                                         page=page,
                                         visited_at=dt)

            # Run the session calculator
            importer.calculate_session_for_user(lms_user)

            # Analyse the sessions created by the calculator, and turn the start time, duration and pageviews into
            # tuples for comparison against the expected result
            actual_outputs = []
            for session in LMSSession.objects.all():
                session_start_timedelta = session.first_visit.visited_at - self.test_start_datetime
                session_start_time_in_mins = int(
                    session_start_timedelta.total_seconds() / 60)
                actual_outputs.append(
                    (session_start_time_in_mins,
                     session.session_length_in_mins, session.pageviews))

            # Now that we've assembled tuples of session starts, durations and pageviews, do they match what we expect?
            self.assertEqual(expected_outputs, actual_outputs)