Commit c56ac7be by Gabe Mulley

Course user activity

Change-Id: I6dac7d5bb0d041728c64c09e1999fb61339bee92
parent 6e4bac48
class Course(object):
"""Course scoped analytics."""
# TODO: Should we have an acceptance test that runs the hadoop job to populate the database, serves the data with
# the API server and uses the client to retrieve it and validate the various transports?
def __init__(self, client, course_key):
"""
Initialize the CourseUserActivity.
Arguments:
client (analyticsdataclient.client.Client): The client to use to access remote resources.
course_key (mixed): An object that when passed to unicode() returns the unique identifier for the course as
it is represented in the data pipeline results.
"""
self.client = client
self.course_key = course_key
@property
def recent_active_user_count(self):
"""A count of users who have recently interacted with the course in any way."""
# TODO: should we return something more structured than a python dict?
return self.client.get('courses/{0}/recent_activity'.format(unicode(self.course_key)))
@property
def recent_problem_activity_count(self):
"""A count of users who have recently attempted a problem."""
# TODO: Can we avoid passing around strings like "ATTEMPTED_PROBLEM" in the data pipeline and the client?
return self.client.get(
'courses/{0}/recent_activity?label=ATTEMPTED_PROBLEM'.format(unicode(self.course_key)))
from analyticsdataclient.client import Client, ClientError
class InMemoryClient(Client):
"""Serves resources that have previously been set and stored in memory."""
def __init__(self):
"""Initialize the fake client."""
super(InMemoryClient, self).__init__()
self.resources = {}
def has_resource(self, resource, timeout=None):
"""Return True iff the resource has been previously set."""
try:
self.get(resource, timeout=timeout)
return True
except ClientError:
return False
def get(self, resource, timeout=None):
"""Return the resource from memory."""
try:
return self.resources[resource]
except KeyError:
raise ClientError('Unable to find requested resource')
from unittest import TestCase
from analyticsdataclient.course import Course
from analyticsdataclient.tests import InMemoryClient
class CourseTest(TestCase):
def setUp(self):
self.client = InMemoryClient()
self.course = Course(self.client, 'edX/DemoX/Demo_Course')
def test_recent_activity(self):
# These tests don't feel terribly useful, since it's not really testing any substantial code... just that mock
# values are returned. The risky part of the interface (the URL and the response data) is not tested at all
# since it is mocked out.
course_id = 'edX/DemoX/Demo_Course'
expected_result = {
'course_id': 'edX/DemoX/Demo_Course',
'interval_start': '2014-05-24T00:00:00Z',
'interval_end': '2014-06-01T00:00:00Z',
'label': 'ACTIVE',
'count': 300,
}
self.client.resources['courses/{0}/recent_activity'.format(course_id)] = expected_result
self.assertEquals(self.course.recent_active_user_count, expected_result)
from unittest import TestCase from unittest import TestCase
from analyticsdataclient.client import Client, ClientError
from analyticsdataclient.status import Status from analyticsdataclient.status import Status
from analyticsdataclient.tests import InMemoryClient
class StatusTest(TestCase): class StatusTest(TestCase):
...@@ -46,23 +46,3 @@ class StatusTest(TestCase): ...@@ -46,23 +46,3 @@ class StatusTest(TestCase):
self.client.resources['health'] = {} self.client.resources['health'] = {}
self.assertEquals(self.status.healthy, False) self.assertEquals(self.status.healthy, False)
class InMemoryClient(Client):
def __init__(self):
super(InMemoryClient, self).__init__()
self.resources = {}
def has_resource(self, resource, timeout=None):
try:
self.get(resource, timeout=timeout)
return True
except ClientError:
return False
def get(self, resource, timeout=None):
try:
return self.resources[resource]
except KeyError:
raise ClientError('Unable to find requested resource')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment