From 3ff31892609bcb15f88f35c46a86d8872c173f6a Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 15 Jan 2013 15:39:05 -0500 Subject: [PATCH 01/27] Finished tests for access.py (as far as able) --- .../courseware/tests/test_access.py | 126 ++++++++++++++++++ .../courseware/tests/test_progress.py | 67 ++++++++++ 2 files changed, 193 insertions(+) create mode 100644 lms/djangoapps/courseware/tests/test_access.py create mode 100644 lms/djangoapps/courseware/tests/test_progress.py diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py new file mode 100644 index 0000000000..ebdad9e6a8 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -0,0 +1,126 @@ +import unittest +import logging +import time +from mock import MagicMock, patch + +from django.conf import settings +from django.test import TestCase + +from xmodule.course_module import CourseDescriptor +from xmodule.error_module import ErrorDescriptor +from xmodule.modulestore import Location +from xmodule.timeparse import parse_time +from xmodule.x_module import XModule, XModuleDescriptor +import courseware.access as access + +class Stub: + def __init__(self): + pass + +class AccessTestCase(TestCase): + def setUp(self): + pass + + def test__has_global_staff_access(self): + # Only 2 branches? + mock_user = MagicMock() + mock_user.is_staff = True + self.assertTrue(access._has_global_staff_access(mock_user)) + mock_user_2 = MagicMock() + mock_user.is_staff = False + self.assertFalse(access._has_global_staff_access(mock_user)) + + def test__has_access_to_location(self): + mock_user = MagicMock() + mock_user.is_authenticated.return_value = False + self.assertFalse(access._has_access_to_location(mock_user, "dummy", + "dummy")) + mock_user_2 = MagicMock() + mock_user_2.groups.all.return_value = ['instructor_toy'] + location = MagicMock(spec=Location) + location.course = 'toy' + self.assertTrue(access._has_access_to_location(mock_user_2, location, + "instructor")) + mock_user_3 = MagicMock() + mock_user_3.is_staff = False + self.assertFalse(access._has_access_to_location(mock_user_3, 'dummy', + 'dummy')) + + def test__dispatch(self): + self.assertRaises(ValueError, access._dispatch,{}, 'action', 'dummy', + 'dummy') + + def test__has_access_string(self): + mock_user = MagicMock() + mock_user.is_staff = True + self.assertTrue(access._has_access_string(mock_user, 'global', 'staff')) + self.assertFalse(access._has_access_string(mock_user, 'dummy', 'staff')) + + def test__has_access_descriptor(self): + mock_descriptor = MagicMock() + mock_descriptor.start = 0 + # test has dependency on time.gmtime() > 0 + self.assertTrue(access._has_access_descriptor("dummy", mock_descriptor, + 'load')) + mock_descriptor_2 = MagicMock() + mock_descriptor_2.start = None + self.assertTrue(access._has_access_descriptor("dummy", mock_descriptor_2, + 'load')) + + def test__has_access_error_desc(self): + mock_user = None + mock_descriptor = MagicMock() + mock_descriptor.location = None + # Just want to make sure function goes through path. + self.assertFalse(access._has_access_error_desc(mock_user, mock_descriptor, + 'load')) + + def test__get_access_group_name_course_desc(self): + self.assertEquals(access._get_access_group_name_course_desc('dummy', + 'notstaff'), + []) + # Problem: Can't use a Mock for location because needs to be a valid + # input to Location + # Getting "IndentationError: expected an indented block" +## tag, org, course, category, name = [MagicMock()]*5 +## #mock_course.location = ['tag', 'org', 'course', 'category', 'name'] +## L = Location([tag, org, course, category, name]) +## print L.course_id() +## assert False + #mock_course.location.course = 'toy' + #access._get_access_group_name_course_desc(mock_course, 'staff') + + def test__has_access_course_desc(self): + # This is more of a test for see_exists + mock_course = MagicMock() + mock_course.metadata.get = 'is_public' + self.assertTrue(access._has_access_course_desc('dummy', mock_course, + 'see_exists')) + mock_course_2 = MagicMock() + mock_course_2.metadata.get = 'private' + # Is there a way to see all the functions that have been called on a mock? + # Basically, I want to see if _has_staff_access_to_descriptor is called on + # the mock user and course + # This actually doesn't seem possible, according to the API + # None user can see course even if not 'is_public'? + self.assertTrue(access._has_access_course_desc(None, mock_course_2, + 'see_exists')) + def test_get_access_group_name(self): + # Need to create an instance of CourseDescriptor + # Is it necessary to test? basically "testing" python + self.assertRaises(TypeError, access.get_access_group_name, + 'notCourseDescriptor', 'dummy_action') + + def test_has_access(self): + magic = MagicMock() + error = ErrorDescriptor(magic) + mock_user = MagicMock() + self.assertFalse(access.has_access(None, error, 'load')) + self.assertFalse(access.has_access(mock_user, 'dummy', 'staff')) + self.assertRaises(TypeError, access.has_access,'dummyuser', {}, 'dummy') + +# How do decorators work? I think that is the correct +## def test_patches(self): +## user = Stub() +## @patch.object(Stub, "is_staff", True) +## self.assertTrue(access._has_global_staff_access(mock_user)) diff --git a/lms/djangoapps/courseware/tests/test_progress.py b/lms/djangoapps/courseware/tests/test_progress.py new file mode 100644 index 0000000000..480d594863 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_progress.py @@ -0,0 +1,67 @@ +from django.test import TestCase +from courseware import progress +from mock import MagicMock + + + +class ProgessTests(TestCase): + def setUp(self): + + self.d = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 0}) + + self.c = progress.completion() + self.c2= progress.completion() + self.c2.dict = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 2, + 'questions_incorrect': 1, + 'questions_total': 0}) + + self.cplusc2 = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 2, + 'questions_incorrect': 1, + 'questions_total': 0}) + + + + self.oth = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 7}) + + self.x = MagicMock() + self.x.dict = self.oth + + self.d_oth = {'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 7} + def test_getitem(self): + self.assertEqual(self.c.__getitem__('duration_watched'), 0) + + def test_setitem(self): + self.c.__setitem__('questions_correct', 4) + self.assertEqual(str(self.c),str(self.d)) + + # def test_add(self): + # self.assertEqual(self.c.__add__(self.c2), self.cplusc2) + + def test_contains(self): + + return self.c.__contains__('meow') + #self.assertEqual(self.c.__contains__('done'), True) + + def test_repr(self): + self.assertEqual(self.c.__repr__(), str(progress.completion())) From 1565cd5bd364caa2d478ae3bd27095462e46a5ec Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Fri, 18 Jan 2013 14:44:17 -0500 Subject: [PATCH 02/27] Test cases for lms/djangoapps/courseware/module_render in test_module_render --- .../courseware/tests/test_module_render.py | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 lms/djangoapps/courseware/tests/test_module_render.py diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py new file mode 100644 index 0000000000..8340d1fda2 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -0,0 +1,164 @@ +from unittest import TestCase +import logging +from mock import MagicMock, patch +import json +import factory + +from django.http import Http404, HttpResponse, HttpRequest +from django.conf import settings +from django.contrib.auth.models import User +from django.test.client import Client +from django.conf import settings + +from courseware.models import StudentModule +from xmodule.modulestore.exceptions import ItemNotFoundError +from xmodule.modulestore import Location +import courseware.module_render as render + +class Stub: + def __init__(self): + pass + +class ModuleRenderTestCase(TestCase): + def setUp(self): + self.location = ['tag', 'org', 'course', 'category', 'name'] + + def test_toc_for_course(self): + mock_course = MagicMock() + mock_course.id = 'dummy' + mock_course.location = Location(self.location) + mock_course.get_children.return_value = [] + mock_user = MagicMock() + mock_user.is_authenticated.return_value = False + self.assertIsNone(render.toc_for_course(mock_user,'dummy', + mock_course, 'dummy', 'dummy')) + + def test_get_module(self): + self.assertIsNone(render.get_module('dummyuser',None,\ + 'invalid location',None,None)) + + + def test__get_module(self): + mock_user = MagicMock() + mock_user.is_authenticated.return_value = True + location = ['tag', 'org', 'course', 'category', 'name'] + #render._get_module(mock_user, + + def test_get_instance_module(self): + mock_user = MagicMock() + mock_user.is_authenticated.return_value = False + self.assertIsNone(render.get_instance_module('dummy', mock_user, 'dummy', + 'dummy')) + mock_user_2 = MagicMock() + mock_user_2.is_authenticated.return_value = True + mock_module = MagicMock() + mock_module.descriptor.stores_state = False + self.assertIsNone(render.get_instance_module('dummy', mock_user_2, + mock_module,'dummy')) + + def test_get_shared_instance_module(self): +## class MockUserFactory(factory.Factory): +## FACTORY_FOR = MagicMock +## is_authenticated.return_value = + mock_user = MagicMock(User) + mock_user.is_authenticated.return_value = False + self.assertIsNone(render.get_shared_instance_module('dummy', mock_user, 'dummy', + 'dummy')) + mock_user_2 = MagicMock(User) + mock_user_2.is_authenticated.return_value = True + mock_module = MagicMock() + mock_module.shared_state_key = 'key' + self.assertIsInstance(render.get_shared_instance_module('dummy', mock_user, + mock_module, 'dummy'), StudentModule) + + + + def test_xqueue_callback(self): + mock_request = MagicMock() + mock_request.POST.copy.return_value = {} + # 339 + self.assertRaises(Http404, render.xqueue_callback,mock_request, + 'dummy', 'dummy', 'dummy', 'dummy') + mock_request_2 = MagicMock() + xpackage = {'xqueue_header': json.dumps({}), + 'xqueue_body' : 'Message from grader'} + mock_request_2.POST.copy.return_value = xpackage + # 342 + self.assertRaises(Http404, render.xqueue_callback,mock_request_2, + 'dummy', 'dummy', 'dummy', 'dummy') + mock_request_3 = MagicMock() + xpackage_2 = {'xqueue_header': json.dumps({'lms_key':'secretkey'}), + 'xqueue_body' : 'Message from grader'} + mock_request_3.POST.copy.return_value = xpackage_2 +## self.assertRaises(Http404, render.xqueue_callback, mock_request_3, +## 'dummy', 0, 'dummy', 'dummy') + # continue later + + def test_modx_dispatch(self): + self.assertRaises(Http404, render.modx_dispatch, 'dummy', 'dummy', + 'invalid Location', 'dummy') + mock_request = MagicMock() + mock_request.FILES.keys.return_value = ['file_id'] + mock_request.FILES.getlist.return_value = ['file']*(settings.MAX_FILEUPLOADS_PER_INPUT + 1) + self.assertEquals(render.modx_dispatch(mock_request, 'dummy', self.location, + 'dummy').content, + json.dumps({'success': 'Submission aborted! Maximum %d files may be submitted at once' %\ + settings.MAX_FILEUPLOADS_PER_INPUT})) + mock_request_2 = MagicMock() + mock_request_2.FILES.keys.return_value = ['file_id'] + inputfile = Stub() + inputfile.size = 1 + settings.STUDENT_FILEUPLOAD_MAX_SIZE + inputfile.name = 'name' + filelist = [inputfile] + mock_request_2.FILES.getlist.return_value = filelist + self.assertEquals(render.modx_dispatch(mock_request_2, 'dummy', self.location, + 'dummy').content, + json.dumps({'success': 'Submission aborted! Your file "%s" is too large (max size: %d MB)' %\ + (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2))})) + mock_request_3 = MagicMock() + mock_request_3.POST.copy.return_value = {} + inputfile_2 = Stub() + inputfile_2.size = 1 + inputfile_2.name = 'name' + self.assertRaises(ItemNotFoundError, render.modx_dispatch, + mock_request_3, 'dummy', self.location, 'toy') + # Deadend + + def test_preview_chemcalc(self): + mock_request = MagicMock() + mock_request.method = 'notGET' + self.assertRaises(Http404, render.preview_chemcalc, mock_request) + mock_request_2 = MagicMock() + mock_request_2.method = 'GET' + mock_request_2.GET.get.return_value = None + self.assertEquals(render.preview_chemcalc(mock_request_2).content, + json.dumps({'preview':'', + 'error':'No formula specified.'})) + + mock_request_3 = MagicMock() + mock_request_3.method = 'GET' + # Test fails because chemcalc.render_to_html always parses strings? + mock_request_3.GET.get.return_value = unicode('\x12400', errors="strict") +## self.assertEquals(render.preview_chemcalc(mock_request_3).content, +## json.dumps({'preview':'', +## 'error':"Couldn't parse formula: formula"})) +## + mock_request_3 = MagicMock() + mock_request_3.method = 'GET' + mock_request_3.GET.get.return_value = Stub() + self.assertEquals(render.preview_chemcalc(mock_request_3).content, + json.dumps({'preview':'', + 'error':"Error while rendering preview"})) + + + def test_get_score_bucket(self): + self.assertEquals(render.get_score_bucket(0, 10), 'incorrect') + self.assertEquals(render.get_score_bucket(1, 10), 'partial') + self.assertEquals(render.get_score_bucket(10, 10), 'correct') + # get_score_bucket calls error cases 'incorrect' + self.assertEquals(render.get_score_bucket(11, 10), 'incorrect') + self.assertEquals(render.get_score_bucket(-1, 10), 'incorrect') + + +class MagicMockFactory(factory.Factory): + FACTORY_FOR = MagicMock From 6e773909e48b84475d239c76ee8d9431eb80d71b Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 22 Jan 2013 10:36:05 -0500 Subject: [PATCH 03/27] added test_views --- .../courseware/tests/test_module_render.py | 4 +- lms/djangoapps/courseware/tests/test_views.py | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 lms/djangoapps/courseware/tests/test_views.py diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 8340d1fda2..d4748ebb04 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -70,8 +70,6 @@ class ModuleRenderTestCase(TestCase): mock_module.shared_state_key = 'key' self.assertIsInstance(render.get_shared_instance_module('dummy', mock_user, mock_module, 'dummy'), StudentModule) - - def test_xqueue_callback(self): mock_request = MagicMock() @@ -162,3 +160,5 @@ class ModuleRenderTestCase(TestCase): class MagicMockFactory(factory.Factory): FACTORY_FOR = MagicMock + v = factory.LazyAttribute(i for i in [True, False, False]) + diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py new file mode 100644 index 0000000000..1acf175bbd --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -0,0 +1,37 @@ +from unittest import TestCase +import logging +from mock import MagicMock, patch + +from django.conf import settings +from django.test.utils import override_settings + +import courseware.views as views + +class Stub(): + pass + +class ViewsTestCase(TestCase): + def setUp(self): + pass + + + def test_user_groups(self): + mock_user = MagicMock() + mock_user.is_authenticated.return_value = False + self.assertEquals(views.user_groups(mock_user),[]) + + @override_settings(DEBUG = True) + def test_user_groups_debug(self): + mock_user = MagicMock() + mock_user.is_authenticated.return_value = True + pass + #views.user_groups(mock_user) + #Keep going later + + def test_get_current_child(self): + self.assertIsNone(views.get_current_child(Stub())) + mock_xmodule = MagicMock() + mock_xmodule.position = -1 + mock_xmodule.get_display_items.return_value = ['one','two'] + print views.user_groups(mock_xmodule) + self.assertEquals(views.user_groups(mock_xmodule), 'one') From 35650233891b668d7c74570d59fd030dd49b0485 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 22 Jan 2013 14:01:01 -0500 Subject: [PATCH 04/27] created test_courses.py --- .../courseware/tests/test_courses.py | 21 +++++++++ lms/djangoapps/courseware/tests/test_views.py | 47 +++++++++++++++++-- 2 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 lms/djangoapps/courseware/tests/test_courses.py diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py new file mode 100644 index 0000000000..7e1456efec --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -0,0 +1,21 @@ +from mock import MagicMock, patch +import datetime + +from django.test import TestCase +from django.contrib.auth.models import User + +from student.models import CourseEnrollment +import courseware.courses as courses + +class CoursesTestCase(TestCase): + def setUp(self): + self.user = User.objects.create(username='dummy', password='123456', + email='test@mit.edu') + self.date = datetime.datetime(2013,1,22) + self.course_id = 'edx/toy/Fall_2012' + self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, + course_id = self.course_id, + created = self.date)[0] + + def test_get_course_by_id(self): + courses.get_course_by_id(self.course_id) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 1acf175bbd..ba7393f939 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -1,24 +1,37 @@ -from unittest import TestCase import logging from mock import MagicMock, patch +import datetime +from django.test import TestCase +from django.http import Http404 from django.conf import settings from django.test.utils import override_settings +from django.contrib.auth.models import User +from student.models import CourseEnrollment import courseware.views as views +from xmodule.modulestore.django import modulestore + class Stub(): pass class ViewsTestCase(TestCase): def setUp(self): - pass - + self.user = User.objects.create(username='dummy', password='123456', + email='test@mit.edu') + self.date = datetime.datetime(2013,1,22) + self.course_id = 'edx/toy/Fall_2012' + self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, + course_id = self.course_id, + created = self.date)[0] def test_user_groups(self): + # depreciated function? mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertEquals(views.user_groups(mock_user),[]) + @override_settings(DEBUG = True) def test_user_groups_debug(self): @@ -33,5 +46,29 @@ class ViewsTestCase(TestCase): mock_xmodule = MagicMock() mock_xmodule.position = -1 mock_xmodule.get_display_items.return_value = ['one','two'] - print views.user_groups(mock_xmodule) - self.assertEquals(views.user_groups(mock_xmodule), 'one') + self.assertEquals(views.get_current_child(mock_xmodule), 'one') + mock_xmodule_2 = MagicMock() + mock_xmodule_2.position = 3 + mock_xmodule_2.get_display_items.return_value = [] + self.assertIsNone(views.get_current_child(mock_xmodule_2)) + + def test_redirect_to_course_position(self): + mock_module = MagicMock() + mock_module.descriptor.id = 'Underwater Basketweaving' + mock_module.position = 3 + mock_module.get_display_items.return_value = [] + self.assertRaises(Http404, views.redirect_to_course_position, + mock_module, True) + + def test_index(self): + print modulestore() + assert False + + def test_registered_for_course(self): + self.assertFalse(views.registered_for_course('Basketweaving', None)) + mock_user = MagicMock() + mock_user.is_authenticated.return_value = False + self.assertFalse(views.registered_for_course('dummy', mock_user)) + mock_course = MagicMock() + mock_course.id = self.course_id + self.assertTrue(views.registered_for_course(mock_course, self.user)) From 7884e2c6906b99c181ca70bd8d8c8e7b9d34c146 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 22 Jan 2013 15:08:44 -0500 Subject: [PATCH 05/27] more tests --- lms/djangoapps/courseware/tests/test_courses.py | 2 ++ lms/djangoapps/courseware/tests/test_views.py | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 7e1456efec..7cb2f8b54b 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -6,6 +6,7 @@ from django.contrib.auth.models import User from student.models import CourseEnrollment import courseware.courses as courses +from xmodule.modulestore.xml import XMLModuleStore class CoursesTestCase(TestCase): def setUp(self): @@ -16,6 +17,7 @@ class CoursesTestCase(TestCase): self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] + self.xml_modulestore = XMLModuleStore() def test_get_course_by_id(self): courses.get_course_by_id(self.course_id) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index ba7393f939..9bca202761 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -61,8 +61,9 @@ class ViewsTestCase(TestCase): mock_module, True) def test_index(self): - print modulestore() - assert False + pass + #print modulestore() + #assert False def test_registered_for_course(self): self.assertFalse(views.registered_for_course('Basketweaving', None)) @@ -72,3 +73,7 @@ class ViewsTestCase(TestCase): mock_course = MagicMock() mock_course.id = self.course_id self.assertTrue(views.registered_for_course(mock_course, self.user)) + + def test_jump_to(self): + self.assertRaises(Http404, views.jump_to, 'foo', 'bar', ()) + From 26ee9a24ef72d035d7554e84b5cc161da8fb3f7d Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 22 Jan 2013 13:42:01 -0500 Subject: [PATCH 06/27] Add test for TOC rendering --- .../courseware/tests/test_module_render.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 lms/djangoapps/courseware/tests/test_module_render.py diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py new file mode 100644 index 0000000000..d5164d4903 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -0,0 +1,94 @@ +import unittest +import logging + +from django.conf import settings +from django.test import TestCase +from django.test.client import RequestFactory +from override_settings import override_settings + +import factory +from django.contrib.auth.models import User + +from xmodule.modulestore.django import modulestore, _MODULESTORES +from courseware import module_render + +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class TestTOC(TestCase): + """Check the Table of Contents for a course""" + def setUp(self): + self._MODULESTORES = {} + + # Toy courses should be loaded + self.course_name = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course(self.course_name) + + self.portal_user = UserFactory() + + def test_toc_toy_from_chapter(self): + chapter = 'Overview' + chapter_url = '%s/%s/%s' % ('/courses', self.course_name, chapter) + factory = RequestFactory() + request = factory.get(chapter_url) + + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': '', 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) + + actual = module_render.toc_for_course(self.portal_user, request, self.toy_course, chapter, None) + self.assertEqual(expected, actual) + + def test_toc_toy_from_section(self): + chapter = 'Overview' + chapter_url = '%s/%s/%s' % ('/courses', self.course_name, chapter) + section = 'Welcome' + factory = RequestFactory() + request = factory.get(chapter_url) + + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': '', 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': '', 'active': True}, + {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) + + actual = module_render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section) + self.assertEqual(expected, actual) \ No newline at end of file From 3fd69bcae4f36405e4c5069867ac5c1d62d0b4cb Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Wed, 23 Jan 2013 10:41:12 -0500 Subject: [PATCH 07/27] more tests in test_views.py --- lms/djangoapps/courseware/tests/test_views.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 9bca202761..cf4c792ab7 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -11,7 +11,8 @@ from django.contrib.auth.models import User from student.models import CourseEnrollment import courseware.views as views from xmodule.modulestore.django import modulestore - +from xmodule.modulestore.exceptions import InvalidLocationError,\ + ItemNotFoundError, NoPathToItem class Stub(): pass @@ -25,6 +26,7 @@ class ViewsTestCase(TestCase): self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] + self.location = ['tag', 'org', 'course', 'category', 'name'] def test_user_groups(self): # depreciated function? @@ -75,5 +77,8 @@ class ViewsTestCase(TestCase): self.assertTrue(views.registered_for_course(mock_course, self.user)) def test_jump_to(self): - self.assertRaises(Http404, views.jump_to, 'foo', 'bar', ()) + mock_request = MagicMock() + self.assertRaises(Http404, views.jump_to, mock_request, 'bar', ()) + self.assertRaises(ItemNotFoundError, views.jump_to, mock_request, 'dummy', + self.location) From 4d469fd9f7d0148eacb70823b8b44998de173142 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Thu, 24 Jan 2013 09:55:24 -0500 Subject: [PATCH 08/27] Add test for jump_to. --- lms/djangoapps/courseware/tests/test_views.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lms/djangoapps/courseware/tests/test_views.py diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py new file mode 100644 index 0000000000..f3206004d6 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -0,0 +1,48 @@ +import unittest +import logging + +from django.conf import settings +from django.test import TestCase +from django.test.client import RequestFactory +from override_settings import override_settings + +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore, _MODULESTORES +from courseware import views + +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class TestJumpTo(TestCase): + """Check the jumpto link for a course""" + def setUp(self): + self._MODULESTORES = {} + + # Toy courses should be loaded + self.course_name = 'edX/toy/2012_Fall' + + def test_jumpto_invalid_location(self): + location = Location('i4x', 'edX', 'toy', 'NoSuchPlace', None) + jumpto_url = '%s/%s/jump_to/%s' % ('/courses', self.course_name, location) + expected = 'courses/edX/toy/2012_Fall/courseware/Overview/' + response = self.client.get(jumpto_url) + self.assertEqual(response.status_code, 404) + + def test_jumpto_from_chapter(self): + location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') + jumpto_url = '%s/%s/jump_to/%s' % ('/courses', self.course_name, location) + expected = 'courses/edX/toy/2012_Fall/courseware/Overview/' + response = self.client.get(jumpto_url) + self.assertRedirects(response, expected, status_code=302, target_status_code=302) From 61e12f57e7f64721c969ed4ad03e1ee03474be63 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 24 Jan 2013 09:59:33 -0500 Subject: [PATCH 09/27] experimenting with creating a course --- .../courseware/tests/test_course_creation.py | 61 ++++++++++ .../courseware/tests/test_module_render.py | 13 +-- lms/djangoapps/courseware/tests/test_views.py | 106 ++++++++++++++++-- 3 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 lms/djangoapps/courseware/tests/test_course_creation.py diff --git a/lms/djangoapps/courseware/tests/test_course_creation.py b/lms/djangoapps/courseware/tests/test_course_creation.py new file mode 100644 index 0000000000..af3e3ee0e1 --- /dev/null +++ b/lms/djangoapps/courseware/tests/test_course_creation.py @@ -0,0 +1,61 @@ +import logging +from mock import MagicMock, patch +import factory +import copy +from path import path + +from django.test import TestCase +from django.test.client import Client +from django.core.urlresolvers import reverse +from django.conf import settings +from override_settings import override_settings + +from xmodule.modulestore.xml_importer import import_from_xml +import xmodule.modulestore.django + +TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) +TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') + +@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) +class CreateTest(TestCase): + def setUp(self): + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() + import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) + + def check_edit_item(self, test_course_name): + import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) + for descriptor in modulestore().get_items(Location(None, None, None, None, None)): + print "Checking ", descriptor.location.url() + print descriptor.__class__, descriptor.location + resp = self.client.get(reverse('edit_item'), {'id': descriptor.location.url()}) + self.assertEqual(resp.status_code, 200) + + def test_edit_item_toy(self): + self.check_edit_item('toy') + +## def setUp(self): +## self.client = Client() +## self.username = 'username' +## self.email = 'test@foo.com' +## self.pw = 'password' +## +## def create_account(self, username, email, pw): +## resp = self.client.post('/create_account', { +## 'username': username, +## 'email': email, +## 'password': pw, +## 'location': 'home', +## 'language': 'Franglish', +## 'name': 'Fred Weasley', +## 'terms_of_service': 'true', +## 'honor_code': 'true', +## }) +## return resp +## +## def registration(self, email): +## '''look up registration object by email''' +## return Registration.objects.get(user__email=email) +## +## def activate_user(self, email): +## activation_key = self.registration(email).activation_key diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 24f21241f0..ae725638e4 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -1,26 +1,22 @@ -from unittest import TestCase import logging from mock import MagicMock, patch import json import factory +import unittest from django.http import Http404, HttpResponse, HttpRequest from django.conf import settings from django.contrib.auth.models import User from django.test.client import Client from django.conf import settings +from django.test import TestCase +from django.test.client import RequestFactory from courseware.models import StudentModule from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.modulestore import Location import courseware.module_render as render - -import unittest - -from django.test import TestCase -from django.test.client import RequestFactory from override_settings import override_settings - from xmodule.modulestore.django import modulestore, _MODULESTORES @@ -202,7 +198,8 @@ class TestTOC(TestCase): # Toy courses should be loaded self.course_name = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course(self.course_name) - + print type(self.toy_course) + assert False self.portal_user = UserFactory() def test_toc_toy_from_chapter(self): diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index cf4c792ab7..3ff14657b8 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -1,32 +1,84 @@ import logging from mock import MagicMock, patch import datetime +import factory from django.test import TestCase -from django.http import Http404 +from django.http import Http404, HttpResponse from django.conf import settings from django.test.utils import override_settings from django.contrib.auth.models import User +from django.test.client import RequestFactory from student.models import CourseEnrollment -import courseware.views as views from xmodule.modulestore.django import modulestore from xmodule.modulestore.exceptions import InvalidLocationError,\ - ItemNotFoundError, NoPathToItem + ItemNotFoundError, NoPathToItem +import courseware.views as views +from xmodule.modulestore import Location +#import mitx.common.djangoapps.mitxmako as mako class Stub(): pass +def render_to_response(template_name, dictionary, context_instance=None, + namespace='main', **kwargs): + # The original returns HttpResponse + print dir() + print template_name + print dictionary + return HttpResponse('foo') + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + +# This part is required for modulestore() to work properly +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +class ModulestoreTest(TestCase): + def setUp(self): + self._MODULESTORES = {} + + # Toy courses should be loaded + self.course_name = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course('edX/toy/2012_Fall') + + def test(self): + self.assertEquals(1,2) + class ViewsTestCase(TestCase): def setUp(self): self.user = User.objects.create(username='dummy', password='123456', email='test@mit.edu') self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/Fall_2012' + self.course_id = 'edx/toy/2012_Fall' self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] self.location = ['tag', 'org', 'course', 'category', 'name'] + self._MODULESTORES = {} + # This is a CourseDescriptor object + self.toy_course = modulestore().get_course('edX/toy/2012_Fall') + self.request_factory = RequestFactory() + # Many functions call upon render_to_response + # Problem is that we don't know what templates there are? + views.render_to_response = render_to_response + #m = mako.MakoMiddleware() def test_user_groups(self): # depreciated function? @@ -77,8 +129,46 @@ class ViewsTestCase(TestCase): self.assertTrue(views.registered_for_course(mock_course, self.user)) def test_jump_to(self): - mock_request = MagicMock() - self.assertRaises(Http404, views.jump_to, mock_request, 'bar', ()) + chapter = 'Overview' + chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) + request = self.request_factory.get(chapter_url) + self.assertRaisesRegexp(Http404, 'Invalid location', views.jump_to, + request, 'bar', ()) + self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request, + 'dummy', self.location) + print type(self.toy_course) + print dir(self.toy_course) + print self.toy_course.location + print self.toy_course.__dict__ + valid = ['i4x', 'edX', 'toy', 'chapter', 'overview'] + L = Location('i4x', 'edX', 'toy', 'chapter', 'Overview', None) - self.assertRaises(ItemNotFoundError, views.jump_to, mock_request, 'dummy', - self.location) + views.jump_to(request, 'dummy', L) + + def test_static_tab(self): + mock_request = MagicMock() + mock_request.user = self.user + # What is tab_slug? + #views.static_tab(mock_request, self.course_id, 'dummy') + + def test_university_profile(self): + chapter = 'Overview' + chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) + request = self.request_factory.get(chapter_url) + request.user = UserFactory() + self.assertRaisesRegexp(Http404, 'University Profile*', + views.university_profile, request, 'Harvard') + # Mocked out function render_to_response + self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) + + def test_syllabus(self): + chapter = 'Overview' + chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) + request = self.request_factory.get(chapter_url) + request.user = UserFactory() + # course not found + views.syllabus(request, self.course_id) + + def test_render_notifications(self): + request = self.request_factory.get('foo') + views.render_notifications(request, self.course_id, 'dummy') From 9663973038a13e8cce1fd9eee0bd7ff212ca37bb Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 24 Jan 2013 14:59:46 -0500 Subject: [PATCH 10/27] more tests for courseware/views --- .../courseware/tests/test_module_render.py | 5 -- lms/djangoapps/courseware/tests/test_views.py | 70 +++++++++++++------ 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index ae725638e4..925601ba37 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -62,9 +62,6 @@ class ModuleRenderTestCase(TestCase): mock_module,'dummy')) def test_get_shared_instance_module(self): -## class MockUserFactory(factory.Factory): -## FACTORY_FOR = MagicMock -## is_authenticated.return_value = mock_user = MagicMock(User) mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_shared_instance_module('dummy', mock_user, 'dummy', @@ -198,8 +195,6 @@ class TestTOC(TestCase): # Toy courses should be loaded self.course_name = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course(self.course_name) - print type(self.toy_course) - assert False self.portal_user = UserFactory() def test_toc_toy_from_chapter(self): diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 57ef91c79e..fda591b2e6 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -1,9 +1,9 @@ -<<<<<<< HEAD import logging from mock import MagicMock, patch import datetime import factory import unittest +import os from django.test import TestCase from django.http import Http404, HttpResponse @@ -25,13 +25,13 @@ from xmodule.modulestore import Location class Stub(): pass -def render_to_response(template_name, dictionary, context_instance=None, - namespace='main', **kwargs): - # The original returns HttpResponse - print dir() - print template_name - print dictionary - return HttpResponse('foo') +##def render_to_response(template_name, dictionary, context_instance=None, +## namespace='main', **kwargs): +## # The original returns HttpResponse +## print dir() +## print template_name +## print dictionary +## return HttpResponse('foo') class UserFactory(factory.Factory): first_name = 'Test' @@ -56,7 +56,7 @@ TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) -class ModulestoreTest(TestCase): +#class ModulestoreTest(TestCase): @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestJumpTo(TestCase): @@ -68,9 +68,6 @@ class TestJumpTo(TestCase): self.course_name = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course('edX/toy/2012_Fall') - def test(self): - self.assertEquals(1,2) - def test_jumpto_invalid_location(self): location = Location('i4x', 'edX', 'toy', 'NoSuchPlace', None) jumpto_url = '%s/%s/jump_to/%s' % ('/courses', self.course_name, location) @@ -101,11 +98,11 @@ class ViewsTestCase(TestCase): self.request_factory = RequestFactory() # Many functions call upon render_to_response # Problem is that we don't know what templates there are? - views.render_to_response = render_to_response + #views.render_to_response = render_to_response #m = mako.MakoMiddleware() def test_user_groups(self): - # depreciated function? + # depreciated function mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertEquals(views.user_groups(mock_user),[]) @@ -160,10 +157,10 @@ class ViewsTestCase(TestCase): request, 'bar', ()) self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request, 'dummy', self.location) - print type(self.toy_course) - print dir(self.toy_course) - print self.toy_course.location - print self.toy_course.__dict__ +## print type(self.toy_course) +## print dir(self.toy_course) +## print self.toy_course.location +## print self.toy_course.__dict__ valid = ['i4x', 'edX', 'toy', 'chapter', 'overview'] L = Location('i4x', 'edX', 'toy', 'chapter', 'Overview', None) @@ -172,18 +169,32 @@ class ViewsTestCase(TestCase): def test_static_tab(self): mock_request = MagicMock() mock_request.user = self.user - # What is tab_slug? + # What is tab_slug? A string? #views.static_tab(mock_request, self.course_id, 'dummy') + def test_static_university_profile(self): + # TODO + # Can't test unless have a valid template file +## request = self.client.get('university_profile/edX') +## views.static_university_profile(request, 'edX') + pass + + def test_university_profile(self): + chapter = 'Overview' chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) request = self.request_factory.get(chapter_url) request.user = UserFactory() self.assertRaisesRegexp(Http404, 'University Profile*', views.university_profile, request, 'Harvard') - # Mocked out function render_to_response - self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) + # Supposed to return a HttpResponse object + # Templates don't exist because not in database + # TODO + # assertTemplateUsed is called on an HttpResponse, but + #request_2 = self.client.get('/university_profile/edx') + #self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) + # Can't continue testing unless have valid template file def test_syllabus(self): chapter = 'Overview' @@ -191,8 +202,23 @@ class ViewsTestCase(TestCase): request = self.request_factory.get(chapter_url) request.user = UserFactory() # course not found + # TODO views.syllabus(request, self.course_id) def test_render_notifications(self): request = self.request_factory.get('foo') - views.render_notifications(request, self.course_id, 'dummy') + #views.render_notifications(request, self.course_id, 'dummy') + # TODO + # Needs valid template + + def test_news(self): + #print settings.TEMPLATE_DIRS + #assert False + # I want news to get all the way to render_to_response + # Bug? get_notifications is actually in lms/lib/comment_client/legacy.py + request = self.client.get('/news') + self.user.id = 'foo' + request.user = self.user + course_id = 'edX/toy/2012_Fall' + views.news(request, course_id) + # TODO From f9b0ec37cd760750bdc2522d22184d1b0cb66a39 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 24 Jan 2013 16:08:19 -0500 Subject: [PATCH 11/27] more tests in test_views, needs templates to continue --- lms/djangoapps/courseware/tests/test_views.py | 67 +++++++++++-------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index fda591b2e6..52496bcb6b 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -4,6 +4,7 @@ import datetime import factory import unittest import os +from nose.plugins.skip import SkipTest from django.test import TestCase from django.http import Http404, HttpResponse @@ -19,6 +20,12 @@ from xmodule.modulestore.exceptions import InvalidLocationError,\ import courseware.views as views from xmodule.modulestore import Location +def skipped(func): + from nose.plugins.skip import SkipTest + def _(): + raise SkipTest("Test %s is skipped" % func.__name__) + _.__name__ = func.__name__ + return _ #from override_settings import override_settings @@ -39,8 +46,14 @@ class UserFactory(factory.Factory): is_staff = True is_active = True -# This part is required for modulestore() to work properly +def skipped(func): + from nose.plugins.skip import SkipTest + def _(): + raise SkipTest("Test %s is skipped" % func.__name__) + _.__name__ = func.__name__ + return _ +# This part is required for modulestore() to work properly def xml_store_config(data_dir): return { 'default': { @@ -96,10 +109,6 @@ class ViewsTestCase(TestCase): # This is a CourseDescriptor object self.toy_course = modulestore().get_course('edX/toy/2012_Fall') self.request_factory = RequestFactory() - # Many functions call upon render_to_response - # Problem is that we don't know what templates there are? - #views.render_to_response = render_to_response - #m = mako.MakoMiddleware() def test_user_groups(self): # depreciated function @@ -161,49 +170,50 @@ class ViewsTestCase(TestCase): ## print dir(self.toy_course) ## print self.toy_course.location ## print self.toy_course.__dict__ - valid = ['i4x', 'edX', 'toy', 'chapter', 'overview'] - L = Location('i4x', 'edX', 'toy', 'chapter', 'Overview', None) - - views.jump_to(request, 'dummy', L) +## valid = ['i4x', 'edX', 'toy', 'chapter', 'overview'] +## L = Location('i4x', 'edX', 'toy', 'chapter', 'Overview', None) +## +## views.jump_to(request, 'dummy', L) def test_static_tab(self): - mock_request = MagicMock() - mock_request.user = self.user - # What is tab_slug? A string? - #views.static_tab(mock_request, self.course_id, 'dummy') - + request = self.request_factory.get('foo') + request.user = self.user + self.assertRaises(Http404, views.static_tab, request, 'edX/toy/2012_Fall', + 'dummy') + # What are valid tab_slugs? +## request_2 = self.request_factory.get('foo') +## request_2.user = UserFactory() + def test_static_university_profile(self): # TODO # Can't test unless have a valid template file -## request = self.client.get('university_profile/edX') -## views.static_university_profile(request, 'edX') - pass + raise SkipTest + request = self.client.get('university_profile/edX') + self.assertIsInstance(views.static_university_profile(request, 'edX'), HttpResponse) - def test_university_profile(self): - + raise SkipTest chapter = 'Overview' chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) request = self.request_factory.get(chapter_url) request.user = UserFactory() self.assertRaisesRegexp(Http404, 'University Profile*', views.university_profile, request, 'Harvard') - # Supposed to return a HttpResponse object - # Templates don't exist because not in database # TODO - # assertTemplateUsed is called on an HttpResponse, but #request_2 = self.client.get('/university_profile/edx') - #self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) + self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) # Can't continue testing unless have valid template file + def test_syllabus(self): + raise SkipTest chapter = 'Overview' chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) request = self.request_factory.get(chapter_url) request.user = UserFactory() - # course not found + # Can't find valid template # TODO - views.syllabus(request, self.course_id) + views.syllabus(request, 'edX/toy/2012_Fall') def test_render_notifications(self): request = self.request_factory.get('foo') @@ -212,13 +222,12 @@ class ViewsTestCase(TestCase): # Needs valid template def test_news(self): - #print settings.TEMPLATE_DIRS - #assert False - # I want news to get all the way to render_to_response + raise SkipTest # Bug? get_notifications is actually in lms/lib/comment_client/legacy.py request = self.client.get('/news') self.user.id = 'foo' request.user = self.user course_id = 'edX/toy/2012_Fall' - views.news(request, course_id) + self.assertIsInstance(views.news(request, course_id), HttpResponse) + # TODO From 583505b95ba8a2a803e4130829e9c19c8e586533 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Fri, 25 Jan 2013 12:19:16 -0500 Subject: [PATCH 12/27] test_courses.py --- .../courseware/tests/test_courses.py | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 7cb2f8b54b..2f4868b27b 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -3,21 +3,59 @@ import datetime from django.test import TestCase from django.contrib.auth.models import User +from django.conf import settings +from django.test.utils import override_settings from student.models import CourseEnrollment import courseware.courses as courses from xmodule.modulestore.xml import XMLModuleStore +from xmodule.modulestore.django import modulestore +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class CoursesTestCase(TestCase): def setUp(self): self.user = User.objects.create(username='dummy', password='123456', email='test@mit.edu') self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/Fall_2012' + self.course_id = 'edx/toy/2012_Fall' self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] - self.xml_modulestore = XMLModuleStore() + self._MODULESTORES = {} + self.toy_course = modulestore().get_course('edX/toy/2012_Fall') def test_get_course_by_id(self): - courses.get_course_by_id(self.course_id) + courses.get_course_by_id("edx/toy/2012_Fall") + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class CoursesTests(TestCase): + def setUp(self): + self._MODULESTORES = {} + self.course_name = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course('edX/toy/2012_Fall') + self.fake_user = User.objects.create(is_superuser=True) + + ''' + no test written for get_request_for_thread + ''' + + def test_get_course_by_id(self): + self.test_course_id = "edX/toy/2012_Fall" + # print modulestore().get_instance(test_course_id, Location('i4x', 'edx', 'toy', 'course', '2012_Fall')) + self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) + + From 7918c35414ca2f6d9cfe7205b684902deaf43ae9 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Mon, 28 Jan 2013 15:29:55 -0500 Subject: [PATCH 13/27] fixing up tests --- .../courseware/tests/test_courses.py | 30 ++-- .../courseware/tests/test_module_render.py | 130 ++++++++++++------ lms/djangoapps/courseware/tests/test_views.py | 44 +++--- 3 files changed, 126 insertions(+), 78 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py index 2f4868b27b..91b6af4dfc 100644 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ b/lms/djangoapps/courseware/tests/test_courses.py @@ -10,6 +10,7 @@ from student.models import CourseEnrollment import courseware.courses as courses from xmodule.modulestore.xml import XMLModuleStore from xmodule.modulestore.django import modulestore +from xmodule.modulestore import Location def xml_store_config(data_dir): return { @@ -28,34 +29,35 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class CoursesTestCase(TestCase): def setUp(self): - self.user = User.objects.create(username='dummy', password='123456', - email='test@mit.edu') - self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/2012_Fall' - self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, - course_id = self.course_id, - created = self.date)[0] +## self.user = User.objects.create(username='dummy', password='123456', +## email='test@mit.edu') +## self.date = datetime.datetime(2013,1,22) +## self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, +## course_id = self.course_id, +## created = self.date)[0] self._MODULESTORES = {} + #self.course_id = 'edx/toy/2012_Fall' self.toy_course = modulestore().get_course('edX/toy/2012_Fall') def test_get_course_by_id(self): - courses.get_course_by_id("edx/toy/2012_Fall") + courses.get_course_by_id("edX/toy/2012_Fall") + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class CoursesTests(TestCase): + # runs def setUp(self): self._MODULESTORES = {} - self.course_name = 'edX/toy/2012_Fall' + #self.course_id = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course('edX/toy/2012_Fall') - self.fake_user = User.objects.create(is_superuser=True) +## self.fake_user = User.objects.create(is_superuser=True) ''' no test written for get_request_for_thread ''' def test_get_course_by_id(self): - self.test_course_id = "edX/toy/2012_Fall" + #self.test_course_id = "edX/toy/2012_Fall" + courses.get_course_by_id("edX/toy/2012_Fall") # print modulestore().get_instance(test_course_id, Location('i4x', 'edx', 'toy', 'course', '2012_Fall')) - self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) - - + #self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 925601ba37..3150450648 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -2,7 +2,9 @@ import logging from mock import MagicMock, patch import json import factory -import unittest +import unittest +from nose.tools import set_trace +from nose.plugins.skip import SkipTest from django.http import Http404, HttpResponse, HttpRequest from django.conf import settings @@ -11,22 +13,50 @@ from django.test.client import Client from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory +from django.core.urlresolvers import reverse -from courseware.models import StudentModule +from courseware.models import StudentModule, StudentModuleCache from xmodule.modulestore.exceptions import ItemNotFoundError +from xmodule.exceptions import NotFoundError from xmodule.modulestore import Location import courseware.module_render as render from override_settings import override_settings from xmodule.modulestore.django import modulestore, _MODULESTORES - +from xmodule.seq_module import SequenceModule +from courseware.tests.tests import PageLoader +from student.models import Registration class Stub: def __init__(self): pass -class ModuleRenderTestCase(TestCase): +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class ModuleRenderTestCase(PageLoader): def setUp(self): - self.location = ['tag', 'org', 'course', 'category', 'name'] + self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self._MODULESTORES = {} + self.course_id = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course(self.course_id) def test_toc_for_course(self): mock_course = MagicMock() @@ -37,19 +67,26 @@ class ModuleRenderTestCase(TestCase): mock_user.is_authenticated.return_value = False self.assertIsNone(render.toc_for_course(mock_user,'dummy', mock_course, 'dummy', 'dummy')) + # rest of tests are in class TestTOC def test_get_module(self): self.assertIsNone(render.get_module('dummyuser',None,\ 'invalid location',None,None)) - + #done def test__get_module(self): mock_user = MagicMock() - mock_user.is_authenticated.return_value = True - location = ['tag', 'org', 'course', 'category', 'name'] - #render._get_module(mock_user, + mock_user.is_authenticated.return_value = False + location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') + mock_request = MagicMock() + s = render._get_module(mock_user, mock_request, location, + 'dummy', 'edX/toy/2012_Fall') + self.assertIsInstance(s, SequenceModule) + # Don't know how to generate error in line 260 to test + # Can't tell if sequence module is an error? def test_get_instance_module(self): + # done mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_instance_module('dummy', mock_user, 'dummy', @@ -62,16 +99,28 @@ class ModuleRenderTestCase(TestCase): mock_module,'dummy')) def test_get_shared_instance_module(self): + raise SkipTest mock_user = MagicMock(User) mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_shared_instance_module('dummy', mock_user, 'dummy', 'dummy')) mock_user_2 = MagicMock(User) mock_user_2.is_authenticated.return_value = True + mock_module = MagicMock() mock_module.shared_state_key = 'key' - self.assertIsInstance(render.get_shared_instance_module('dummy', mock_user, - mock_module, 'dummy'), StudentModule) + mock_module.location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') + mock_module.get_shared_state.return_value = '{}' + mock_cache = MagicMock() + mock_cache.lookup.return_value = False + #mock_cache._state = 'dummy' + #set_trace() + print mock_module.get_shared_state() + s = render.get_shared_instance_module(self.course_id, mock_user_2, + mock_module, mock_cache) + self.assertIsInstance(s, StudentModule) + # Problem: can't get code to take branch that creates StudentModule? + # Can't finish testing modx_dispatch def test_xqueue_callback(self): mock_request = MagicMock() @@ -90,9 +139,21 @@ class ModuleRenderTestCase(TestCase): xpackage_2 = {'xqueue_header': json.dumps({'lms_key':'secretkey'}), 'xqueue_body' : 'Message from grader'} mock_request_3.POST.copy.return_value = xpackage_2 -## self.assertRaises(Http404, render.xqueue_callback, mock_request_3, -## 'dummy', 0, 'dummy', 'dummy') - # continue later + # Roadblock: how to get user registered in class? + raise SkipTest + # + # trying alternate way of creating account in hopes of getting valid id + # Problem: Can't activate user + + self.student_name = '12' + self.password = 'foo' + self.email = 'test@mit.edu' + self.create_account(self.student_name, self.email, self.password) + self.activate_user(self.email) + request = RequestFactory().get('stuff') + # This doesn't work to install user + render.xqueue_callback(mock_request_3, self.course_id, + self.student_name, self.password, 'dummy') def test_modx_dispatch(self): self.assertRaises(Http404, render.modx_dispatch, 'dummy', 'dummy', @@ -117,12 +178,23 @@ class ModuleRenderTestCase(TestCase): (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2))})) mock_request_3 = MagicMock() mock_request_3.POST.copy.return_value = {} + mock_request_3.FILES = False + mock_request_3.user = UserFactory() inputfile_2 = Stub() inputfile_2.size = 1 inputfile_2.name = 'name' self.assertRaises(ItemNotFoundError, render.modx_dispatch, mock_request_3, 'dummy', self.location, 'toy') - # Deadend + self.assertRaises(Http404,render.modx_dispatch, mock_request_3, 'dummy', + self.location, self.course_id) +## student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(self.course_id, +## mock_request_3.user, modulestore().get_instance(self.course_id, self.location)) +## get_shared_instance_module(course_id, request.user, instance, student_module_cache) + # 'goto_position' is the only dispatch that will work + mock_request_3.POST.copy.return_value = {'position':1} + self.assertIsInstance(render.modx_dispatch(mock_request_3, 'goto_position', + self.location, self.course_id), HttpResponse) + # keep going def test_preview_chemcalc(self): mock_request = MagicMock() @@ -159,33 +231,6 @@ class ModuleRenderTestCase(TestCase): self.assertEquals(render.get_score_bucket(11, 10), 'incorrect') self.assertEquals(render.get_score_bucket(-1, 10), 'incorrect') - -class MagicMockFactory(factory.Factory): - FACTORY_FOR = MagicMock - v = factory.LazyAttribute(i for i in [True, False, False]) - - - -def xml_store_config(data_dir): - return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', - } - } -} - -TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) - -class UserFactory(factory.Factory): - first_name = 'Test' - last_name = 'Robot' - is_staff = True - is_active = True - @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestTOC(TestCase): """Check the Table of Contents for a course""" @@ -245,3 +290,4 @@ class TestTOC(TestCase): actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section) self.assertEqual(expected, actual) + diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 52496bcb6b..c901f87720 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -32,14 +32,6 @@ def skipped(func): class Stub(): pass -##def render_to_response(template_name, dictionary, context_instance=None, -## namespace='main', **kwargs): -## # The original returns HttpResponse -## print dir() -## print template_name -## print dictionary -## return HttpResponse('foo') - class UserFactory(factory.Factory): first_name = 'Test' last_name = 'Robot' @@ -100,7 +92,7 @@ class ViewsTestCase(TestCase): self.user = User.objects.create(username='dummy', password='123456', email='test@mit.edu') self.date = datetime.datetime(2013,1,22) - self.course_id = 'edx/toy/2012_Fall' + self.course_id = 'edX/toy/2012_Fall' self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, course_id = self.course_id, created = self.date)[0] @@ -109,6 +101,9 @@ class ViewsTestCase(TestCase): # This is a CourseDescriptor object self.toy_course = modulestore().get_course('edX/toy/2012_Fall') self.request_factory = RequestFactory() + chapter = 'Overview' + self.chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) + def test_user_groups(self): # depreciated function @@ -145,9 +140,19 @@ class ViewsTestCase(TestCase): mock_module, True) def test_index(self): - pass - #print modulestore() - #assert False + assert SkipTest + request = self.request_factory.get(self.chapter_url) + request.user = UserFactory() + response = views.index(request, self.course_id) + self.assertIsInstance(response, HttpResponse) + self.assertEqual(response.status_code, 302) + # views.index does not throw 404 if chapter, section, or position are + # not valid, which doesn't match index's comments + views.index(request, self.course_id, chapter='foo', section='bar', + position='baz') + request_2 = self.request_factory.get(self.chapter_url) + request_2.user = self.user + response = views.index(request_2, self.course_id) def test_registered_for_course(self): self.assertFalse(views.registered_for_course('Basketweaving', None)) @@ -159,9 +164,7 @@ class ViewsTestCase(TestCase): self.assertTrue(views.registered_for_course(mock_course, self.user)) def test_jump_to(self): - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) self.assertRaisesRegexp(Http404, 'Invalid location', views.jump_to, request, 'bar', ()) self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request, @@ -186,16 +189,14 @@ class ViewsTestCase(TestCase): def test_static_university_profile(self): # TODO - # Can't test unless have a valid template file + # Can't test unless havehttp://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/ a valid template file raise SkipTest request = self.client.get('university_profile/edX') self.assertIsInstance(views.static_university_profile(request, 'edX'), HttpResponse) def test_university_profile(self): raise SkipTest - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) request.user = UserFactory() self.assertRaisesRegexp(Http404, 'University Profile*', views.university_profile, request, 'Harvard') @@ -207,15 +208,14 @@ class ViewsTestCase(TestCase): def test_syllabus(self): raise SkipTest - chapter = 'Overview' - chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - request = self.request_factory.get(chapter_url) + request = self.request_factory.get(self.chapter_url) request.user = UserFactory() # Can't find valid template # TODO views.syllabus(request, 'edX/toy/2012_Fall') def test_render_notifications(self): + raise SkipTest request = self.request_factory.get('foo') #views.render_notifications(request, self.course_id, 'dummy') # TODO From 74839663ff163576bef15ac951c6eba1a6d6dddf Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 10:12:39 -0500 Subject: [PATCH 14/27] added cms/djangoapps/contentstore/test/tests.py --- .../contentstore/tests/test_views.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 cms/djangoapps/contentstore/tests/test_views.py diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py new file mode 100644 index 0000000000..f513eef7f9 --- /dev/null +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -0,0 +1,50 @@ +import logging +from mock import MagicMock, patch +import json +import factory +import unittest +from nose.tools import set_trace +from nose.plugins.skip import SkipTest + +from django.http import Http404, HttpResponse, HttpRequest +from django.conf import settings +from django.contrib.auth.models import User +from django.test.client import Client +from django.conf import settings +from django.test import TestCase +from django.test.client import RequestFactory + +import cms.djangoapps.contentstore.views as views + +def xml_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } + } +} + +class UserFactory(factory.Factory): + first_name = 'Test' + last_name = 'Robot' + is_staff = True + is_active = True + is_authenticated = True + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + +@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) +class ViewsTestCase(TestCase): + def setUp(self): + self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self._MODULESTORES = {} + self.course_id = 'edX/toy/2012_Fall' + self.toy_course = modulestore().get_course(self.course_id) + + def test_has_access(self): + user = UserFactory() + views.has_access(user, self.location) From 85c412fc2eafefd0240a3c0081532d633b045a37 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 11:06:32 -0500 Subject: [PATCH 15/27] changed cms/env/tests, added test_views.py --- cms/djangoapps/contentstore/tests/test_views.py | 10 +++++++--- cms/envs/test.py | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index f513eef7f9..ae6548bd9d 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -13,8 +13,11 @@ from django.test.client import Client from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory +from override_settings import override_settings + +from xmodule.modulestore.django import modulestore, _MODULESTORES +import contentstore.views as views -import cms.djangoapps.contentstore.views as views def xml_store_config(data_dir): return { @@ -32,7 +35,6 @@ class UserFactory(factory.Factory): last_name = 'Robot' is_staff = True is_active = True - is_authenticated = True TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) @@ -47,4 +49,6 @@ class ViewsTestCase(TestCase): def test_has_access(self): user = UserFactory() - views.has_access(user, self.location) + user.is_authenticated = True + set_trace() + self.assertTrue(views.has_access(user, self.location)) diff --git a/cms/envs/test.py b/cms/envs/test.py index d55c309827..e31037b04f 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -25,6 +25,9 @@ STATIC_ROOT = TEST_ROOT / "staticfiles" GITHUB_REPO_ROOT = TEST_ROOT / "data" COMMON_TEST_DATA_ROOT = COMMON_ROOT / "test" / "data" +# Makes the tests run much faster... +SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead + # TODO (cpennington): We need to figure out how envs/test.py can inject things into common.py so that we don't have to repeat this sort of thing STATICFILES_DIRS = [ COMMON_ROOT / "static", From d9fdccb567924f04ec420e95bfe5c37e5bee751a Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 14:23:55 -0500 Subject: [PATCH 16/27] testing testing tests --- .../contentstore/tests/test_views.py | 45 ++++++++++++++++--- .../courseware/tests/test_module_render.py | 9 ++-- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index ae6548bd9d..c1fa19624c 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -6,7 +6,7 @@ import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest -from django.http import Http404, HttpResponse, HttpRequest +from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect from django.conf import settings from django.contrib.auth.models import User from django.test.client import Client @@ -14,9 +14,12 @@ from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory from override_settings import override_settings +from django.core.exceptions import PermissionDenied from xmodule.modulestore.django import modulestore, _MODULESTORES import contentstore.views as views +import auth.authz as a +from contentstore.tests.factories import XModuleCourseFactory, CourseFactory def xml_store_config(data_dir): @@ -39,16 +42,46 @@ class UserFactory(factory.Factory): TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class ViewsTestCase(TestCase): def setUp(self): self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] + # empty Modulestore self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' + self.course_id_2 = 'edx/full/6.002_Spring_2012' self.toy_course = modulestore().get_course(self.course_id) def test_has_access(self): - user = UserFactory() - user.is_authenticated = True - set_trace() - self.assertTrue(views.has_access(user, self.location)) + user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) + m = MagicMock() + m.count.return_value = 1 + user.groups.filter.return_value = m + self.assertTrue(views.has_access(user, self.location_2)) + user.is_authenticated = False + self.assertFalse(views.has_access(user, self.location_2)) + + def test_course_index(self): + # UserFactory doesn't work? + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + request = MagicMock(user = self.user) + # Instead of raising exception when has_access is False, redirects + self.assertIsInstance(views.course_index(request, 'edX', + 'full', '6.002_Spring_2012'), HttpResponseRedirect) + self.user_2 = MagicMock(is_staff = True, is_active = True) + self.user_2.is_authenticated.return_value = True + request_2 = MagicMock(user = self.user_2) + # Bug? Raises error because calls modulestore().get_item(location) + #NotImplementedError: XMLModuleStores can't guarantee that definitions + #are unique. Use get_instance. + print views.course_index(request_2, 'edX', + 'full', '6.002_Spring_2012') + + def test_edit_subsection(self): + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + self.request = MagicMock(user = self.user) + self.assertIsInstance(views.edit_subscription(self.request, self.location_2), + HttpResponseRedirect) + diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 3150450648..f419e6f582 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -107,8 +107,7 @@ class ModuleRenderTestCase(PageLoader): mock_user_2 = MagicMock(User) mock_user_2.is_authenticated.return_value = True - mock_module = MagicMock() - mock_module.shared_state_key = 'key' + mock_module = MagicMock(shared_state_key = 'key') mock_module.location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') mock_module.get_shared_state.return_value = '{}' mock_cache = MagicMock() @@ -197,11 +196,9 @@ class ModuleRenderTestCase(PageLoader): # keep going def test_preview_chemcalc(self): - mock_request = MagicMock() - mock_request.method = 'notGET' + mock_request = MagicMock(method = 'notGET') self.assertRaises(Http404, render.preview_chemcalc, mock_request) - mock_request_2 = MagicMock() - mock_request_2.method = 'GET' + mock_request_2 = MagicMock(method = 'GET') mock_request_2.GET.get.return_value = None self.assertEquals(render.preview_chemcalc(mock_request_2).content, json.dumps({'preview':'', From 3858362157d1638f222fc5e8da893bdbe38262d9 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Tue, 29 Jan 2013 15:53:20 -0500 Subject: [PATCH 17/27] more tests --- cms/djangoapps/contentstore/tests/test_views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index c1fa19624c..ed18e1cc8c 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -50,8 +50,14 @@ class ViewsTestCase(TestCase): self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' - self.toy_course = modulestore().get_course(self.course_id) + #self.toy_course = modulestore().get_course(self.course_id) + # Problem: Classes persist, need to delete stuff from modulestore + self.course = CourseFactory.create() + print dir(self.course) + def tearDown(self): + pass + def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) m = MagicMock() @@ -72,16 +78,15 @@ class ViewsTestCase(TestCase): self.user_2 = MagicMock(is_staff = True, is_active = True) self.user_2.is_authenticated.return_value = True request_2 = MagicMock(user = self.user_2) - # Bug? Raises error because calls modulestore().get_item(location) - #NotImplementedError: XMLModuleStores can't guarantee that definitions - #are unique. Use get_instance. + # Need to use XModuleStoreFactory? print views.course_index(request_2, 'edX', 'full', '6.002_Spring_2012') def test_edit_subsection(self): + # Redirects if request.user doesn't have access to location self.user = MagicMock(is_staff = False, is_active = False) self.user.is_authenticated.return_value = False self.request = MagicMock(user = self.user) - self.assertIsInstance(views.edit_subscription(self.request, self.location_2), + self.assertIsInstance(views.edit_subsection(self.request, self.location_2), HttpResponseRedirect) From cdbe9857d67b3c71255be512e47e440a5a0e10b2 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Wed, 30 Jan 2013 12:30:48 -0500 Subject: [PATCH 18/27] tests in cms.djangoapps.contentstore/tests/test_views.py --- .../contentstore/tests/test_views.py | 64 ++++++++++++++++--- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index ed18e1cc8c..87dd7f7ac6 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -6,7 +6,7 @@ import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest -from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect +from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest from django.conf import settings from django.contrib.auth.models import User from django.test.client import Client @@ -18,8 +18,8 @@ from django.core.exceptions import PermissionDenied from xmodule.modulestore.django import modulestore, _MODULESTORES import contentstore.views as views -import auth.authz as a -from contentstore.tests.factories import XModuleCourseFactory, CourseFactory +from contentstore.tests.factories import CourseFactory, ItemFactory +from xmodule.modulestore import Location def xml_store_config(data_dir): @@ -46,17 +46,21 @@ class ViewsTestCase(TestCase): def setUp(self): self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] + self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] # empty Modulestore self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' #self.toy_course = modulestore().get_course(self.course_id) # Problem: Classes persist, need to delete stuff from modulestore + # is a CourseDescriptor object? self.course = CourseFactory.create() - print dir(self.course) + # is a sequence descriptor + self.item = ItemFactory.create(template = 'i4x://edx/templates/sequential/Empty') def tearDown(self): - pass + _MODULESTORES = {} + modulestore().collection.drop() def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) @@ -72,15 +76,15 @@ class ViewsTestCase(TestCase): self.user = MagicMock(is_staff = False, is_active = False) self.user.is_authenticated.return_value = False request = MagicMock(user = self.user) - # Instead of raising exception when has_access is False, redirects + # Redirects if request.user doesn't have access to location self.assertIsInstance(views.course_index(request, 'edX', 'full', '6.002_Spring_2012'), HttpResponseRedirect) self.user_2 = MagicMock(is_staff = True, is_active = True) self.user_2.is_authenticated.return_value = True request_2 = MagicMock(user = self.user_2) - # Need to use XModuleStoreFactory? - print views.course_index(request_2, 'edX', - 'full', '6.002_Spring_2012') + # Doesn't work unless we figure out render_to_response +## views.course_index(request_2, 'MITx', +## '999', 'Robot_Super_Course') def test_edit_subsection(self): # Redirects if request.user doesn't have access to location @@ -89,4 +93,44 @@ class ViewsTestCase(TestCase): self.request = MagicMock(user = self.user) self.assertIsInstance(views.edit_subsection(self.request, self.location_2), HttpResponseRedirect) - + # If location isn't for a "sequential", return Bad Request + self.user_2 = MagicMock(is_staff = True, is_active = True) + self.user_2.is_authenticated.return_value = True + self.request_2 = MagicMock(user = self.user_2) + self.assertIsInstance(views.edit_subsection(self.request_2, + self.location_3), HttpResponseBadRequest) + # Need render_to_response + #views.edit_subsection(self.request_2, self.item.location) + + def test_edit_unit(self): + # if user doesn't have access, should redirect + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + self.request = MagicMock(user = self.user) + self.assertIsInstance(views.edit_unit(self.request, self.location_2), + HttpResponseRedirect) + + def test_assignment_type_update(self): + # If user doesn't have access, should redirect + self.user = MagicMock(is_staff = False, is_active = False) + self.user.is_authenticated.return_value = False + self.request = RequestFactory().get('foo') + self.request.user = self.user + self.assertIsInstance(views.assignment_type_update(self.request, + 'MITx', '999', 'course', 'Robot_Super_Course'), + HttpResponseRedirect) + # if user has access, then should return HttpResponse + self.user_2 = MagicMock(is_staff = True, is_active = True) + self.user_2.is_authenticated.return_value = True + self.request.user = self.user_2 + get_response = views.assignment_type_update(self.request,'MITx', '999', + 'course', 'Robot_Super_Course') + self.assertIsInstance(get_response,HttpResponse) + get_response_string = '{"id": 99, "location": ["i4x", "MITx", "999", "course", "Robot_Super_Course", null], "graderType": "Not Graded"}' + self.assertEquals(get_response.content, get_response_string) + self.request_2 = RequestFactory().post('foo') + self.request_2.user = self.user_2 + post_response = views.assignment_type_update(self.request_2,'MITx', '999', + 'course', 'Robot_Super_Course') + self.assertIsInstance(post_response,HttpResponse) + self.assertEquals(post_response.content, 'null') From 40ddaa99766244efb3f46b8b2841aa6f1a076724 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Wed, 30 Jan 2013 16:03:16 -0500 Subject: [PATCH 19/27] more tests on test_views.py --- .../contentstore/tests/test_views.py | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index 87dd7f7ac6..2cb00eac36 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -5,6 +5,7 @@ import factory import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest +from collections import defaultdict from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest from django.conf import settings @@ -20,7 +21,11 @@ from xmodule.modulestore.django import modulestore, _MODULESTORES import contentstore.views as views from contentstore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore import Location +from xmodule.x_module import ModuleSystem +from xmodule.error_module import ErrorModule +class Stub(): + pass def xml_store_config(data_dir): return { @@ -61,6 +66,7 @@ class ViewsTestCase(TestCase): def tearDown(self): _MODULESTORES = {} modulestore().collection.drop() + assert False def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) @@ -134,3 +140,78 @@ class ViewsTestCase(TestCase): 'course', 'Robot_Super_Course') self.assertIsInstance(post_response,HttpResponse) self.assertEquals(post_response.content, 'null') + + def test_load_preview_state(self): + # Tests that function creates empty defaultdict when request.session + # is empty + # location cannot be a list or other mutable type + self.request = RequestFactory().get('foo') + self.request.session = {} + instance_state, shared_state = views.load_preview_state(self.request, + 'foo', 'bar') + self.assertIsNone(instance_state) + self.assertIsNone(shared_state) + + def test_save_preview_state(self): + self.request = RequestFactory().get('foo') + self.request.session = {} + loc = Location(self.location_3) + result = {'preview_states': + {('id', loc):{'instance':None, + 'shared':None, + } + } + } + views.save_preview_state(self.request, 'id', loc, None, None) + self.assertEquals(self.request.session, result) + + def test_get_preview_module(self): + raise SkipTest + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + mock_descriptor = MagicMock() + mock_descriptor.get_sample_state.return_value = [('foo','bar')] + instance, shared = views.get_preview_module(self.request, 'id', mock_descriptor) + self.assertEquals(instance, 'foo') + + def test_preview_module_system(self): + # Returns a ModuleSystem + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + self.assertIsInstance(views.preview_module_system(self.request, + 'id', self.course), + ModuleSystem) + + def test_load_preview_module(self): + + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + self.request.session = {} + self.assertIsInstance(views.load_preview_module(self.request, 'id', + self.course, 'instance', 'shared'), + ErrorModule) + system = views.preview_module_system(self.request, 'id', self.course) + # is a functools.partial object? + # Not sure how to get a valid line 507 + print self.course.xmodule_constructor(system) + print self.course.xmodule_constructor(system).func + print self.course.xmodule_constructor(system).keywords + + def test__xmodule_recurse(self): + raise SkipTest +## mock_item = MagicMock() +## mock_item.get_children.return_value = [] + s = Stub() + s.children.append(Stub()) + views._xmodule_recurse(s, lambda x: return) + #views._xmodule_recurse(s, lambda x: x.n += 1) + self.assertEquals(s.n, 1) + self.assertEquals(s.children[0].n, 1) + +class Stub(): + def __init__(self): + self.n = 0 + self.children = [] + def get_children(self): + return self.children + From abc3e5b09d705d728522b6ffb79da85a5489fe1a Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 31 Jan 2013 14:47:59 -0500 Subject: [PATCH 20/27] more tests in test_views.py --- .../contentstore/tests/test_views.py | 119 ++++++++++++++++-- 1 file changed, 111 insertions(+), 8 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index 2cb00eac36..9fa16ad4b2 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -23,6 +23,7 @@ from contentstore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore import Location from xmodule.x_module import ModuleSystem from xmodule.error_module import ErrorModule +from contentstore.utils import get_course_for_item class Stub(): pass @@ -49,6 +50,7 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) class ViewsTestCase(TestCase): def setUp(self): + #modulestore().collection.drop() self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] @@ -56,8 +58,6 @@ class ViewsTestCase(TestCase): self._MODULESTORES = {} self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' - #self.toy_course = modulestore().get_course(self.course_id) - # Problem: Classes persist, need to delete stuff from modulestore # is a CourseDescriptor object? self.course = CourseFactory.create() # is a sequence descriptor @@ -66,7 +66,7 @@ class ViewsTestCase(TestCase): def tearDown(self): _MODULESTORES = {} modulestore().collection.drop() - assert False + #assert False def test_has_access(self): user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) @@ -196,18 +196,121 @@ class ViewsTestCase(TestCase): print self.course.xmodule_constructor(system) print self.course.xmodule_constructor(system).func print self.course.xmodule_constructor(system).keywords + print dir(self.course.xmodule_constructor(system).func) def test__xmodule_recurse(self): - raise SkipTest -## mock_item = MagicMock() -## mock_item.get_children.return_value = [] + #There shouldn't be a difference, but the code works with defined + # function f but not with lambda functions + mock_item = MagicMock() + mock_item.get_children.return_value = [] s = Stub() s.children.append(Stub()) - views._xmodule_recurse(s, lambda x: return) - #views._xmodule_recurse(s, lambda x: x.n += 1) + views._xmodule_recurse(s, f) self.assertEquals(s.n, 1) self.assertEquals(s.children[0].n, 1) + + def test_get_module_previews(self): + # needs a working render_to_string + raise SkipTest + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + self.request.session = {} + print views.get_module_previews(self.request, self.course) + + def test_delete_item(self): + # If user doesn't have permission, redirect + self.no_permit_user = MagicMock(is_staff = False, is_active = False) + self.no_permit_user.is_authenticated.return_value = True + self.request = RequestFactory().post('i4x://MITx/999/course/Robot_Super_Course') + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':'i4x://MITx/999/course/Robot_Super_Course'}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.delete_item, self.request) + # Should return an HttpResponse + self.permit_user =MagicMock(is_staff = True, is_active = True) + self.permit_user.is_authenticated.return_value = True + self.request_2 = RequestFactory().post(self.item.location.url()) + self.request_2.POST = self.request_2.POST.copy() + self.request_2.POST.update({'id':self.item.location.url()}) + self.request_2.user = self.permit_user + response = views.delete_item(self.request_2) + self.assertIsInstance(response, HttpResponse) + self.assertEquals(modulestore().get_items(self.item.location.url()), []) + # Set delete_children to True to delete all children + # Create children + self.item_2 = ItemFactory.create() + child_item = ItemFactory.create() +## print type(self.item_2) +## print self.item_2.__dict__ + # Is there better way of adding children? What format are children in? + self.item_2.definition['children'] = [child_item.location.url()] + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request_3.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_3.user = self.permit_user + print self.item_2.get_children() + self.assertIsInstance(views.delete_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_2.location.url()), []) + # Problem: Function doesn't delete child item? + # child_item can be manually deleted, but can't delete it using function + # Not sure if problem with _xmodule_recurse and lambda functions + #store = views.get_modulestore(child_item.location.url()) + #store.delete_item(child_item.location) + self.assertEquals(modulestore().get_items(child_item.location.url()), []) + # Check delete_item on 'vertical' + self.item_3 = ItemFactory.create(template = 'i4x://edx/templates/vertical/Empty') + self.request_4 = RequestFactory().post(self.item_3.location.url()) + self.request_4.POST = self.request_4.POST.copy() + self.request_4.POST.update({'id':self.item_3.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.delete_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_3.location.url()), []) + + def test_save_item(self): + # Test that user with no permissions gets redirected + self.no_permit_user = MagicMock(is_staff = False, is_active = False) + self.no_permit_user.is_authenticated.return_value = True + self.request = RequestFactory().post(self.item.location.url()) + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':self.item.location.url()}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.save_item, self.request) + # Test user with permissions but nothing in request.POST + self.item_2 = ItemFactory.create() + self.permit_user =MagicMock(is_staff = True, is_active = True) + self.permit_user.is_authenticated.return_value = True + self.request_2 = RequestFactory().post(self.item_2.location.url()) + self.request_2.POST = self.request.POST.copy() + self.request_2.POST.update({'id':self.item_2.location.url()}) + self.request_2.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_2), HttpResponse) + # Test updating data + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'data':{'foo':'bar'}}) + self.request_3.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).definition['data'], + {u'foo': u'bar'}) + # Test metadata, which is a dictionary? + self.request_4 = RequestFactory().post(self.item_2.location.url()) + self.request_4.POST = self.request.POST.copy() + self.request_4.POST.update({'id':self.item_2.location.url(), + 'metadata':{'foo':'bar'}}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).metadata['foo'], + 'bar') + +def f(x): + x.n += 1 + class Stub(): def __init__(self): self.n = 0 From 7908d87902d0e89faa674eb9383c6ecb00e10f6f Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Thu, 31 Jan 2013 15:58:14 -0500 Subject: [PATCH 21/27] more tests for views.py --- .../contentstore/tests/test_views.py | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index 9fa16ad4b2..d5a15a10e3 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -6,6 +6,7 @@ import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest from collections import defaultdict +import re from django.http import Http404, HttpResponse, HttpRequest, HttpResponseRedirect, HttpResponseBadRequest from django.conf import settings @@ -24,6 +25,7 @@ from xmodule.modulestore import Location from xmodule.x_module import ModuleSystem from xmodule.error_module import ErrorModule from contentstore.utils import get_course_for_item +from xmodule.templates import update_templates class Stub(): pass @@ -50,12 +52,14 @@ TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) class ViewsTestCase(TestCase): def setUp(self): - #modulestore().collection.drop() + self._MODULESTORES = {} + modulestore().collection.drop() + update_templates() self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] # empty Modulestore - self._MODULESTORES = {} + self.course_id = 'edX/toy/2012_Fall' self.course_id_2 = 'edx/full/6.002_Spring_2012' # is a CourseDescriptor object? @@ -210,6 +214,7 @@ class ViewsTestCase(TestCase): self.assertEquals(s.children[0].n, 1) def test_get_module_previews(self): + raise SkipTest # needs a working render_to_string raise SkipTest self.request = RequestFactory().get('foo') @@ -218,6 +223,7 @@ class ViewsTestCase(TestCase): print views.get_module_previews(self.request, self.course) def test_delete_item(self): + raise SkipTest # If user doesn't have permission, redirect self.no_permit_user = MagicMock(is_staff = False, is_active = False) self.no_permit_user.is_authenticated.return_value = True @@ -297,7 +303,7 @@ class ViewsTestCase(TestCase): self.assertIsInstance(views.save_item(self.request_3), HttpResponse) self.assertEquals(modulestore().get_item(self.item_2.location.dict()).definition['data'], {u'foo': u'bar'}) - # Test metadata, which is a dictionary? + # Test updating metadata self.request_4 = RequestFactory().post(self.item_2.location.url()) self.request_4.POST = self.request.POST.copy() self.request_4.POST.update({'id':self.item_2.location.url(), @@ -306,7 +312,25 @@ class ViewsTestCase(TestCase): self.assertIsInstance(views.save_item(self.request_4), HttpResponse) self.assertEquals(modulestore().get_item(self.item_2.location.dict()).metadata['foo'], 'bar') - + + def test_clone_item(self): + # Test that user with no permissions gets redirected + self.no_permit_user = MagicMock(is_staff = False, is_active = False) + self.no_permit_user.is_authenticated.return_value = True + self.request = RequestFactory().post(self.item.location.url()) + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':self.item.location.url(), + 'parent_location':self.course.location.url(), + 'template':self.location_3, + 'display_name':'bar'}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.clone_item, self.request) + self.permit_user = MagicMock(is_staff = True, is_active = True) + self.permit_user.is_authenticated.return_value = True + self.request.user = self.permit_user + response = views.clone_item(self.request) + self.assertIsInstance(response, HttpResponse) + self.assertRegexpMatches(response.content, '{"id": "i4x://MITx/999/course/') def f(x): x.n += 1 From c144b2519a6cad068e88df0f4c50e0937d036b59 Mon Sep 17 00:00:00 2001 From: Deena Wang Date: Fri, 1 Feb 2013 15:57:11 -0500 Subject: [PATCH 22/27] more tests in test_views.py --- .../contentstore/tests/factories.py | 53 ++- .../contentstore/tests/test_views.py | 369 +++++++++++++++++- 2 files changed, 401 insertions(+), 21 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/factories.py b/cms/djangoapps/contentstore/tests/factories.py index cb9f451d38..ab83c52438 100644 --- a/cms/djangoapps/contentstore/tests/factories.py +++ b/cms/djangoapps/contentstore/tests/factories.py @@ -1,10 +1,17 @@ from factory import Factory -from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore +from datetime import datetime +import uuid from time import gmtime from uuid import uuid4 -from xmodule.timeparse import stringify_time +from django.contrib.auth.models import Group + +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore +from xmodule.timeparse import stringify_time +from student.models import (User, UserProfile, Registration, + CourseEnrollmentAllowed) +from django.contrib.auth.models import Group def XMODULE_COURSE_CREATION(class_to_create, **kwargs): return XModuleCourseFactory._create(class_to_create, **kwargs) @@ -114,4 +121,42 @@ class ItemFactory(XModuleItemFactory): parent_location = 'i4x://MITx/999/course/Robot_Super_Course' template = 'i4x://edx/templates/chapter/Empty' - display_name = 'Section One' \ No newline at end of file + display_name = 'Section One' + +class UserProfileFactory(Factory): + FACTORY_FOR = UserProfile + + user = None + name = 'Robot Studio' + courseware = 'course.xml' + +class RegistrationFactory(Factory): + FACTORY_FOR = Registration + + user = None + activation_key = uuid.uuid4().hex + +class UserFactory(Factory): + FACTORY_FOR = User + + username = 'robot' + email = 'robot@edx.org' + password = 'test' + first_name = 'Robot' + last_name = 'Tester' + is_staff = False + is_active = True + is_superuser = False + last_login = datetime.now() + date_joined = datetime.now() + +class GroupFactory(Factory): + FACTORY_FOR = Group + + name = 'test_group' + +class CourseEnrollmentAllowedFactory(Factory): + FACTORY_FOR = CourseEnrollmentAllowed + + email = 'test@edx.org' + course_id = 'edX/test/2012_Fall' diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py index ae6548bd9d..f4f7fcd964 100644 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ b/cms/djangoapps/contentstore/tests/test_views.py @@ -5,19 +5,32 @@ import factory import unittest from nose.tools import set_trace from nose.plugins.skip import SkipTest +from collections import defaultdict +import re -from django.http import Http404, HttpResponse, HttpRequest +from django.http import (Http404, HttpResponse, HttpRequest, + HttpResponseRedirect, HttpResponseBadRequest, + HttpResponseForbidden) from django.conf import settings from django.contrib.auth.models import User -from django.test.client import Client -from django.conf import settings +from django.test.client import Client, RequestFactory from django.test import TestCase -from django.test.client import RequestFactory +from django.core.exceptions import PermissionDenied from override_settings import override_settings from xmodule.modulestore.django import modulestore, _MODULESTORES +from xmodule.modulestore import Location +from xmodule.x_module import ModuleSystem +from xmodule.error_module import ErrorModule +from xmodule.seq_module import SequenceModule +from xmodule.templates import update_templates +from contentstore.utils import get_course_for_item +from contentstore.tests.factories import UserFactory +from contentstore.tests.factories import CourseFactory, ItemFactory import contentstore.views as views +class Stub(): + pass def xml_store_config(data_dir): return { @@ -30,25 +43,347 @@ def xml_store_config(data_dir): } } -class UserFactory(factory.Factory): - first_name = 'Test' - last_name = 'Robot' - is_staff = True - is_active = True - TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class ViewsTestCase(TestCase): def setUp(self): - self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + # empty Modulestore self._MODULESTORES = {} + modulestore().collection.drop() + update_templates() + self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] + self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] + self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] self.course_id = 'edX/toy/2012_Fall' - self.toy_course = modulestore().get_course(self.course_id) + self.course_id_2 = 'edx/full/6.002_Spring_2012' + # is a CourseDescriptor object? + self.course = CourseFactory.create() + # is a sequence descriptor + self.item = ItemFactory.create(template = 'i4x://edx/templates/sequential/Empty') + self.no_permit_user = UserFactory() + self.permit_user = UserFactory(is_staff = True, username = 'Wizardly Herbert') + def tearDown(self): + _MODULESTORES = {} + modulestore().collection.drop() + assert False + def test_has_access(self): - user = UserFactory() - user.is_authenticated = True - set_trace() - self.assertTrue(views.has_access(user, self.location)) + self.assertTrue(views.has_access(self.permit_user, self.location_2)) + self.assertFalse(views.has_access(self.no_permit_user, self.location_2)) + # done + + def test_course_index(self): + request = RequestFactory().get('foo') + request.user = self.no_permit_user + # Redirects if request.user doesn't have access to location + self.assertRaises(PermissionDenied, views.course_index, request, 'edX', + 'full', '6.002_Spring_2012') + request_2 = RequestFactory().get('foo') + request.user = self.permit_user + # Doesn't work unless we figure out render_to_response +## views.course_index(request_2, 'MITx', +## '999', 'Robot_Super_Course') + + def test_edit_subsection(self): + # Redirects if request.user doesn't have access to location + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.edit_subsection, self.request, + self.location_2) + # If location isn't for a "sequential", return Bad Request + self.request_2 = RequestFactory().get('foo') + self.request_2.user = self.permit_user + self.assertIsInstance(views.edit_subsection(self.request_2, + self.location_3), HttpResponseBadRequest) + # Need render_to_response + #views.edit_subsection(self.request_2, self.item.location) + + def test_edit_unit(self): + raise SkipTest + # if user doesn't have access, should redirect + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.edit_unit, self.request, + self.location_2) + self.request_2 = RequestFactory().get('foo') + self.request_2.user = self.permit_user + # Problem: no parent locations, so IndexError + #print modulestore().get_parent_locations(self.location_3, None) + views.edit_unit(self.request_2, self.location_3) + # Needs render_to_response + + def test_assignment_type_update(self): + raise SkipTest + # If user doesn't have access, should return HttpResponseForbidden() + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.assertIsInstance(views.assignment_type_update(self.request, + 'MITx', '999', 'course', 'Robot_Super_Course'), + HttpResponseForbidden) +## views.assignment_type_update(self.request, 'MITx', '999', 'course', 'Robot_Super_Course') + # if user has access, then should return HttpResponse + self.request.user = self.permit_user + get_response = views.assignment_type_update(self.request,'MITx', '999', + 'course', 'Robot_Super_Course') + self.assertIsInstance(get_response,HttpResponse) + get_response_string = '{"id": 99, "location": ["i4x", "MITx", "999", "course", "Robot_Super_Course", null], "graderType": "Not Graded"}' + self.assertEquals(get_response.content, get_response_string) + self.request_2 = RequestFactory().post('foo') + self.request_2.user = self.permit_user + post_response = views.assignment_type_update(self.request_2,'MITx', '999', + 'course', 'Robot_Super_Course') + self.assertIsInstance(post_response,HttpResponse) + self.assertEquals(post_response.content, 'null') + + def test_load_preview_state(self): + # Tests that function creates empty defaultdict when request.session + # is empty + # location cannot be a list or other mutable type + self.request = RequestFactory().get('foo') + self.request.session = {} + instance_state, shared_state = views.load_preview_state(self.request, + 'foo', 'bar') + self.assertIsNone(instance_state) + self.assertIsNone(shared_state) + # Done + + def test_save_preview_state(self): + self.request = RequestFactory().get('foo') + self.request.session = {} + loc = Location(self.location_3) + result = {'preview_states': + {('id', loc):{'instance':None, + 'shared':None, + } + } + } + views.save_preview_state(self.request, 'id', loc, None, None) + self.assertEquals(self.request.session, result) + # Done + + def test_get_preview_module(self): + self.request = RequestFactory().get('foo') + self.request.user = self.permit_user + self.request.session = {} + module = views.get_preview_module(self.request, 'id', self.course) + self.assertIsInstance(module, SequenceModule) + # Done + + def test_preview_module_system(self): + # Returns a ModuleSystem + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.assertIsInstance(views.preview_module_system(self.request, + 'id', self.course), + ModuleSystem) + # done + + def test_load_preview_module(self): + # if error in getting module, return ErrorModule + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.request.session = {} + self.assertIsInstance(views.load_preview_module(self.request, 'id', + self.course, 'instance', 'shared'), + ErrorModule) + instance_state, shared_state = self.course.get_sample_state()[0] + module = views.load_preview_module(self.request,'id', self.course, + instance_state, shared_state) + self.assertIsInstance(module, SequenceModule) + # I'd like to test module.get_html, but it relies on render_to_string + # Test static_tab + self.course_2 = CourseFactory(display_name = 'Intro_to_intros', location = Location('i4x', 'MITx', '666', 'static_tab', 'Intro_to_intros')) + module_2 = views.load_preview_module(self.request,'id', self.course_2, + instance_state, shared_state) + self.assertIsInstance(module, SequenceModule) + # needs render_to_string + + def test__xmodule_recurse(self): + #There shouldn't be a difference, but the code works with defined + # function f but not with lambda functions + mock_item = MagicMock() + mock_item.get_children.return_value = [] + s = Stub() + s.children.append(Stub()) + views._xmodule_recurse(s, f) + self.assertEquals(s.n, 1) + self.assertEquals(s.children[0].n, 1) + + def test_get_module_previews(self): + raise SkipTest + # needs a working render_to_string + self.request = RequestFactory().get('foo') + self.request.user = UserFactory() + self.request.session = {} + print views.get_module_previews(self.request, self.course) + + def test_delete_item(self): + raise SkipTest + # If user doesn't have permission, redirect + self.request = RequestFactory().post('i4x://MITx/999/course/Robot_Super_Course') + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':'i4x://MITx/999/course/Robot_Super_Course'}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.delete_item, self.request) + # Should return an HttpResponse + self.request_2 = RequestFactory().post(self.item.location.url()) + self.request_2.POST = self.request_2.POST.copy() + self.request_2.POST.update({'id':self.item.location.url()}) + self.request_2.user = self.permit_user + response = views.delete_item(self.request_2) + self.assertIsInstance(response, HttpResponse) + self.assertEquals(modulestore().get_items(self.item.location.url()), []) + # Set delete_children to True to delete all children + # Create children + self.item_2 = ItemFactory.create() + child_item = ItemFactory.create() +## print type(self.item_2) +## print self.item_2.__dict__ + # Is there better way of adding children? What format are children in? + self.item_2.definition['children'] = [child_item.location.url()] + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request_3.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_3.user = self.permit_user + print self.item_2.get_children() + self.assertIsInstance(views.delete_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_2.location.url()), []) + # Problem: Function doesn't delete child item? + # child_item can be manually deleted, but can't delete it using function + # Not sure if problem with _xmodule_recurse and lambda functions + #store = views.get_modulestore(child_item.location.url()) + #store.delete_item(child_item.location) + self.assertEquals(modulestore().get_items(child_item.location.url()), []) + + # Check delete_item on 'vertical' + self.item_3 = ItemFactory.create(template = 'i4x://edx/templates/vertical/Empty') + self.request_4 = RequestFactory().post(self.item_3.location.url()) + self.request_4.POST = self.request_4.POST.copy() + self.request_4.POST.update({'id':self.item_3.location.url(), + 'delete_children':True, + 'delete_all_versions':True}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.delete_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_items(self.item_3.location.url()), []) + + def test_save_item(self): + # Test that user with no permissions gets redirected + self.request = RequestFactory().post(self.item.location.url()) + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':self.item.location.url()}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.save_item, self.request) + # Test user with permissions but nothing in request.POST + self.item_2 = ItemFactory.create() + self.request_2 = RequestFactory().post(self.item_2.location.url()) + self.request_2.POST = self.request.POST.copy() + self.request_2.POST.update({'id':self.item_2.location.url()}) + self.request_2.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_2), HttpResponse) + # Test updating data + self.request_3 = RequestFactory().post(self.item_2.location.url()) + self.request_3.POST = self.request.POST.copy() + self.request_3.POST.update({'id':self.item_2.location.url(), + 'data':{'foo':'bar'}}) + self.request_3.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_3), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).definition['data'], + {u'foo': u'bar'}) + # Test updating metadata + self.request_4 = RequestFactory().post(self.item_2.location.url()) + self.request_4.POST = self.request.POST.copy() + self.request_4.POST.update({'id':self.item_2.location.url(), + 'metadata':{'foo':'bar'}}) + self.request_4.user = self.permit_user + self.assertIsInstance(views.save_item(self.request_4), HttpResponse) + self.assertEquals(modulestore().get_item(self.item_2.location.dict()).metadata['foo'], + 'bar') + #done + + def test_clone_item(self): + # Test that user with no permissions gets redirected + self.request = RequestFactory().post(self.item.location.url()) + self.request.POST = self.request.POST.copy() + self.request.POST.update({'id':self.item.location.url(), + 'parent_location':self.course.location.url(), + 'template':self.location_3, + 'display_name':'bar'}) + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.clone_item, self.request) + self.request.user = self.permit_user + response = views.clone_item(self.request) + self.assertIsInstance(response, HttpResponse) + self.assertRegexpMatches(response.content, '{"id": "i4x://MITx/999/course/') + # Done + + def test_upload_asset(self): + # Test get request + self.request = RequestFactory().get('foo') + self.assertIsInstance(views.upload_asset(self.request,'org', 'course', + 'coursename'), HttpResponseBadRequest) + # Test no permissions + self.request_2 = RequestFactory().post('foo') + self.request_2.user = self.no_permit_user + self.assertIsInstance(views.upload_asset(self.request_2, 'MITx', '999', + 'Robot_Super_Course'), HttpResponseForbidden) + # Test if course exists + + self.request_3 = RequestFactory().post('foo') + self.request_3.user = self.permit_user + # Throws error because of improperly formatted log +## self.assertIsInstance(views.upload_asset(self.request_3,'org', 'course', +## 'coursename'),HttpResponseBadRequest) + # Test response with fake file attached + # Not sure how to create fake file for testing purposes because + # can't override request.FILES +## print self.request_3.FILES +## print type(self.request_3.FILES) +## f = open('file.txt') +## self.request_4 = RequestFactory().post('foo', f) +## print self.request_3.FILES +## mock_file = MagicMock(name = 'Secrets', content_type = 'foo') +## mock_file.read.return_value = 'stuff' +## file_dict = {'file':mock_file} +## self.request_3.FILES = file_dict +## print views.upload_asset(self.request_3, 'MITx', '999', +## 'Robot_Super_Course') + + def test_manage_users(self): + self.request = RequestFactory().get('foo') + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.manage_users, self.request, + self.location_3) + # Needs render_to_response + + def test_create_json_response(self): + ok_response = views.create_json_response() + self.assertIsInstance(ok_response, HttpResponse) + self.assertEquals(ok_response.content, '{"Status": "OK"}') + bad_response = views.create_json_response('Spacetime collapsing') + self.assertIsInstance(bad_response, HttpResponse) + self.assertEquals(bad_response.content, '{"Status": "Failed", "ErrMsg": "Spacetime collapsing"}') + + def test_reorder_static_tabs(self): + self.request = RequestFactory().get('foo') + self.request.POST = {'tabs':[self.location_3]} + self.request.user = self.no_permit_user + self.assertRaises(PermissionDenied, views.reorder_static_tabs, self.request) + self.request.user = self.permit_user + self.assertIsInstance(views.reorder_static_tabs(self.request), + HttpResponseBadRequest) + # to be continued ... + +def f(x): + x.n += 1 + +class Stub(): + def __init__(self): + self.n = 0 + self.children = [] + def get_children(self): + return self.children + From faf5c3f0a2e3927637285abb4e5bc8c9a16365d8 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Tue, 5 Mar 2013 09:10:02 -0500 Subject: [PATCH 23/27] Updated Deena's tests after merge with master to ensure that none of the tests fail. Deleted some tests. --- .../contentstore/tests/factories.py | 150 ------ .../contentstore/tests/test_views.py | 447 ------------------ .../courseware/tests/test_course_creation.py | 61 --- .../courseware/tests/test_module_render.py | 26 +- .../courseware/tests/test_progress.py | 8 - lms/djangoapps/courseware/tests/test_views.py | 73 --- 6 files changed, 1 insertion(+), 764 deletions(-) delete mode 100644 cms/djangoapps/contentstore/tests/factories.py delete mode 100644 cms/djangoapps/contentstore/tests/test_views.py delete mode 100644 lms/djangoapps/courseware/tests/test_course_creation.py diff --git a/cms/djangoapps/contentstore/tests/factories.py b/cms/djangoapps/contentstore/tests/factories.py deleted file mode 100644 index cb01cb447e..0000000000 --- a/cms/djangoapps/contentstore/tests/factories.py +++ /dev/null @@ -1,150 +0,0 @@ -from factory import Factory -from datetime import datetime -from uuid import uuid4 -from student.models import (User, UserProfile, Registration, - CourseEnrollmentAllowed) -from django.contrib.auth.models import Group - -from django.contrib.auth.models import Group - -from xmodule.modulestore import Location -from xmodule.modulestore.django import modulestore -from xmodule.timeparse import stringify_time -from student.models import (User, UserProfile, Registration, - CourseEnrollmentAllowed) -from django.contrib.auth.models import Group - -class UserProfileFactory(Factory): - FACTORY_FOR = UserProfile - - user = None - name = 'Robot Studio' - courseware = 'course.xml' - - -class RegistrationFactory(Factory): - FACTORY_FOR = Registration - - user = None - activation_key = uuid4().hex - - -class UserFactory(Factory): - FACTORY_FOR = User - - username = 'robot' - email = 'robot@edx.org' - password = 'test' - first_name = 'Robot' - last_name = 'Tester' - is_staff = False - is_active = True - is_superuser = False - last_login = datetime.now() - date_joined = datetime.now() - - -class GroupFactory(Factory): - FACTORY_FOR = Group - - name = 'test_group' - - -class CourseEnrollmentAllowedFactory(Factory): - FACTORY_FOR = CourseEnrollmentAllowed - -class CourseFactory(XModuleCourseFactory): - FACTORY_FOR = Course - - template = 'i4x://edx/templates/course/Empty' - org = 'MITx' - number = '999' - display_name = 'Robot Super Course' - -class XModuleItemFactory(Factory): - """ - Factory for XModule items. - """ - - ABSTRACT_FACTORY = True - _creation_function = (XMODULE_ITEM_CREATION,) - - @classmethod - def _create(cls, target_class, *args, **kwargs): - """ - kwargs must include parent_location, template. Can contain display_name - target_class is ignored - """ - - DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info'] - - parent_location = Location(kwargs.get('parent_location')) - template = Location(kwargs.get('template')) - display_name = kwargs.get('display_name') - - store = modulestore('direct') - - # This code was based off that in cms/djangoapps/contentstore/views.py - parent = store.get_item(parent_location) - dest_location = parent_location._replace(category=template.category, name=uuid4().hex) - - new_item = store.clone_item(template, dest_location) - - # TODO: This needs to be deleted when we have proper storage for static content - new_item.metadata['data_dir'] = parent.metadata['data_dir'] - - # replace the display name with an optional parameter passed in from the caller - if display_name is not None: - new_item.metadata['display_name'] = display_name - - store.update_metadata(new_item.location.url(), new_item.own_metadata) - - if new_item.location.category not in DETACHED_CATEGORIES: - store.update_children(parent_location, parent.definition.get('children', []) + [new_item.location.url()]) - - return new_item - -class Item: - pass - -class ItemFactory(XModuleItemFactory): - FACTORY_FOR = Item - - parent_location = 'i4x://MITx/999/course/Robot_Super_Course' - template = 'i4x://edx/templates/chapter/Empty' - display_name = 'Section One' - -class UserProfileFactory(Factory): - FACTORY_FOR = UserProfile - - user = None - name = 'Robot Studio' - courseware = 'course.xml' - -class RegistrationFactory(Factory): - FACTORY_FOR = Registration - - user = None - activation_key = uuid.uuid4().hex - -class UserFactory(Factory): - FACTORY_FOR = User - - username = 'robot' - email = 'robot@edx.org' - password = 'test' - first_name = 'Robot' - last_name = 'Tester' - is_staff = False - is_active = True - is_superuser = False - last_login = datetime.now() - date_joined = datetime.now() - -class GroupFactory(Factory): - FACTORY_FOR = Group - - name = 'test_group' - -class CourseEnrollmentAllowedFactory(Factory): - FACTORY_FOR = CourseEnrollmentAllowed diff --git a/cms/djangoapps/contentstore/tests/test_views.py b/cms/djangoapps/contentstore/tests/test_views.py deleted file mode 100644 index 85f960e7d5..0000000000 --- a/cms/djangoapps/contentstore/tests/test_views.py +++ /dev/null @@ -1,447 +0,0 @@ -import logging -from mock import MagicMock, patch -import json -import factory -import unittest -from nose.tools import set_trace -from nose.plugins.skip import SkipTest -from collections import defaultdict -import re - -from django.http import (Http404, HttpResponse, HttpRequest, - HttpResponseRedirect, HttpResponseBadRequest, - HttpResponseForbidden) -from django.conf import settings -from django.contrib.auth.models import User -from django.test.client import Client, RequestFactory -from django.test import TestCase -from django.core.exceptions import PermissionDenied -from override_settings import override_settings -from django.core.exceptions import PermissionDenied - -from xmodule.modulestore.django import modulestore, _MODULESTORES -from xmodule.modulestore import Location -from xmodule.x_module import ModuleSystem -from xmodule.error_module import ErrorModule -from xmodule.seq_module import SequenceModule -from xmodule.templates import update_templates -from contentstore.utils import get_course_for_item -from contentstore.tests.factories import UserFactory -from contentstore.tests.factories import CourseFactory, ItemFactory -import contentstore.views as views -from contentstore.tests.factories import CourseFactory, ItemFactory -from xmodule.modulestore import Location -from xmodule.x_module import ModuleSystem -from xmodule.error_module import ErrorModule -from contentstore.utils import get_course_for_item -from xmodule.templates import update_templates - -class Stub(): - pass - -def xml_store_config(data_dir): - return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', - } - } -} - -TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) - -class ViewsTestCase(TestCase): - def setUp(self): - # empty Modulestore - self._MODULESTORES = {} - modulestore().collection.drop() - update_templates() - self.location = ['i4x', 'edX', 'toy', 'chapter', 'Overview'] - self.location_2 = ['i4x', 'edX', 'full', 'course', '6.002_Spring_2012'] - self.location_3 = ['i4x', 'MITx', '999', 'course', 'Robot_Super_Course'] - self.course_id = 'edX/toy/2012_Fall' - self.course_id_2 = 'edx/full/6.002_Spring_2012' - # is a CourseDescriptor object? - self.course = CourseFactory.create() - # is a sequence descriptor - self.item = ItemFactory.create(template = 'i4x://edx/templates/sequential/Empty') - self.no_permit_user = UserFactory() - self.permit_user = UserFactory(is_staff = True, username = 'Wizardly Herbert') - - def tearDown(self): - _MODULESTORES = {} - modulestore().collection.drop() - - def test_has_access(self): - self.assertTrue(views.has_access(self.permit_user, self.location_2)) - self.assertFalse(views.has_access(self.no_permit_user, self.location_2)) - # done - - def test_course_index(self): - request = RequestFactory().get('foo') - request.user = self.no_permit_user - # Redirects if request.user doesn't have access to location - self.assertRaises(PermissionDenied, views.course_index, request, 'edX', - 'full', '6.002_Spring_2012') - request_2 = RequestFactory().get('foo') - request.user = self.permit_user - - def test_has_access(self): - user = MagicMock(is_staff = True, is_active = True, is_authenticated = True) - m = MagicMock() - m.count.return_value = 1 - user.groups.filter.return_value = m - self.assertTrue(views.has_access(user, self.location_2)) - user.is_authenticated = False - self.assertFalse(views.has_access(user, self.location_2)) - - def test_course_index(self): - # UserFactory doesn't work? - self.user = MagicMock(is_staff = False, is_active = False) - self.user.is_authenticated.return_value = False - request = MagicMock(user = self.user) - # Redirects if request.user doesn't have access to location - self.assertIsInstance(views.course_index(request, 'edX', - 'full', '6.002_Spring_2012'), HttpResponseRedirect) - self.user_2 = MagicMock(is_staff = True, is_active = True) - self.user_2.is_authenticated.return_value = True - request_2 = MagicMock(user = self.user_2) - # Doesn't work unless we figure out render_to_response -## views.course_index(request_2, 'MITx', -## '999', 'Robot_Super_Course') - - def test_edit_subsection(self): - # Redirects if request.user doesn't have access to location - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.edit_subsection, self.request, - self.location_2) - # If location isn't for a "sequential", return Bad Request - self.request_2 = RequestFactory().get('foo') - self.request_2.user = self.permit_user - self.user = MagicMock(is_staff = False, is_active = False) - self.user.is_authenticated.return_value = False - self.request = MagicMock(user = self.user) - self.assertIsInstance(views.edit_subsection(self.request, self.location_2), - HttpResponseRedirect) - # If location isn't for a "sequential", return Bad Request - self.user_2 = MagicMock(is_staff = True, is_active = True) - self.user_2.is_authenticated.return_value = True - self.request_2 = MagicMock(user = self.user_2) - self.assertIsInstance(views.edit_subsection(self.request_2, - self.location_3), HttpResponseBadRequest) - # Need render_to_response - #views.edit_subsection(self.request_2, self.item.location) - - def test_edit_unit(self): - raise SkipTest - # if user doesn't have access, should redirect - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.edit_unit, self.request, - self.location_2) - self.request_2 = RequestFactory().get('foo') - self.request_2.user = self.permit_user - # Problem: no parent locations, so IndexError - #print modulestore().get_parent_locations(self.location_3, None) - views.edit_unit(self.request_2, self.location_3) - # Needs render_to_response - - def test_assignment_type_update(self): - raise SkipTest - # If user doesn't have access, should return HttpResponseForbidden() - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertIsInstance(views.assignment_type_update(self.request, - 'MITx', '999', 'course', 'Robot_Super_Course'), - HttpResponseForbidden) -## views.assignment_type_update(self.request, 'MITx', '999', 'course', 'Robot_Super_Course') - # if user has access, then should return HttpResponse - self.request.user = self.permit_user - # if user doesn't have access, should redirect - self.user = MagicMock(is_staff = False, is_active = False) - self.user.is_authenticated.return_value = False - self.request = MagicMock(user = self.user) - self.assertIsInstance(views.edit_unit(self.request, self.location_2), - HttpResponseRedirect) - - def test_assignment_type_update(self): - # If user doesn't have access, should redirect - self.user = MagicMock(is_staff = False, is_active = False) - self.user.is_authenticated.return_value = False - self.request = RequestFactory().get('foo') - self.request.user = self.user - self.assertIsInstance(views.assignment_type_update(self.request, - 'MITx', '999', 'course', 'Robot_Super_Course'), - HttpResponseRedirect) - # if user has access, then should return HttpResponse - self.user_2 = MagicMock(is_staff = True, is_active = True) - self.user_2.is_authenticated.return_value = True - self.request.user = self.user_2 - get_response = views.assignment_type_update(self.request,'MITx', '999', - 'course', 'Robot_Super_Course') - self.assertIsInstance(get_response,HttpResponse) - get_response_string = '{"id": 99, "location": ["i4x", "MITx", "999", "course", "Robot_Super_Course", null], "graderType": "Not Graded"}' - self.assertEquals(get_response.content, get_response_string) - self.request_2 = RequestFactory().post('foo') - self.request_2.user = self.permit_user - post_response = views.assignment_type_update(self.request_2,'MITx', '999', - 'course', 'Robot_Super_Course') - self.assertIsInstance(post_response,HttpResponse) - self.assertEquals(post_response.content, 'null') - - def test_load_preview_state(self): - # Tests that function creates empty defaultdict when request.session - # is empty - # location cannot be a list or other mutable type - self.request = RequestFactory().get('foo') - self.request.session = {} - instance_state, shared_state = views.load_preview_state(self.request, - 'foo', 'bar') - self.assertIsNone(instance_state) - self.assertIsNone(shared_state) - # Done - - def test_save_preview_state(self): - self.request = RequestFactory().get('foo') - self.request.session = {} - loc = Location(self.location_3) - result = {'preview_states': - {('id', loc):{'instance':None, - 'shared':None, - } - } - } - views.save_preview_state(self.request, 'id', loc, None, None) - self.assertEquals(self.request.session, result) - # Done - - def test_get_preview_module(self): - self.request = RequestFactory().get('foo') - self.request.user = self.permit_user - self.request.session = {} - module = views.get_preview_module(self.request, 'id', self.course) - self.assertIsInstance(module, SequenceModule) - # Done - - def test_preview_module_system(self): - # Returns a ModuleSystem - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertIsInstance(views.preview_module_system(self.request, - 'id', self.course), - ModuleSystem) - # done - - def test_load_preview_module(self): - # if error in getting module, return ErrorModule - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertIsInstance(views.preview_module_system(self.request, - 'id', self.course), - ModuleSystem) - self.request.session = {} - self.assertIsInstance(views.load_preview_module(self.request, 'id', - self.course, 'instance', 'shared'), - ErrorModule) - instance_state, shared_state = self.course.get_sample_state()[0] - module = views.load_preview_module(self.request,'id', self.course, - instance_state, shared_state) - self.assertIsInstance(module, SequenceModule) - # I'd like to test module.get_html, but it relies on render_to_string - # Test static_tab - self.course_2 = CourseFactory(display_name = 'Intro_to_intros', location = Location('i4x', 'MITx', '666', 'static_tab', 'Intro_to_intros')) - module_2 = views.load_preview_module(self.request,'id', self.course_2, - instance_state, shared_state) - self.assertIsInstance(module, SequenceModule) - # needs render_to_string - - def test__xmodule_recurse(self): - #There shouldn't be a difference, but the code works with defined - # function f but not with lambda functions - mock_item = MagicMock() - mock_item.get_children.return_value = [] - s = Stub() - s.children.append(Stub()) - views._xmodule_recurse(s, f) - self.assertEquals(s.n, 1) - self.assertEquals(s.children[0].n, 1) - - def test_get_module_previews(self): - raise SkipTest - # needs a working render_to_string - self.request = RequestFactory().get('foo') - self.request.user = UserFactory() - self.request.session = {} - print views.get_module_previews(self.request, self.course) - - def test_delete_item(self): - raise SkipTest - # If user doesn't have permission, redirect - self.request = RequestFactory().post('i4x://MITx/999/course/Robot_Super_Course') - self.request.POST = self.request.POST.copy() - self.request.POST.update({'id':'i4x://MITx/999/course/Robot_Super_Course'}) - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.delete_item, self.request) - # Should return an HttpResponse - self.request_2 = RequestFactory().post(self.item.location.url()) - self.request_2.POST = self.request_2.POST.copy() - self.request_2.POST.update({'id':self.item.location.url()}) - self.request_2.user = self.permit_user - response = views.delete_item(self.request_2) - self.assertIsInstance(response, HttpResponse) - self.assertEquals(modulestore().get_items(self.item.location.url()), []) - # Set delete_children to True to delete all children - # Create children - self.item_2 = ItemFactory.create() - child_item = ItemFactory.create() -## print type(self.item_2) -## print self.item_2.__dict__ - # Is there better way of adding children? What format are children in? - self.item_2.definition['children'] = [child_item.location.url()] - self.request_3 = RequestFactory().post(self.item_2.location.url()) - self.request_3.POST = self.request_3.POST.copy() - self.request_3.POST.update({'id':self.item_2.location.url(), - 'delete_children':True, - 'delete_all_versions':True}) - self.request_3.user = self.permit_user - print self.item_2.get_children() - self.assertIsInstance(views.delete_item(self.request_3), HttpResponse) - self.assertEquals(modulestore().get_items(self.item_2.location.url()), []) - # Problem: Function doesn't delete child item? - # child_item can be manually deleted, but can't delete it using function - # Not sure if problem with _xmodule_recurse and lambda functions - #store = views.get_modulestore(child_item.location.url()) - #store.delete_item(child_item.location) - self.assertEquals(modulestore().get_items(child_item.location.url()), []) - # Check delete_item on 'vertical' - self.item_3 = ItemFactory.create(template = 'i4x://edx/templates/vertical/Empty') - self.request_4 = RequestFactory().post(self.item_3.location.url()) - self.request_4.POST = self.request_4.POST.copy() - self.request_4.POST.update({'id':self.item_3.location.url(), - 'delete_children':True, - 'delete_all_versions':True}) - self.request_4.user = self.permit_user - self.assertIsInstance(views.delete_item(self.request_4), HttpResponse) - self.assertEquals(modulestore().get_items(self.item_3.location.url()), []) - - def test_save_item(self): - # Test that user with no permissions gets redirected - self.request = RequestFactory().post(self.item.location.url()) - self.request.POST = self.request.POST.copy() - self.request.POST.update({'id':self.item.location.url()}) - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.save_item, self.request) - # Test user with permissions but nothing in request.POST - self.item_2 = ItemFactory.create() - self.request_2 = RequestFactory().post(self.item_2.location.url()) - self.request_2.POST = self.request.POST.copy() - self.request_2.POST.update({'id':self.item_2.location.url()}) - self.request_2.user = self.permit_user - self.assertIsInstance(views.save_item(self.request_2), HttpResponse) - # Test updating data - self.request_3 = RequestFactory().post(self.item_2.location.url()) - self.request_3.POST = self.request.POST.copy() - self.request_3.POST.update({'id':self.item_2.location.url(), - 'data':{'foo':'bar'}}) - self.request_3.user = self.permit_user - self.assertIsInstance(views.save_item(self.request_3), HttpResponse) - self.assertEquals(modulestore().get_item(self.item_2.location.dict()).definition['data'], - {u'foo': u'bar'}) - # Test updating metadata - self.request_4 = RequestFactory().post(self.item_2.location.url()) - self.request_4.POST = self.request.POST.copy() - self.request_4.POST.update({'id':self.item_2.location.url(), - 'metadata':{'foo':'bar'}}) - self.request_4.user = self.permit_user - self.assertIsInstance(views.save_item(self.request_4), HttpResponse) - self.assertEquals(modulestore().get_item(self.item_2.location.dict()).metadata['foo'], - 'bar') - #done - - def test_clone_item(self): - # Test that user with no permissions gets redirected - self.request = RequestFactory().post(self.item.location.url()) - self.request.POST = self.request.POST.copy() - self.request.POST.update({'id':self.item.location.url(), - 'parent_location':self.course.location.url(), - 'template':self.location_3, - 'display_name':'bar'}) - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.clone_item, self.request) - self.request.user = self.permit_user - response = views.clone_item(self.request) - self.assertIsInstance(response, HttpResponse) - self.assertRegexpMatches(response.content, '{"id": "i4x://MITx/999/course/') - # Done - - def test_upload_asset(self): - # Test get request - self.request = RequestFactory().get('foo') - self.assertIsInstance(views.upload_asset(self.request,'org', 'course', - 'coursename'), HttpResponseBadRequest) - # Test no permissions - self.request_2 = RequestFactory().post('foo') - self.request_2.user = self.no_permit_user - self.assertIsInstance(views.upload_asset(self.request_2, 'MITx', '999', - 'Robot_Super_Course'), HttpResponseForbidden) - # Test if course exists - - self.request_3 = RequestFactory().post('foo') - self.request_3.user = self.permit_user - # Throws error because of improperly formatted log -## self.assertIsInstance(views.upload_asset(self.request_3,'org', 'course', -## 'coursename'),HttpResponseBadRequest) - # Test response with fake file attached - # Not sure how to create fake file for testing purposes because - # can't override request.FILES -## print self.request_3.FILES -## print type(self.request_3.FILES) -## f = open('file.txt') -## self.request_4 = RequestFactory().post('foo', f) -## print self.request_3.FILES -## mock_file = MagicMock(name = 'Secrets', content_type = 'foo') -## mock_file.read.return_value = 'stuff' -## file_dict = {'file':mock_file} -## self.request_3.FILES = file_dict -## print views.upload_asset(self.request_3, 'MITx', '999', -## 'Robot_Super_Course') - - def test_manage_users(self): - self.request = RequestFactory().get('foo') - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.manage_users, self.request, - self.location_3) - # Needs render_to_response - - def test_create_json_response(self): - ok_response = views.create_json_response() - self.assertIsInstance(ok_response, HttpResponse) - self.assertEquals(ok_response.content, '{"Status": "OK"}') - bad_response = views.create_json_response('Spacetime collapsing') - self.assertIsInstance(bad_response, HttpResponse) - self.assertEquals(bad_response.content, '{"Status": "Failed", "ErrMsg": "Spacetime collapsing"}') - - def test_reorder_static_tabs(self): - self.request = RequestFactory().get('foo') - self.request.POST = {'tabs':[self.location_3]} - self.request.user = self.no_permit_user - self.assertRaises(PermissionDenied, views.reorder_static_tabs, self.request) - self.request.user = self.permit_user - self.assertIsInstance(views.reorder_static_tabs(self.request), - HttpResponseBadRequest) - # to be continued ... - -def f(x): - x.n += 1 - -class Stub(): - def __init__(self): - self.n = 0 - self.children = [] - def get_children(self): - return self.children - diff --git a/lms/djangoapps/courseware/tests/test_course_creation.py b/lms/djangoapps/courseware/tests/test_course_creation.py deleted file mode 100644 index af3e3ee0e1..0000000000 --- a/lms/djangoapps/courseware/tests/test_course_creation.py +++ /dev/null @@ -1,61 +0,0 @@ -import logging -from mock import MagicMock, patch -import factory -import copy -from path import path - -from django.test import TestCase -from django.test.client import Client -from django.core.urlresolvers import reverse -from django.conf import settings -from override_settings import override_settings - -from xmodule.modulestore.xml_importer import import_from_xml -import xmodule.modulestore.django - -TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) -TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path('common/test/data') - -@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class CreateTest(TestCase): - def setUp(self): - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) - - def check_edit_item(self, test_course_name): - import_from_xml(modulestore(), 'common/test/data/', [test_course_name]) - for descriptor in modulestore().get_items(Location(None, None, None, None, None)): - print "Checking ", descriptor.location.url() - print descriptor.__class__, descriptor.location - resp = self.client.get(reverse('edit_item'), {'id': descriptor.location.url()}) - self.assertEqual(resp.status_code, 200) - - def test_edit_item_toy(self): - self.check_edit_item('toy') - -## def setUp(self): -## self.client = Client() -## self.username = 'username' -## self.email = 'test@foo.com' -## self.pw = 'password' -## -## def create_account(self, username, email, pw): -## resp = self.client.post('/create_account', { -## 'username': username, -## 'email': email, -## 'password': pw, -## 'location': 'home', -## 'language': 'Franglish', -## 'name': 'Fred Weasley', -## 'terms_of_service': 'true', -## 'honor_code': 'true', -## }) -## return resp -## -## def registration(self, email): -## '''look up registration object by email''' -## return Registration.objects.get(user__email=email) -## -## def activate_user(self, email): -## activation_key = self.registration(email).activation_key diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index f419e6f582..d5f821e0bf 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -14,13 +14,13 @@ from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory from django.core.urlresolvers import reverse +from django.test.utils import override_settings from courseware.models import StudentModule, StudentModuleCache from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.exceptions import NotFoundError from xmodule.modulestore import Location import courseware.module_render as render -from override_settings import override_settings from xmodule.modulestore.django import modulestore, _MODULESTORES from xmodule.seq_module import SequenceModule from courseware.tests.tests import PageLoader @@ -58,35 +58,11 @@ class ModuleRenderTestCase(PageLoader): self.course_id = 'edX/toy/2012_Fall' self.toy_course = modulestore().get_course(self.course_id) - def test_toc_for_course(self): - mock_course = MagicMock() - mock_course.id = 'dummy' - mock_course.location = Location(self.location) - mock_course.get_children.return_value = [] - mock_user = MagicMock() - mock_user.is_authenticated.return_value = False - self.assertIsNone(render.toc_for_course(mock_user,'dummy', - mock_course, 'dummy', 'dummy')) - # rest of tests are in class TestTOC - def test_get_module(self): self.assertIsNone(render.get_module('dummyuser',None,\ 'invalid location',None,None)) - #done - - def test__get_module(self): - mock_user = MagicMock() - mock_user.is_authenticated.return_value = False - location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') - mock_request = MagicMock() - s = render._get_module(mock_user, mock_request, location, - 'dummy', 'edX/toy/2012_Fall') - self.assertIsInstance(s, SequenceModule) - # Don't know how to generate error in line 260 to test - # Can't tell if sequence module is an error? def test_get_instance_module(self): - # done mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertIsNone(render.get_instance_module('dummy', mock_user, 'dummy', diff --git a/lms/djangoapps/courseware/tests/test_progress.py b/lms/djangoapps/courseware/tests/test_progress.py index 480d594863..4e528f44a4 100644 --- a/lms/djangoapps/courseware/tests/test_progress.py +++ b/lms/djangoapps/courseware/tests/test_progress.py @@ -55,13 +55,5 @@ class ProgessTests(TestCase): self.c.__setitem__('questions_correct', 4) self.assertEqual(str(self.c),str(self.d)) - # def test_add(self): - # self.assertEqual(self.c.__add__(self.c2), self.cplusc2) - - def test_contains(self): - - return self.c.__contains__('meow') - #self.assertEqual(self.c.__contains__('done'), True) - def test_repr(self): self.assertEqual(self.c.__repr__(), str(progress.completion())) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index c901f87720..de4d934ee7 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -4,7 +4,6 @@ import datetime import factory import unittest import os -from nose.plugins.skip import SkipTest from django.test import TestCase from django.http import Http404, HttpResponse @@ -20,13 +19,6 @@ from xmodule.modulestore.exceptions import InvalidLocationError,\ import courseware.views as views from xmodule.modulestore import Location -def skipped(func): - from nose.plugins.skip import SkipTest - def _(): - raise SkipTest("Test %s is skipped" % func.__name__) - _.__name__ = func.__name__ - return _ - #from override_settings import override_settings class Stub(): @@ -38,13 +30,6 @@ class UserFactory(factory.Factory): is_staff = True is_active = True -def skipped(func): - from nose.plugins.skip import SkipTest - def _(): - raise SkipTest("Test %s is skipped" % func.__name__) - _.__name__ = func.__name__ - return _ - # This part is required for modulestore() to work properly def xml_store_config(data_dir): return { @@ -139,20 +124,6 @@ class ViewsTestCase(TestCase): self.assertRaises(Http404, views.redirect_to_course_position, mock_module, True) - def test_index(self): - assert SkipTest - request = self.request_factory.get(self.chapter_url) - request.user = UserFactory() - response = views.index(request, self.course_id) - self.assertIsInstance(response, HttpResponse) - self.assertEqual(response.status_code, 302) - # views.index does not throw 404 if chapter, section, or position are - # not valid, which doesn't match index's comments - views.index(request, self.course_id, chapter='foo', section='bar', - position='baz') - request_2 = self.request_factory.get(self.chapter_url) - request_2.user = self.user - response = views.index(request_2, self.course_id) def test_registered_for_course(self): self.assertFalse(views.registered_for_course('Basketweaving', None)) @@ -187,47 +158,3 @@ class ViewsTestCase(TestCase): ## request_2 = self.request_factory.get('foo') ## request_2.user = UserFactory() - def test_static_university_profile(self): - # TODO - # Can't test unless havehttp://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/ a valid template file - raise SkipTest - request = self.client.get('university_profile/edX') - self.assertIsInstance(views.static_university_profile(request, 'edX'), HttpResponse) - - def test_university_profile(self): - raise SkipTest - request = self.request_factory.get(self.chapter_url) - request.user = UserFactory() - self.assertRaisesRegexp(Http404, 'University Profile*', - views.university_profile, request, 'Harvard') - # TODO - #request_2 = self.client.get('/university_profile/edx') - self.assertIsInstance(views.university_profile(request, 'edX'), HttpResponse) - # Can't continue testing unless have valid template file - - - def test_syllabus(self): - raise SkipTest - request = self.request_factory.get(self.chapter_url) - request.user = UserFactory() - # Can't find valid template - # TODO - views.syllabus(request, 'edX/toy/2012_Fall') - - def test_render_notifications(self): - raise SkipTest - request = self.request_factory.get('foo') - #views.render_notifications(request, self.course_id, 'dummy') - # TODO - # Needs valid template - - def test_news(self): - raise SkipTest - # Bug? get_notifications is actually in lms/lib/comment_client/legacy.py - request = self.client.get('/news') - self.user.id = 'foo' - request.user = self.user - course_id = 'edX/toy/2012_Fall' - self.assertIsInstance(views.news(request, course_id), HttpResponse) - - # TODO From 437aadb28e3ce110d1f75cd0f8af79c52a6dbf32 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Tue, 5 Mar 2013 09:32:20 -0500 Subject: [PATCH 24/27] Cleaned up some tests; deleted skip tests --- .../courseware/tests/test_courses.py | 63 -------------- .../courseware/tests/test_module_render.py | 87 ------------------- lms/djangoapps/courseware/tests/test_views.py | 25 +----- 3 files changed, 1 insertion(+), 174 deletions(-) delete mode 100644 lms/djangoapps/courseware/tests/test_courses.py diff --git a/lms/djangoapps/courseware/tests/test_courses.py b/lms/djangoapps/courseware/tests/test_courses.py deleted file mode 100644 index 91b6af4dfc..0000000000 --- a/lms/djangoapps/courseware/tests/test_courses.py +++ /dev/null @@ -1,63 +0,0 @@ -from mock import MagicMock, patch -import datetime - -from django.test import TestCase -from django.contrib.auth.models import User -from django.conf import settings -from django.test.utils import override_settings - -from student.models import CourseEnrollment -import courseware.courses as courses -from xmodule.modulestore.xml import XMLModuleStore -from xmodule.modulestore.django import modulestore -from xmodule.modulestore import Location - -def xml_store_config(data_dir): - return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', - } - } -} - -TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT -TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) - -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class CoursesTestCase(TestCase): - def setUp(self): -## self.user = User.objects.create(username='dummy', password='123456', -## email='test@mit.edu') -## self.date = datetime.datetime(2013,1,22) -## self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, -## course_id = self.course_id, -## created = self.date)[0] - self._MODULESTORES = {} - #self.course_id = 'edx/toy/2012_Fall' - self.toy_course = modulestore().get_course('edX/toy/2012_Fall') - - def test_get_course_by_id(self): - courses.get_course_by_id("edX/toy/2012_Fall") - - -@override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) -class CoursesTests(TestCase): - # runs - def setUp(self): - self._MODULESTORES = {} - #self.course_id = 'edX/toy/2012_Fall' - self.toy_course = modulestore().get_course('edX/toy/2012_Fall') -## self.fake_user = User.objects.create(is_superuser=True) - - ''' - no test written for get_request_for_thread - ''' - - def test_get_course_by_id(self): - #self.test_course_id = "edX/toy/2012_Fall" - courses.get_course_by_id("edX/toy/2012_Fall") - # print modulestore().get_instance(test_course_id, Location('i4x', 'edx', 'toy', 'course', '2012_Fall')) - #self.assertEqual(courses.get_course_by_id(self.test_course_id),modulestore().get_instance(self.test_course_id, Location('i4x', 'edX', 'toy', 'course', '2012_Fall'), None)) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index d5f821e0bf..9b9b3f6d2f 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -4,7 +4,6 @@ import json import factory import unittest from nose.tools import set_trace -from nose.plugins.skip import SkipTest from django.http import Http404, HttpResponse, HttpRequest from django.conf import settings @@ -74,62 +73,6 @@ class ModuleRenderTestCase(PageLoader): self.assertIsNone(render.get_instance_module('dummy', mock_user_2, mock_module,'dummy')) - def test_get_shared_instance_module(self): - raise SkipTest - mock_user = MagicMock(User) - mock_user.is_authenticated.return_value = False - self.assertIsNone(render.get_shared_instance_module('dummy', mock_user, 'dummy', - 'dummy')) - mock_user_2 = MagicMock(User) - mock_user_2.is_authenticated.return_value = True - - mock_module = MagicMock(shared_state_key = 'key') - mock_module.location = Location('i4x', 'edX', 'toy', 'chapter', 'Overview') - mock_module.get_shared_state.return_value = '{}' - mock_cache = MagicMock() - mock_cache.lookup.return_value = False - #mock_cache._state = 'dummy' - #set_trace() - print mock_module.get_shared_state() - s = render.get_shared_instance_module(self.course_id, mock_user_2, - mock_module, mock_cache) - self.assertIsInstance(s, StudentModule) - # Problem: can't get code to take branch that creates StudentModule? - # Can't finish testing modx_dispatch - - def test_xqueue_callback(self): - mock_request = MagicMock() - mock_request.POST.copy.return_value = {} - # 339 - self.assertRaises(Http404, render.xqueue_callback,mock_request, - 'dummy', 'dummy', 'dummy', 'dummy') - mock_request_2 = MagicMock() - xpackage = {'xqueue_header': json.dumps({}), - 'xqueue_body' : 'Message from grader'} - mock_request_2.POST.copy.return_value = xpackage - # 342 - self.assertRaises(Http404, render.xqueue_callback,mock_request_2, - 'dummy', 'dummy', 'dummy', 'dummy') - mock_request_3 = MagicMock() - xpackage_2 = {'xqueue_header': json.dumps({'lms_key':'secretkey'}), - 'xqueue_body' : 'Message from grader'} - mock_request_3.POST.copy.return_value = xpackage_2 - # Roadblock: how to get user registered in class? - raise SkipTest - # - # trying alternate way of creating account in hopes of getting valid id - # Problem: Can't activate user - - self.student_name = '12' - self.password = 'foo' - self.email = 'test@mit.edu' - self.create_account(self.student_name, self.email, self.password) - self.activate_user(self.email) - request = RequestFactory().get('stuff') - # This doesn't work to install user - render.xqueue_callback(mock_request_3, self.course_id, - self.student_name, self.password, 'dummy') - def test_modx_dispatch(self): self.assertRaises(Http404, render.modx_dispatch, 'dummy', 'dummy', 'invalid Location', 'dummy') @@ -162,40 +105,10 @@ class ModuleRenderTestCase(PageLoader): mock_request_3, 'dummy', self.location, 'toy') self.assertRaises(Http404,render.modx_dispatch, mock_request_3, 'dummy', self.location, self.course_id) -## student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(self.course_id, -## mock_request_3.user, modulestore().get_instance(self.course_id, self.location)) -## get_shared_instance_module(course_id, request.user, instance, student_module_cache) - # 'goto_position' is the only dispatch that will work mock_request_3.POST.copy.return_value = {'position':1} self.assertIsInstance(render.modx_dispatch(mock_request_3, 'goto_position', self.location, self.course_id), HttpResponse) - # keep going - def test_preview_chemcalc(self): - mock_request = MagicMock(method = 'notGET') - self.assertRaises(Http404, render.preview_chemcalc, mock_request) - mock_request_2 = MagicMock(method = 'GET') - mock_request_2.GET.get.return_value = None - self.assertEquals(render.preview_chemcalc(mock_request_2).content, - json.dumps({'preview':'', - 'error':'No formula specified.'})) - - mock_request_3 = MagicMock() - mock_request_3.method = 'GET' - # Test fails because chemcalc.render_to_html always parses strings? - mock_request_3.GET.get.return_value = unicode('\x12400', errors="strict") -## self.assertEquals(render.preview_chemcalc(mock_request_3).content, -## json.dumps({'preview':'', -## 'error':"Couldn't parse formula: formula"})) -## - mock_request_3 = MagicMock() - mock_request_3.method = 'GET' - mock_request_3.GET.get.return_value = Stub() - self.assertEquals(render.preview_chemcalc(mock_request_3).content, - json.dumps({'preview':'', - 'error':"Error while rendering preview"})) - - def test_get_score_bucket(self): self.assertEquals(render.get_score_bucket(0, 10), 'incorrect') self.assertEquals(render.get_score_bucket(1, 10), 'partial') diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index de4d934ee7..76047aabda 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -19,8 +19,6 @@ from xmodule.modulestore.exceptions import InvalidLocationError,\ import courseware.views as views from xmodule.modulestore import Location -#from override_settings import override_settings - class Stub(): pass @@ -45,9 +43,6 @@ def xml_store_config(data_dir): TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) - -#class ModulestoreTest(TestCase): - @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestJumpTo(TestCase): """Check the jumpto link for a course""" @@ -134,27 +129,9 @@ class ViewsTestCase(TestCase): mock_course.id = self.course_id self.assertTrue(views.registered_for_course(mock_course, self.user)) - def test_jump_to(self): + def test_jump_to_invalid(self): request = self.request_factory.get(self.chapter_url) self.assertRaisesRegexp(Http404, 'Invalid location', views.jump_to, request, 'bar', ()) self.assertRaisesRegexp(Http404, 'No data*', views.jump_to, request, 'dummy', self.location) -## print type(self.toy_course) -## print dir(self.toy_course) -## print self.toy_course.location -## print self.toy_course.__dict__ -## valid = ['i4x', 'edX', 'toy', 'chapter', 'overview'] -## L = Location('i4x', 'edX', 'toy', 'chapter', 'Overview', None) -## -## views.jump_to(request, 'dummy', L) - - def test_static_tab(self): - request = self.request_factory.get('foo') - request.user = self.user - self.assertRaises(Http404, views.static_tab, request, 'edX/toy/2012_Fall', - 'dummy') - # What are valid tab_slugs? -## request_2 = self.request_factory.get('foo') -## request_2.user = UserFactory() - From 2fd9ccece1cb39b5234d905ae7f4ca2d4ae02aa6 Mon Sep 17 00:00:00 2001 From: Will Daly Date: Tue, 5 Mar 2013 09:34:52 -0500 Subject: [PATCH 25/27] Fixed whitespace issues; removed a test that made no assertions --- lms/djangoapps/courseware/tests/test_progress.py | 3 +-- lms/djangoapps/courseware/tests/test_views.py | 11 ----------- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_progress.py b/lms/djangoapps/courseware/tests/test_progress.py index 4e528f44a4..44a0f0cb30 100644 --- a/lms/djangoapps/courseware/tests/test_progress.py +++ b/lms/djangoapps/courseware/tests/test_progress.py @@ -30,8 +30,6 @@ class ProgessTests(TestCase): 'questions_incorrect': 1, 'questions_total': 0}) - - self.oth = dict({'duration_total': 0, 'duration_watched': 0, 'done': True, @@ -48,6 +46,7 @@ class ProgessTests(TestCase): 'questions_correct': 4, 'questions_incorrect': 0, 'questions_total': 7} + def test_getitem(self): self.assertEqual(self.c.__getitem__('duration_watched'), 0) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 76047aabda..3ff845834a 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -84,22 +84,12 @@ class ViewsTestCase(TestCase): chapter = 'Overview' self.chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter) - def test_user_groups(self): # depreciated function mock_user = MagicMock() mock_user.is_authenticated.return_value = False self.assertEquals(views.user_groups(mock_user),[]) - - @override_settings(DEBUG = True) - def test_user_groups_debug(self): - mock_user = MagicMock() - mock_user.is_authenticated.return_value = True - pass - #views.user_groups(mock_user) - #Keep going later - def test_get_current_child(self): self.assertIsNone(views.get_current_child(Stub())) mock_xmodule = MagicMock() @@ -119,7 +109,6 @@ class ViewsTestCase(TestCase): self.assertRaises(Http404, views.redirect_to_course_position, mock_module, True) - def test_registered_for_course(self): self.assertFalse(views.registered_for_course('Basketweaving', None)) mock_user = MagicMock() From cee24c5cb23bdd077f195c291d705a50ca8f977b Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 5 Mar 2013 11:18:07 -0500 Subject: [PATCH 26/27] Import existing UserFactory --- lms/djangoapps/courseware/tests/test_module_render.py | 8 ++------ lms/djangoapps/courseware/tests/test_views.py | 7 ++----- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 9b9b3f6d2f..61b70d3656 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -25,6 +25,8 @@ from xmodule.seq_module import SequenceModule from courseware.tests.tests import PageLoader from student.models import Registration +from factories import UserFactory + class Stub: def __init__(self): pass @@ -40,12 +42,6 @@ def xml_store_config(data_dir): } } -class UserFactory(factory.Factory): - first_name = 'Test' - last_name = 'Robot' - is_staff = True - is_active = True - TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 3ff845834a..cb15b5b7b6 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -19,14 +19,11 @@ from xmodule.modulestore.exceptions import InvalidLocationError,\ import courseware.views as views from xmodule.modulestore import Location +from factories import UserFactory + class Stub(): pass -class UserFactory(factory.Factory): - first_name = 'Test' - last_name = 'Robot' - is_staff = True - is_active = True # This part is required for modulestore() to work properly def xml_store_config(data_dir): From b0a018195ad78f180dc3e210e995798c9d7a1d31 Mon Sep 17 00:00:00 2001 From: Jay Zoldak Date: Tue, 5 Mar 2013 11:53:00 -0500 Subject: [PATCH 27/27] Pep8 fixes for tests --- .../courseware/tests/test_access.py | 11 +- .../courseware/tests/test_module_render.py | 97 +++++++++-------- .../courseware/tests/test_progress.py | 87 ++++++++------- lms/djangoapps/courseware/tests/test_views.py | 31 +++--- lms/djangoapps/courseware/tests/tests.py | 101 ++++++++---------- 5 files changed, 158 insertions(+), 169 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_access.py b/lms/djangoapps/courseware/tests/test_access.py index 0b32da17a4..acb05d5d78 100644 --- a/lms/djangoapps/courseware/tests/test_access.py +++ b/lms/djangoapps/courseware/tests/test_access.py @@ -1,21 +1,20 @@ import unittest -import logging +import logging import time from mock import Mock, MagicMock, patch from django.conf import settings from django.test import TestCase -from xmodule.course_module import CourseDescriptor -from xmodule.error_module import ErrorDescriptor -from xmodule.modulestore import Location -from xmodule.timeparse import parse_time +from xmodule.course_module import CourseDescriptor +from xmodule.error_module import ErrorDescriptor +from xmodule.modulestore import Location +from xmodule.timeparse import parse_time from xmodule.x_module import XModule, XModuleDescriptor import courseware.access as access from factories import CourseEnrollmentAllowedFactory - class AccessTestCase(TestCase): def test__has_global_staff_access(self): u = Mock(is_staff=False) diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 61b70d3656..81f95a85e4 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -12,39 +12,42 @@ from django.test.client import Client from django.conf import settings from django.test import TestCase from django.test.client import RequestFactory -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse from django.test.utils import override_settings -from courseware.models import StudentModule, StudentModuleCache +from courseware.models import StudentModule, StudentModuleCache from xmodule.modulestore.exceptions import ItemNotFoundError -from xmodule.exceptions import NotFoundError +from xmodule.exceptions import NotFoundError from xmodule.modulestore import Location import courseware.module_render as render from xmodule.modulestore.django import modulestore, _MODULESTORES from xmodule.seq_module import SequenceModule from courseware.tests.tests import PageLoader -from student.models import Registration +from student.models import Registration from factories import UserFactory + class Stub: def __init__(self): pass + def xml_store_config(data_dir): return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } } } -} TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class ModuleRenderTestCase(PageLoader): def setUp(self): @@ -54,8 +57,8 @@ class ModuleRenderTestCase(PageLoader): self.toy_course = modulestore().get_course(self.course_id) def test_get_module(self): - self.assertIsNone(render.get_module('dummyuser',None,\ - 'invalid location',None,None)) + self.assertIsNone(render.get_module('dummyuser', None, + 'invalid location', None, None)) def test_get_instance_module(self): mock_user = MagicMock() @@ -67,17 +70,17 @@ class ModuleRenderTestCase(PageLoader): mock_module = MagicMock() mock_module.descriptor.stores_state = False self.assertIsNone(render.get_instance_module('dummy', mock_user_2, - mock_module,'dummy')) + mock_module, 'dummy')) def test_modx_dispatch(self): self.assertRaises(Http404, render.modx_dispatch, 'dummy', 'dummy', 'invalid Location', 'dummy') mock_request = MagicMock() mock_request.FILES.keys.return_value = ['file_id'] - mock_request.FILES.getlist.return_value = ['file']*(settings.MAX_FILEUPLOADS_PER_INPUT + 1) + mock_request.FILES.getlist.return_value = ['file'] * (settings.MAX_FILEUPLOADS_PER_INPUT + 1) self.assertEquals(render.modx_dispatch(mock_request, 'dummy', self.location, 'dummy').content, - json.dumps({'success': 'Submission aborted! Maximum %d files may be submitted at once' %\ + json.dumps({'success': 'Submission aborted! Maximum %d files may be submitted at once' % settings.MAX_FILEUPLOADS_PER_INPUT})) mock_request_2 = MagicMock() mock_request_2.FILES.keys.return_value = ['file_id'] @@ -88,8 +91,8 @@ class ModuleRenderTestCase(PageLoader): mock_request_2.FILES.getlist.return_value = filelist self.assertEquals(render.modx_dispatch(mock_request_2, 'dummy', self.location, 'dummy').content, - json.dumps({'success': 'Submission aborted! Your file "%s" is too large (max size: %d MB)' %\ - (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE/(1000**2))})) + json.dumps({'success': 'Submission aborted! Your file "%s" is too large (max size: %d MB)' % + (inputfile.name, settings.STUDENT_FILEUPLOAD_MAX_SIZE / (1000 ** 2))})) mock_request_3 = MagicMock() mock_request_3.POST.copy.return_value = {} mock_request_3.FILES = False @@ -99,12 +102,12 @@ class ModuleRenderTestCase(PageLoader): inputfile_2.name = 'name' self.assertRaises(ItemNotFoundError, render.modx_dispatch, mock_request_3, 'dummy', self.location, 'toy') - self.assertRaises(Http404,render.modx_dispatch, mock_request_3, 'dummy', + self.assertRaises(Http404, render.modx_dispatch, mock_request_3, 'dummy', self.location, self.course_id) - mock_request_3.POST.copy.return_value = {'position':1} + mock_request_3.POST.copy.return_value = {'position': 1} self.assertIsInstance(render.modx_dispatch(mock_request_3, 'goto_position', self.location, self.course_id), HttpResponse) - + def test_get_score_bucket(self): self.assertEquals(render.get_score_bucket(0, 10), 'incorrect') self.assertEquals(render.get_score_bucket(1, 10), 'partial') @@ -113,6 +116,7 @@ class ModuleRenderTestCase(PageLoader): self.assertEquals(render.get_score_bucket(11, 10), 'incorrect') self.assertEquals(render.get_score_bucket(-1, 10), 'incorrect') + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestTOC(TestCase): """Check the Table of Contents for a course""" @@ -130,19 +134,19 @@ class TestTOC(TestCase): factory = RequestFactory() request = factory.get(chapter_url) - expected = ([{'active': True, 'sections': - [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, - 'format': u'Lecture Sequence', 'due': '', 'active': False}, - {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, - 'format': '', 'due': '', 'active': False}, - {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, - 'format': '', 'due': '', 'active': False}, - {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, - 'format': '', 'due': '', 'active': False}], - 'url_name': 'Overview', 'display_name': u'Overview'}, - {'active': False, 'sections': - [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, - 'format': '', 'due': '', 'active': False}], + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': '', 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': '', 'active': False}], 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, None) @@ -155,21 +159,20 @@ class TestTOC(TestCase): factory = RequestFactory() request = factory.get(chapter_url) - expected = ([{'active': True, 'sections': - [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, - 'format': u'Lecture Sequence', 'due': '', 'active': False}, - {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, - 'format': '', 'due': '', 'active': True}, - {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, - 'format': '', 'due': '', 'active': False}, - {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, - 'format': '', 'due': '', 'active': False}], - 'url_name': 'Overview', 'display_name': u'Overview'}, - {'active': False, 'sections': - [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, - 'format': '', 'due': '', 'active': False}], + expected = ([{'active': True, 'sections': + [{'url_name': 'Toy_Videos', 'display_name': u'Toy Videos', 'graded': True, + 'format': u'Lecture Sequence', 'due': '', 'active': False}, + {'url_name': 'Welcome', 'display_name': u'Welcome', 'graded': True, + 'format': '', 'due': '', 'active': True}, + {'url_name': 'video_123456789012', 'display_name': 'video 123456789012', 'graded': True, + 'format': '', 'due': '', 'active': False}, + {'url_name': 'video_4f66f493ac8f', 'display_name': 'video 4f66f493ac8f', 'graded': True, + 'format': '', 'due': '', 'active': False}], + 'url_name': 'Overview', 'display_name': u'Overview'}, + {'active': False, 'sections': + [{'url_name': 'toyvideo', 'display_name': 'toyvideo', 'graded': True, + 'format': '', 'due': '', 'active': False}], 'url_name': 'secret:magic', 'display_name': 'secret:magic'}]) actual = render.toc_for_course(self.portal_user, request, self.toy_course, chapter, section) self.assertEqual(expected, actual) - diff --git a/lms/djangoapps/courseware/tests/test_progress.py b/lms/djangoapps/courseware/tests/test_progress.py index 44a0f0cb30..a70cbe4b9a 100644 --- a/lms/djangoapps/courseware/tests/test_progress.py +++ b/lms/djangoapps/courseware/tests/test_progress.py @@ -1,58 +1,57 @@ -from django.test import TestCase +from django.test import TestCase from courseware import progress from mock import MagicMock - class ProgessTests(TestCase): - def setUp(self): + def setUp(self): - self.d = dict({'duration_total': 0, - 'duration_watched': 0, - 'done': True, - 'questions_correct': 4, - 'questions_incorrect': 0, - 'questions_total': 0}) + self.d = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 0}) - self.c = progress.completion() - self.c2= progress.completion() - self.c2.dict = dict({'duration_total': 0, - 'duration_watched': 0, - 'done': True, - 'questions_correct': 2, - 'questions_incorrect': 1, - 'questions_total': 0}) + self.c = progress.completion() + self.c2 = progress.completion() + self.c2.dict = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 2, + 'questions_incorrect': 1, + 'questions_total': 0}) - self.cplusc2 = dict({'duration_total': 0, - 'duration_watched': 0, - 'done': True, - 'questions_correct': 2, - 'questions_incorrect': 1, - 'questions_total': 0}) + self.cplusc2 = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 2, + 'questions_incorrect': 1, + 'questions_total': 0}) - self.oth = dict({'duration_total': 0, - 'duration_watched': 0, - 'done': True, - 'questions_correct': 4, - 'questions_incorrect': 0, - 'questions_total': 7}) + self.oth = dict({'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 7}) - self.x = MagicMock() - self.x.dict = self.oth + self.x = MagicMock() + self.x.dict = self.oth - self.d_oth = {'duration_total': 0, - 'duration_watched': 0, - 'done': True, - 'questions_correct': 4, - 'questions_incorrect': 0, - 'questions_total': 7} + self.d_oth = {'duration_total': 0, + 'duration_watched': 0, + 'done': True, + 'questions_correct': 4, + 'questions_incorrect': 0, + 'questions_total': 7} - def test_getitem(self): - self.assertEqual(self.c.__getitem__('duration_watched'), 0) + def test_getitem(self): + self.assertEqual(self.c.__getitem__('duration_watched'), 0) - def test_setitem(self): - self.c.__setitem__('questions_correct', 4) - self.assertEqual(str(self.c),str(self.d)) + def test_setitem(self): + self.c.__setitem__('questions_correct', 4) + self.assertEqual(str(self.c), str(self.d)) - def test_repr(self): - self.assertEqual(self.c.__repr__(), str(progress.completion())) + def test_repr(self): + self.assertEqual(self.c.__repr__(), str(progress.completion())) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index cb15b5b7b6..eeac999813 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -15,12 +15,13 @@ from django.test.client import RequestFactory from student.models import CourseEnrollment from xmodule.modulestore.django import modulestore, _MODULESTORES from xmodule.modulestore.exceptions import InvalidLocationError,\ - ItemNotFoundError, NoPathToItem + ItemNotFoundError, NoPathToItem import courseware.views as views from xmodule.modulestore import Location from factories import UserFactory + class Stub(): pass @@ -28,18 +29,19 @@ class Stub(): # This part is required for modulestore() to work properly def xml_store_config(data_dir): return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } } } -} TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) + @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestJumpTo(TestCase): """Check the jumpto link for a course""" @@ -64,15 +66,16 @@ class TestJumpTo(TestCase): response = self.client.get(jumpto_url) self.assertRedirects(response, expected, status_code=302, target_status_code=302) + class ViewsTestCase(TestCase): def setUp(self): self.user = User.objects.create(username='dummy', password='123456', email='test@mit.edu') - self.date = datetime.datetime(2013,1,22) + self.date = datetime.datetime(2013, 1, 22) self.course_id = 'edX/toy/2012_Fall' - self.enrollment = CourseEnrollment.objects.get_or_create(user = self.user, - course_id = self.course_id, - created = self.date)[0] + self.enrollment = CourseEnrollment.objects.get_or_create(user=self.user, + course_id=self.course_id, + created=self.date)[0] self.location = ['tag', 'org', 'course', 'category', 'name'] self._MODULESTORES = {} # This is a CourseDescriptor object @@ -85,13 +88,13 @@ class ViewsTestCase(TestCase): # depreciated function mock_user = MagicMock() mock_user.is_authenticated.return_value = False - self.assertEquals(views.user_groups(mock_user),[]) - + self.assertEquals(views.user_groups(mock_user), []) + def test_get_current_child(self): self.assertIsNone(views.get_current_child(Stub())) mock_xmodule = MagicMock() mock_xmodule.position = -1 - mock_xmodule.get_display_items.return_value = ['one','two'] + mock_xmodule.get_display_items.return_value = ['one', 'two'] self.assertEquals(views.get_current_child(mock_xmodule), 'one') mock_xmodule_2 = MagicMock() mock_xmodule_2.position = 3 diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index fb6842d4a9..7e00baf61f 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -53,46 +53,46 @@ def registration(email): def mongo_store_config(data_dir): return { - 'default': { - 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', - 'OPTIONS': { - 'default_class': 'xmodule.raw_module.RawDescriptor', - 'host': 'localhost', - 'db': 'test_xmodule', - 'collection': 'modulestore', - 'fs_root': data_dir, - 'render_template': 'mitxmako.shortcuts.render_to_string', + 'default': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': { + 'default_class': 'xmodule.raw_module.RawDescriptor', + 'host': 'localhost', + 'db': 'test_xmodule', + 'collection': 'modulestore', + 'fs_root': data_dir, + 'render_template': 'mitxmako.shortcuts.render_to_string', + } } } -} def draft_mongo_store_config(data_dir): return { - 'default': { - 'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore', - 'OPTIONS': { - 'default_class': 'xmodule.raw_module.RawDescriptor', - 'host': 'localhost', - 'db': 'test_xmodule', - 'collection': 'modulestore', - 'fs_root': data_dir, - 'render_template': 'mitxmako.shortcuts.render_to_string', + 'default': { + 'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore', + 'OPTIONS': { + 'default_class': 'xmodule.raw_module.RawDescriptor', + 'host': 'localhost', + 'db': 'test_xmodule', + 'collection': 'modulestore', + 'fs_root': data_dir, + 'render_template': 'mitxmako.shortcuts.render_to_string', + } } } -} def xml_store_config(data_dir): return { - 'default': { - 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', - 'OPTIONS': { - 'data_dir': data_dir, - 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + 'default': { + 'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore', + 'OPTIONS': { + 'data_dir': data_dir, + 'default_class': 'xmodule.hidden_module.HiddenDescriptor', + } } } -} TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR) @@ -115,8 +115,7 @@ class ActivateLoginTestCase(TestCase): 'Response status code was {0} instead of 302'.format(response.status_code)) url = response['Location'] - e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit( - expected_url) + e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url) if not (e_scheme or e_netloc): expected_url = urlunsplit(('http', 'testserver', e_path, e_query, e_fragment)) @@ -211,7 +210,7 @@ class PageLoader(ActivateLoginTestCase): resp = self.client.post('/change_enrollment', { 'enrollment_action': 'enroll', 'course_id': course.id, - }) + }) return parse_json(resp) def try_enroll(self, course): @@ -230,11 +229,10 @@ class PageLoader(ActivateLoginTestCase): resp = self.client.post('/change_enrollment', { 'enrollment_action': 'unenroll', 'course_id': course.id, - }) + }) data = parse_json(resp) self.assertTrue(data['success']) - def check_for_get_code(self, code, url): """ Check that we got the expected code when accessing url via GET. @@ -246,7 +244,6 @@ class PageLoader(ActivateLoginTestCase): .format(resp.status_code, url, code)) return resp - def check_for_post_code(self, code, url, data={}): """ Check that we got the expected code when accessing url via POST. @@ -258,12 +255,8 @@ class PageLoader(ActivateLoginTestCase): .format(resp.status_code, url, code)) return resp - - def check_pages_load(self, module_store): """Make all locations in course load""" - - # enroll in the course before trying to access pages courses = module_store.get_courses() self.assertEqual(len(courses), 1) @@ -316,7 +309,7 @@ class PageLoader(ActivateLoginTestCase): msg = str(resp.status_code) if resp.status_code != 200: - msg = "ERROR " + msg + ": " + descriptor.location.url() + msg = "ERROR " + msg + ": " + descriptor.location.url() all_ok = False num_bad += 1 elif resp.redirect_chain[0][1] != 302: @@ -344,7 +337,6 @@ class PageLoader(ActivateLoginTestCase): self.assertTrue(all_ok) - @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestCoursesLoadTestCase_XmlModulestore(PageLoader): '''Check that all pages in test courses load properly''' @@ -355,21 +347,21 @@ class TestCoursesLoadTestCase_XmlModulestore(PageLoader): def test_toy_course_loads(self): module_store = XMLModuleStore( - TEST_DATA_DIR, - default_class='xmodule.hidden_module.HiddenDescriptor', - course_dirs=['toy'], - load_error_modules=True, - ) + TEST_DATA_DIR, + default_class='xmodule.hidden_module.HiddenDescriptor', + course_dirs=['toy'], + load_error_modules=True, + ) self.check_pages_load(module_store) def test_full_course_loads(self): module_store = XMLModuleStore( - TEST_DATA_DIR, - default_class='xmodule.hidden_module.HiddenDescriptor', - course_dirs=['full'], - load_error_modules=True, - ) + TEST_DATA_DIR, + default_class='xmodule.hidden_module.HiddenDescriptor', + course_dirs=['full'], + load_error_modules=True, + ) self.check_pages_load(module_store) @@ -525,7 +517,6 @@ class TestViewAuth(PageLoader): print 'checking for 404 on {0}'.format(url) self.check_for_get_code(404, url) - # now also make the instructor staff u = user(self.instructor) u.is_staff = True @@ -536,7 +527,6 @@ class TestViewAuth(PageLoader): print 'checking for 200 on {0}'.format(url) self.check_for_get_code(200, url) - def run_wrapped(self, test): """ test.py turns off start dates. Enable them. @@ -552,7 +542,6 @@ class TestViewAuth(PageLoader): finally: settings.MITX_FEATURES['DISABLE_START_DATES'] = oldDSD - def test_dark_launch(self): """Make sure that before course start, students can't access course pages, but instructors can""" @@ -646,7 +635,6 @@ class TestViewAuth(PageLoader): url = reverse_urls(['courseware'], course)[0] self.check_for_get_code(302, url) - # First, try with an enrolled student print '=== Testing student access....' self.login(self.student, self.password) @@ -761,7 +749,6 @@ class TestViewAuth(PageLoader): self.assertTrue(has_access(student_user, self.toy, 'load')) - @override_settings(MODULESTORE=TEST_DATA_XML_MODULESTORE) class TestCourseGrader(PageLoader): """Check that a course gets graded properly""" @@ -832,13 +819,12 @@ class TestCourseGrader(PageLoader): kwargs={ 'course_id': self.graded_course.id, 'location': problem_location, - 'dispatch': 'problem_check', } - ) + 'dispatch': 'problem_check', }) resp = self.client.post(modx_url, { 'input_i4x-edX-graded-problem-{0}_2_1'.format(problem_url_name): responses[0], 'input_i4x-edX-graded-problem-{0}_2_2'.format(problem_url_name): responses[1], - }) + }) print "modx_url", modx_url, "responses", responses print "resp", resp @@ -854,8 +840,7 @@ class TestCourseGrader(PageLoader): kwargs={ 'course_id': self.graded_course.id, 'location': problem_location, - 'dispatch': 'problem_reset', } - ) + 'dispatch': 'problem_reset', }) resp = self.client.post(modx_url) return resp