Commit 2ecf7aec by David Ormsbee

Update Instructor Dashboard tests to use SharedModuleStoreTestCase.

Also added reset_test_case() and @modifies_courseware to SharedModuleStoreTestCase.

Revert "More verbose test builds in Jenkins, for debugging."

This reverts commit 58cade4cc4288335026649470a48b7bbca969ee8.
parent 68414a13
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
Modulestore configuration for test cases. Modulestore configuration for test cases.
""" """
import datetime import datetime
import functools
import pytz import pytz
from uuid import uuid4 from uuid import uuid4
...@@ -220,7 +221,8 @@ class SharedModuleStoreTestCase(TestCase): ...@@ -220,7 +221,8 @@ class SharedModuleStoreTestCase(TestCase):
Subclass for any test case that uses a ModuleStore that can be shared Subclass for any test case that uses a ModuleStore that can be shared
between individual tests. This class ensures that the ModuleStore is cleaned between individual tests. This class ensures that the ModuleStore is cleaned
before/after the entire test case has run. Use this class if your tests before/after the entire test case has run. Use this class if your tests
set up one or a small number of courses that individual tests do not modify. set up one or a small number of courses that individual tests do not modify
(or modify extermely rarely -- see @modifies_courseware).
If your tests modify contents in the ModuleStore, you should use If your tests modify contents in the ModuleStore, you should use
ModuleStoreTestCase instead. ModuleStoreTestCase instead.
...@@ -279,6 +281,52 @@ class SharedModuleStoreTestCase(TestCase): ...@@ -279,6 +281,52 @@ class SharedModuleStoreTestCase(TestCase):
OverrideFieldData.provider_classes = None OverrideFieldData.provider_classes = None
super(SharedModuleStoreTestCase, self).setUp() super(SharedModuleStoreTestCase, self).setUp()
def reset(self):
"""
Manually run tearDownClass/setUpClass again.
This is so that if you have a mostly read-only course that you're just
modifying in one test, you can write `self.reset()` at the
end of that test and reset the state of the world for other tests in
the class.
"""
self.tearDownClass()
self.setUpClass()
@staticmethod
def modifies_courseware(f):
"""
Decorator to place around tests that modify course content.
For performance reasons, SharedModuleStoreTestCase intentionally does
not reset the modulestore between individual tests. However, sometimes
you might have a test case where the vast majority of tests treat a
course as read-only, but one or two want to modify it. In that case, you
can do this:
class MyTestCase(SharedModuleStoreTestCase):
# ...
@SharedModuleStoreTestCase.modifies_courseware
def test_that_edits_modulestore(self):
do_something()
This is equivalent to calling `self.reset()` at the end of
your test.
If you find yourself using this functionality a lot, it might indicate
that you should be using ModuleStoreTestCase instead, or that you should
break up your tests into different TestCases.
"""
@functools.wraps(f)
def wrapper(*args, **kwargs):
"""Call the object method, and reset the test case afterwards."""
return_val = f(*args, **kwargs)
obj = args[0]
obj.reset()
return return_val
return wrapper
class ModuleStoreTestCase(TestCase): class ModuleStoreTestCase(TestCase):
""" """
......
...@@ -6,7 +6,7 @@ from nose.tools import raises ...@@ -6,7 +6,7 @@ from nose.tools import raises
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from student.roles import CourseBetaTesterRole, CourseStaffRole from student.roles import CourseBetaTesterRole, CourseStaffRole
...@@ -19,13 +19,15 @@ from instructor.access import (allow_access, ...@@ -19,13 +19,15 @@ from instructor.access import (allow_access,
@attr('shard_1') @attr('shard_1')
class TestInstructorAccessList(ModuleStoreTestCase): class TestInstructorAccessList(SharedModuleStoreTestCase):
""" Test access listings. """ """ Test access listings. """
@classmethod
def setUpClass(cls):
super(TestInstructorAccessList, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorAccessList, self).setUp() super(TestInstructorAccessList, self).setUp()
self.course = CourseFactory.create()
self.instructors = [UserFactory.create() for _ in xrange(4)] self.instructors = [UserFactory.create() for _ in xrange(4)]
for user in self.instructors: for user in self.instructors:
allow_access(self.course, user, 'instructor') allow_access(self.course, user, 'instructor')
...@@ -43,8 +45,13 @@ class TestInstructorAccessList(ModuleStoreTestCase): ...@@ -43,8 +45,13 @@ class TestInstructorAccessList(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
class TestInstructorAccessAllow(ModuleStoreTestCase): class TestInstructorAccessAllow(SharedModuleStoreTestCase):
""" Test access allow. """ """ Test access allow. """
@classmethod
def setUpClass(cls):
super(TestInstructorAccessAllow, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorAccessAllow, self).setUp() super(TestInstructorAccessAllow, self).setUp()
...@@ -79,13 +86,15 @@ class TestInstructorAccessAllow(ModuleStoreTestCase): ...@@ -79,13 +86,15 @@ class TestInstructorAccessAllow(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
class TestInstructorAccessRevoke(ModuleStoreTestCase): class TestInstructorAccessRevoke(SharedModuleStoreTestCase):
""" Test access revoke. """ """ Test access revoke. """
@classmethod
def setUpClass(cls):
super(TestInstructorAccessRevoke, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorAccessRevoke, self).setUp() super(TestInstructorAccessRevoke, self).setUp()
self.course = CourseFactory.create()
self.staff = [UserFactory.create() for _ in xrange(4)] self.staff = [UserFactory.create() for _ in xrange(4)]
for user in self.staff: for user in self.staff:
allow_access(self.course, user, 'staff') allow_access(self.course, user, 'staff')
...@@ -115,15 +124,17 @@ class TestInstructorAccessRevoke(ModuleStoreTestCase): ...@@ -115,15 +124,17 @@ class TestInstructorAccessRevoke(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
class TestInstructorAccessForum(ModuleStoreTestCase): class TestInstructorAccessForum(SharedModuleStoreTestCase):
""" """
Test forum access control. Test forum access control.
""" """
@classmethod
def setUpClass(cls):
super(TestInstructorAccessForum, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorAccessForum, self).setUp() super(TestInstructorAccessForum, self).setUp()
self.course = CourseFactory.create()
self.mod_role = Role.objects.create( self.mod_role = Role.objects.create(
course_id=self.course.id, course_id=self.course.id,
name=FORUM_ROLE_MODERATOR name=FORUM_ROLE_MODERATOR
......
...@@ -13,15 +13,19 @@ from student.models import CourseEnrollment ...@@ -13,15 +13,19 @@ from student.models import CourseEnrollment
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@attr('shard_1') @attr('shard_1')
class TestInstructorAPIEnrollmentEmailLocalization(ModuleStoreTestCase): class TestInstructorAPIEnrollmentEmailLocalization(SharedModuleStoreTestCase):
""" """
Test whether the enroll, unenroll and beta role emails are sent in the Test whether the enroll, unenroll and beta role emails are sent in the
proper language, i.e: the student's language. proper language, i.e: the student's language.
""" """
@classmethod
def setUpClass(cls):
super(TestInstructorAPIEnrollmentEmailLocalization, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorAPIEnrollmentEmailLocalization, self).setUp() super(TestInstructorAPIEnrollmentEmailLocalization, self).setUp()
...@@ -29,7 +33,6 @@ class TestInstructorAPIEnrollmentEmailLocalization(ModuleStoreTestCase): ...@@ -29,7 +33,6 @@ class TestInstructorAPIEnrollmentEmailLocalization(ModuleStoreTestCase):
# Platform language is English, instructor's language is Chinese, # Platform language is English, instructor's language is Chinese,
# student's language is French, so the emails should all be sent in # student's language is French, so the emails should all be sent in
# French. # French.
self.course = CourseFactory.create()
self.instructor = InstructorFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id)
set_user_preference(self.instructor, LANGUAGE_KEY, 'zh-cn') set_user_preference(self.instructor, LANGUAGE_KEY, 'zh-cn')
self.client.login(username=self.instructor.username, password='test') self.client.login(username=self.instructor.username, password='test')
......
...@@ -8,7 +8,7 @@ from nose.plugins.attrib import attr ...@@ -8,7 +8,7 @@ from nose.plugins.attrib import attr
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.utils import override_settings from django.test.utils import override_settings
from django.conf import settings from django.conf import settings
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from config_models.models import cache from config_models.models import cache
from courseware.tests.factories import GlobalStaffFactory, InstructorFactory, UserFactory from courseware.tests.factories import GlobalStaffFactory, InstructorFactory, UserFactory
...@@ -18,19 +18,23 @@ from certificates import api as certs_api ...@@ -18,19 +18,23 @@ from certificates import api as certs_api
@attr('shard_1') @attr('shard_1')
@ddt.ddt @ddt.ddt
class CertificatesInstructorDashTest(ModuleStoreTestCase): class CertificatesInstructorDashTest(SharedModuleStoreTestCase):
"""Tests for the certificate panel of the instructor dash. """ """Tests for the certificate panel of the instructor dash. """
ERROR_REASON = "An error occurred!" ERROR_REASON = "An error occurred!"
DOWNLOAD_URL = "http://www.example.com/abcd123/cert.pdf" DOWNLOAD_URL = "http://www.example.com/abcd123/cert.pdf"
def setUp(self): @classmethod
super(CertificatesInstructorDashTest, self).setUp() def setUpClass(cls):
self.course = CourseFactory.create() super(CertificatesInstructorDashTest, cls).setUpClass()
self.url = reverse( cls.course = CourseFactory.create()
cls.url = reverse(
'instructor_dashboard', 'instructor_dashboard',
kwargs={'course_id': unicode(self.course.id)} kwargs={'course_id': unicode(cls.course.id)}
) )
def setUp(self):
super(CertificatesInstructorDashTest, self).setUp()
self.global_staff = GlobalStaffFactory() self.global_staff = GlobalStaffFactory()
self.instructor = InstructorFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id)
...@@ -189,12 +193,15 @@ class CertificatesInstructorDashTest(ModuleStoreTestCase): ...@@ -189,12 +193,15 @@ class CertificatesInstructorDashTest(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
@override_settings(CERT_QUEUE='certificates') @override_settings(CERT_QUEUE='certificates')
@ddt.ddt @ddt.ddt
class CertificatesInstructorApiTest(ModuleStoreTestCase): class CertificatesInstructorApiTest(SharedModuleStoreTestCase):
"""Tests for the certificates end-points in the instructor dash API. """ """Tests for the certificates end-points in the instructor dash API. """
@classmethod
def setUpClass(cls):
super(CertificatesInstructorApiTest, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(CertificatesInstructorApiTest, self).setUp() super(CertificatesInstructorApiTest, self).setUp()
self.course = CourseFactory.create()
self.global_staff = GlobalStaffFactory() self.global_staff = GlobalStaffFactory()
self.instructor = InstructorFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id)
......
...@@ -13,18 +13,26 @@ from course_modes.models import CourseMode ...@@ -13,18 +13,26 @@ from course_modes.models import CourseMode
from student.roles import CourseFinanceAdminRole from student.roles import CourseFinanceAdminRole
from shoppingcart.models import Coupon, CourseRegistrationCode from shoppingcart.models import Coupon, CourseRegistrationCode
from student.tests.factories import AdminFactory from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
@attr('shard_1') @attr('shard_1')
class TestECommerceDashboardViews(ModuleStoreTestCase): class TestECommerceDashboardViews(SharedModuleStoreTestCase):
""" """
Check for E-commerce view on the new instructor dashboard Check for E-commerce view on the new instructor dashboard
""" """
@classmethod
def setUpClass(cls):
super(TestECommerceDashboardViews, cls).setUpClass()
cls.course = CourseFactory.create()
# URL for instructor dash
cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course.id.to_deprecated_string()})
cls.e_commerce_link = '<a href="" data-section="e-commerce">E-Commerce</a>'
def setUp(self): def setUp(self):
super(TestECommerceDashboardViews, self).setUp() super(TestECommerceDashboardViews, self).setUp()
self.course = CourseFactory.create()
# Create instructor account # Create instructor account
self.instructor = AdminFactory.create() self.instructor = AdminFactory.create()
...@@ -34,9 +42,6 @@ class TestECommerceDashboardViews(ModuleStoreTestCase): ...@@ -34,9 +42,6 @@ class TestECommerceDashboardViews(ModuleStoreTestCase):
mode_display_name='honor', min_price=10, currency='usd' mode_display_name='honor', min_price=10, currency='usd'
) )
mode.save() mode.save()
# URL for instructor dash
self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()})
self.e_commerce_link = '<a href="" data-section="e-commerce">E-Commerce</a>'
CourseFinanceAdminRole(self.course.id).add_users(self.instructor) CourseFinanceAdminRole(self.course.id).add_users(self.instructor)
def test_pass_e_commerce_tab_in_instructor_dashboard(self): def test_pass_e_commerce_tab_in_instructor_dashboard(self):
......
...@@ -11,30 +11,36 @@ from nose.plugins.attrib import attr ...@@ -11,30 +11,36 @@ from nose.plugins.attrib import attr
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from bulk_email.models import CourseAuthorization from bulk_email.models import CourseAuthorization
from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import (
TEST_DATA_MIXED_TOY_MODULESTORE, SharedModuleStoreTestCase
)
from student.tests.factories import AdminFactory from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
@attr('shard_1') @attr('shard_1')
class TestNewInstructorDashboardEmailViewMongoBacked(ModuleStoreTestCase): class TestNewInstructorDashboardEmailViewMongoBacked(SharedModuleStoreTestCase):
""" """
Check for email view on the new instructor dashboard Check for email view on the new instructor dashboard
for Mongo-backed courses for Mongo-backed courses
""" """
@classmethod
def setUpClass(cls):
super(TestNewInstructorDashboardEmailViewMongoBacked, cls).setUpClass()
cls.course = CourseFactory.create()
# URL for instructor dash
cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course.id.to_deprecated_string()})
# URL for email view
cls.email_link = '<a href="" data-section="send_email">Email</a>'
def setUp(self): def setUp(self):
super(TestNewInstructorDashboardEmailViewMongoBacked, self).setUp() super(TestNewInstructorDashboardEmailViewMongoBacked, self).setUp()
self.course = CourseFactory.create()
# Create instructor account # Create instructor account
instructor = AdminFactory.create() instructor = AdminFactory.create()
self.client.login(username=instructor.username, password="test") self.client.login(username=instructor.username, password="test")
# URL for instructor dash
self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()})
# URL for email view
self.email_link = '<a href="" data-section="send_email">Email</a>'
# In order for bulk email to work, we must have both the ENABLE_INSTRUCTOR_EMAIL_FLAG # In order for bulk email to work, we must have both the ENABLE_INSTRUCTOR_EMAIL_FLAG
# set to True and for the course to be Mongo-backed. # set to True and for the course to be Mongo-backed.
# The flag is enabled and the course is Mongo-backed (should work) # The flag is enabled and the course is Mongo-backed (should work)
...@@ -101,16 +107,25 @@ class TestNewInstructorDashboardEmailViewMongoBacked(ModuleStoreTestCase): ...@@ -101,16 +107,25 @@ class TestNewInstructorDashboardEmailViewMongoBacked(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
class TestNewInstructorDashboardEmailViewXMLBacked(ModuleStoreTestCase): class TestNewInstructorDashboardEmailViewXMLBacked(SharedModuleStoreTestCase):
""" """
Check for email view on the new instructor dashboard Check for email view on the new instructor dashboard
""" """
MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE
@classmethod
def setUpClass(cls):
super(TestNewInstructorDashboardEmailViewXMLBacked, cls).setUpClass()
cls.course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
# URL for instructor dash
cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course_key.to_deprecated_string()})
# URL for email view
cls.email_link = '<a href="" data-section="send_email">Email</a>'
def setUp(self): def setUp(self):
super(TestNewInstructorDashboardEmailViewXMLBacked, self).setUp() super(TestNewInstructorDashboardEmailViewXMLBacked, self).setUp()
self.course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall')
# Create instructor account # Create instructor account
instructor = AdminFactory.create() instructor = AdminFactory.create()
......
...@@ -30,7 +30,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey ...@@ -30,7 +30,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from submissions import api as sub_api from submissions import api as sub_api
from student.models import anonymous_id_for_user from student.models import anonymous_id_for_user
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@attr('shard_1') @attr('shard_1')
...@@ -296,40 +296,40 @@ class TestInstructorUnenrollDB(TestEnrollmentChangeBase): ...@@ -296,40 +296,40 @@ class TestInstructorUnenrollDB(TestEnrollmentChangeBase):
@attr('shard_1') @attr('shard_1')
class TestInstructorEnrollmentStudentModule(ModuleStoreTestCase): class TestInstructorEnrollmentStudentModule(SharedModuleStoreTestCase):
""" Test student module manipulations. """ """ Test student module manipulations. """
def setUp(self): @classmethod
super(TestInstructorEnrollmentStudentModule, self).setUp() def setUpClass(cls):
store = modulestore() super(TestInstructorEnrollmentStudentModule, cls).setUpClass()
self.user = UserFactory() cls.course = CourseFactory(
self.course = CourseFactory(
name='fake', name='fake',
org='course', org='course',
run='id', run='id',
) )
# pylint: disable=no-member # pylint: disable=no-member
self.course_key = self.course.location.course_key cls.course_key = cls.course.location.course_key
self.parent = ItemFactory( with cls.store.bulk_operations(cls.course.id, emit_signals=False):
category="library_content", cls.parent = ItemFactory(
user_id=self.user.id, category="library_content",
parent=self.course, parent=cls.course,
publish_item=True, publish_item=True,
modulestore=store, )
) cls.child = ItemFactory(
self.child = ItemFactory( category="html",
category="html", parent=cls.parent,
user_id=self.user.id, publish_item=True,
parent=self.parent, )
publish_item=True, cls.unrelated = ItemFactory(
modulestore=store, category="html",
) parent=cls.course,
self.unrelated = ItemFactory( publish_item=True,
category="html", )
user_id=self.user.id,
parent=self.course, def setUp(self):
publish_item=True, super(TestInstructorEnrollmentStudentModule, self).setUp()
modulestore=store,
) self.user = UserFactory()
parent_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'}) parent_state = json.dumps({'attempts': 32, 'otherstuff': 'alsorobots'})
child_state = json.dumps({'attempts': 10, 'whatever': 'things'}) child_state = json.dumps({'attempts': 10, 'whatever': 'things'})
unrelated_state = json.dumps({'attempts': 12, 'brains': 'zombie'}) unrelated_state = json.dumps({'attempts': 12, 'brains': 'zombie'})
...@@ -567,26 +567,27 @@ class TestSendBetaRoleEmail(TestCase): ...@@ -567,26 +567,27 @@ class TestSendBetaRoleEmail(TestCase):
@attr('shard_1') @attr('shard_1')
class TestGetEmailParams(ModuleStoreTestCase): class TestGetEmailParams(SharedModuleStoreTestCase):
""" """
Test what URLs the function get_email_params returns under different Test what URLs the function get_email_params returns under different
production-like conditions. production-like conditions.
""" """
def setUp(self): @classmethod
super(TestGetEmailParams, self).setUp() def setUpClass(cls):
super(TestGetEmailParams, cls).setUpClass()
self.course = CourseFactory.create() cls.course = CourseFactory.create()
# Explicitly construct what we expect the course URLs to be # Explicitly construct what we expect the course URLs to be
site = settings.SITE_NAME site = settings.SITE_NAME
self.course_url = u'https://{}/courses/{}/'.format( cls.course_url = u'https://{}/courses/{}/'.format(
site,
self.course.id.to_deprecated_string()
)
self.course_about_url = self.course_url + 'about'
self.registration_url = u'https://{}/register'.format(
site, site,
cls.course.id.to_deprecated_string()
) )
cls.course_about_url = cls.course_url + 'about'
cls.registration_url = u'https://{}/register'.format(site)
def setUp(self):
super(TestGetEmailParams, self).setUp()
def test_normal_params(self): def test_normal_params(self):
# For a normal site, what do we expect to get for the URLs? # For a normal site, what do we expect to get for the URLs?
...@@ -612,16 +613,19 @@ class TestGetEmailParams(ModuleStoreTestCase): ...@@ -612,16 +613,19 @@ class TestGetEmailParams(ModuleStoreTestCase):
@attr('shard_1') @attr('shard_1')
class TestRenderMessageToString(ModuleStoreTestCase): class TestRenderMessageToString(SharedModuleStoreTestCase):
""" """
Test that email templates can be rendered in a language chosen manually. Test that email templates can be rendered in a language chosen manually.
""" """
@classmethod
def setUpClass(cls):
super(TestRenderMessageToString, cls).setUpClass()
cls.course = CourseFactory.create()
cls.subject_template = 'emails/enroll_email_allowedsubject.txt'
cls.message_template = 'emails/enroll_email_allowedmessage.txt'
def setUp(self): def setUp(self):
super(TestRenderMessageToString, self).setUp() super(TestRenderMessageToString, self).setUp()
self.subject_template = 'emails/enroll_email_allowedsubject.txt'
self.message_template = 'emails/enroll_email_allowedmessage.txt'
self.course = CourseFactory.create()
def get_email_params(self): def get_email_params(self):
""" """
......
...@@ -8,14 +8,21 @@ from courseware.models import XModuleUserStateSummaryField ...@@ -8,14 +8,21 @@ from courseware.models import XModuleUserStateSummaryField
from courseware.tests.factories import UserStateSummaryFactory from courseware.tests.factories import UserStateSummaryFactory
import instructor.hint_manager as view import instructor.hint_manager as view
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
# pylint: disable=missing-docstring # pylint: disable=missing-docstring
@attr('shard_1') @attr('shard_1')
class HintManagerTest(ModuleStoreTestCase): class HintManagerTest(SharedModuleStoreTestCase):
@classmethod
def setUpClass(cls):
super(HintManagerTest, cls).setUpClass()
cls.course = CourseFactory.create(org='Me', number='19.002', display_name='test_course')
cls.url = '/courses/Me/19.002/test_course/hint_manager'
cls.course_id = cls.course.id
cls.problem_id = cls.course_id.make_usage_key('crowdsource_hinter', 'crowdsource_hinter_001')
def setUp(self): def setUp(self):
""" """
...@@ -24,13 +31,9 @@ class HintManagerTest(ModuleStoreTestCase): ...@@ -24,13 +31,9 @@ class HintManagerTest(ModuleStoreTestCase):
""" """
super(HintManagerTest, self).setUp() super(HintManagerTest, self).setUp()
self.course = CourseFactory.create(org='Me', number='19.002', display_name='test_course')
self.url = '/courses/Me/19.002/test_course/hint_manager'
self.user = UserFactory.create(username='robot', email='robot@edx.org', password='test', is_staff=True) self.user = UserFactory.create(username='robot', email='robot@edx.org', password='test', is_staff=True)
self.c = Client() self.c = Client()
self.c.login(username='robot', password='test') self.c.login(username='robot', password='test')
self.course_id = self.course.id
self.problem_id = self.course_id.make_usage_key('crowdsource_hinter', 'crowdsource_hinter_001')
UserStateSummaryFactory.create( UserStateSummaryFactory.create(
field_name='hints', field_name='hints',
usage_id=self.problem_id, usage_id=self.problem_id,
......
...@@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse ...@@ -12,7 +12,7 @@ from django.core.urlresolvers import reverse
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from student.models import CourseEnrollment, CourseEnrollmentAllowed from student.models import CourseEnrollment, CourseEnrollmentAllowed
from instructor.views.legacy import get_and_clean_student_list, send_mail_to_student from instructor.views.legacy import get_and_clean_student_list, send_mail_to_student
from django.core import mail from django.core import mail
...@@ -22,10 +22,14 @@ USER_COUNT = 4 ...@@ -22,10 +22,14 @@ USER_COUNT = 4
@attr('shard_1') @attr('shard_1')
@ddt.ddt @ddt.ddt
class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase): class TestInstructorEnrollsStudent(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
""" """
Check Enrollment/Unenrollment with/without auto-enrollment on activation and with/without email notification Check Enrollment/Unenrollment with/without auto-enrollment on activation and with/without email notification
""" """
@classmethod
def setUpClass(cls):
super(TestInstructorEnrollsStudent, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestInstructorEnrollsStudent, self).setUp() super(TestInstructorEnrollsStudent, self).setUp()
...@@ -33,8 +37,6 @@ class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase) ...@@ -33,8 +37,6 @@ class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase)
instructor = AdminFactory.create() instructor = AdminFactory.create()
self.client.login(username=instructor.username, password='test') self.client.login(username=instructor.username, password='test')
self.course = CourseFactory.create()
self.users = [ self.users = [
UserFactory.create(username="student%d" % i, email="student%d@test.com" % i) UserFactory.create(username="student%d" % i, email="student%d@test.com" % i)
for i in xrange(USER_COUNT) for i in xrange(USER_COUNT)
......
...@@ -9,7 +9,7 @@ from nose.plugins.attrib import attr ...@@ -9,7 +9,7 @@ from nose.plugins.attrib import attr
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from edxmako.tests import mako_middleware_process_request from edxmako.tests import mako_middleware_process_request
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from instructor.views import legacy from instructor.views import legacy
...@@ -18,12 +18,16 @@ from instructor.views import legacy ...@@ -18,12 +18,16 @@ from instructor.views import legacy
@attr('shard_1') @attr('shard_1')
class TestXss(ModuleStoreTestCase): class TestXss(SharedModuleStoreTestCase):
@classmethod
def setUpClass(cls):
super(TestXss, cls).setUpClass()
cls._course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestXss, self).setUp() super(TestXss, self).setUp()
self._request_factory = RequestFactory() self._request_factory = RequestFactory()
self._course = CourseFactory.create()
self._evil_student = UserFactory.create( self._evil_student = UserFactory.create(
email="robot+evil@edx.org", email="robot+evil@edx.org",
username="evil-robot", username="evil-robot",
......
...@@ -10,29 +10,32 @@ from nose.plugins.attrib import attr ...@@ -10,29 +10,32 @@ from nose.plugins.attrib import attr
from student.roles import CourseFinanceAdminRole from student.roles import CourseFinanceAdminRole
from student.tests.factories import AdminFactory from student.tests.factories import AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
@attr('shard_1') @attr('shard_1')
@patch.dict(settings.FEATURES, {'ENABLE_PROCTORED_EXAMS': True}) @patch.dict(settings.FEATURES, {'ENABLE_PROCTORED_EXAMS': True})
class TestProctoringDashboardViews(ModuleStoreTestCase): class TestProctoringDashboardViews(SharedModuleStoreTestCase):
""" """
Check for Proctoring view on the new instructor dashboard Check for Proctoring view on the new instructor dashboard
""" """
@classmethod
def setUpClass(cls):
super(TestProctoringDashboardViews, cls).setUpClass()
cls.course = CourseFactory.create(enable_proctored_exams=True)
# URL for instructor dash
cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course.id.to_deprecated_string()})
cls.proctoring_link = '<a href="" data-section="proctoring">Proctoring</a>'
def setUp(self): def setUp(self):
super(TestProctoringDashboardViews, self).setUp() super(TestProctoringDashboardViews, self).setUp()
self.course = CourseFactory.create()
self.course.enable_proctored_exams = True
# Create instructor account # Create instructor account
self.instructor = AdminFactory.create() self.instructor = AdminFactory.create()
self.client.login(username=self.instructor.username, password="test") self.client.login(username=self.instructor.username, password="test")
self.course = self.update_course(self.course, self.instructor.id)
# URL for instructor dash
self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()})
self.proctoring_link = '<a href="" data-section="proctoring">Proctoring</a>'
CourseFinanceAdminRole(self.course.id).add_users(self.instructor) CourseFinanceAdminRole(self.course.id).add_users(self.instructor)
def test_pass_proctoring_tab_in_instructor_dashboard(self): def test_pass_proctoring_tab_in_instructor_dashboard(self):
......
...@@ -15,19 +15,22 @@ import json ...@@ -15,19 +15,22 @@ import json
from student.tests.factories import UserFactory, CourseModeFactory from student.tests.factories import UserFactory, CourseModeFactory
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.utils import override_settings from django.test.utils import override_settings
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@attr('shard_1') @attr('shard_1')
@override_settings(REGISTRATION_CODE_LENGTH=8) @override_settings(REGISTRATION_CODE_LENGTH=8)
class TestCourseRegistrationCodeStatus(ModuleStoreTestCase): class TestCourseRegistrationCodeStatus(SharedModuleStoreTestCase):
""" """
Test registration code status. Test registration code status.
""" """
@classmethod
def setUpClass(cls):
super(TestCourseRegistrationCodeStatus, cls).setUpClass()
cls.course = CourseFactory.create()
def setUp(self): def setUp(self):
super(TestCourseRegistrationCodeStatus, self).setUp() super(TestCourseRegistrationCodeStatus, self).setUp()
self.course = CourseFactory.create()
CourseModeFactory.create(course_id=self.course.id, min_price=50) CourseModeFactory.create(course_id=self.course.id, min_price=50)
self.instructor = InstructorFactory(course_key=self.course.id) self.instructor = InstructorFactory(course_key=self.course.id)
self.client.login(username=self.instructor.username, password='test') self.client.login(username=self.instructor.username, password='test')
......
...@@ -3,7 +3,7 @@ Tests for the InstructorService ...@@ -3,7 +3,7 @@ Tests for the InstructorService
""" """
import json import json
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from courseware.models import StudentModule from courseware.models import StudentModule
from instructor.services import InstructorService from instructor.services import InstructorService
...@@ -15,31 +15,31 @@ from student.tests.factories import UserFactory ...@@ -15,31 +15,31 @@ from student.tests.factories import UserFactory
@attr('shard_1') @attr('shard_1')
class InstructorServiceTests(ModuleStoreTestCase): class InstructorServiceTests(SharedModuleStoreTestCase):
""" """
Tests for the InstructorService Tests for the InstructorService
""" """
@classmethod
def setUpClass(cls):
super(InstructorServiceTests, cls).setUpClass()
cls.course = CourseFactory.create()
cls.problem_location = msk_from_problem_urlname(
cls.course.id,
'robot-some-problem-urlname'
)
cls.other_problem_location = msk_from_problem_urlname(
cls.course.id,
'robot-some-other_problem-urlname'
)
cls.problem_urlname = unicode(cls.problem_location)
cls.other_problem_urlname = unicode(cls.other_problem_location)
def setUp(self): def setUp(self):
super(InstructorServiceTests, self).setUp() super(InstructorServiceTests, self).setUp()
self.course = CourseFactory.create()
self.student = UserFactory() self.student = UserFactory()
CourseEnrollment.enroll(self.student, self.course.id) CourseEnrollment.enroll(self.student, self.course.id)
self.problem_location = msk_from_problem_urlname(
self.course.id,
'robot-some-problem-urlname'
)
self.other_problem_location = msk_from_problem_urlname(
self.course.id,
'robot-some-other_problem-urlname'
)
self.problem_urlname = unicode(self.problem_location)
self.other_problem_urlname = unicode(self.other_problem_location)
self.service = InstructorService() self.service = InstructorService()
self.module_to_reset = StudentModule.objects.create( self.module_to_reset = StudentModule.objects.create(
student=self.student, student=self.student,
......
...@@ -6,7 +6,7 @@ from django.core.urlresolvers import reverse ...@@ -6,7 +6,7 @@ from django.core.urlresolvers import reverse
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from capa.tests.response_xml_factory import StringResponseXMLFactory from capa.tests.response_xml_factory import StringResponseXMLFactory
from courseware.tests.factories import StudentModuleFactory from courseware.tests.factories import StudentModuleFactory
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
...@@ -16,7 +16,7 @@ USER_COUNT = 11 ...@@ -16,7 +16,7 @@ USER_COUNT = 11
@attr('shard_1') @attr('shard_1')
class TestGradebook(ModuleStoreTestCase): class TestGradebook(SharedModuleStoreTestCase):
""" """
Test functionality of the spoc gradebook. Sets up a course with assignments and Test functionality of the spoc gradebook. Sets up a course with assignments and
students who've scored various scores on these assignments. Base class for further students who've scored various scores on these assignments. Base class for further
...@@ -24,45 +24,48 @@ class TestGradebook(ModuleStoreTestCase): ...@@ -24,45 +24,48 @@ class TestGradebook(ModuleStoreTestCase):
""" """
grading_policy = None grading_policy = None
@classmethod
def setUpClass(cls):
super(TestGradebook, cls).setUpClass()
# Create a course with the desired grading policy (from our class attribute)
kwargs = {}
if cls.grading_policy is not None:
kwargs['grading_policy'] = cls.grading_policy
cls.course = CourseFactory.create(**kwargs)
# Now give it some content
with cls.store.bulk_operations(cls.course.id, emit_signals=False):
chapter = ItemFactory.create(
parent_location=cls.course.location,
category="sequential",
)
section = ItemFactory.create(
parent_location=chapter.location,
category="sequential",
metadata={'graded': True, 'format': 'Homework'}
)
cls.items = [
ItemFactory.create(
parent_location=section.location,
category="problem",
data=StringResponseXMLFactory().build_xml(answer='foo'),
metadata={'rerandomize': 'always'}
)
for __ in xrange(USER_COUNT - 1)
]
def setUp(self): def setUp(self):
super(TestGradebook, self).setUp() super(TestGradebook, self).setUp()
instructor = AdminFactory.create() instructor = AdminFactory.create()
self.client.login(username=instructor.username, password='test') self.client.login(username=instructor.username, password='test')
# remove the caches
modulestore().request_cache = None
modulestore().metadata_inheritance_cache_subsystem = None
kwargs = {}
if self.grading_policy is not None:
kwargs['grading_policy'] = self.grading_policy
self.course = CourseFactory.create(**kwargs)
chapter = ItemFactory.create(
parent_location=self.course.location,
category="sequential",
)
section = ItemFactory.create(
parent_location=chapter.location,
category="sequential",
metadata={'graded': True, 'format': 'Homework'}
)
self.users = [UserFactory.create() for _ in xrange(USER_COUNT)] self.users = [UserFactory.create() for _ in xrange(USER_COUNT)]
for user in self.users: for user in self.users:
CourseEnrollmentFactory.create(user=user, course_id=self.course.id) CourseEnrollmentFactory.create(user=user, course_id=self.course.id)
for i in xrange(USER_COUNT - 1): for i, item in enumerate(self.items):
category = "problem"
item = ItemFactory.create(
parent_location=section.location,
category=category,
data=StringResponseXMLFactory().build_xml(answer='foo'),
metadata={'rerandomize': 'always'}
)
for j, user in enumerate(self.users): for j, user in enumerate(self.users):
StudentModuleFactory.create( StudentModuleFactory.create(
grade=1 if i < j else 0, grade=1 if i < j else 0,
......
...@@ -14,7 +14,7 @@ from nose.plugins.attrib import attr ...@@ -14,7 +14,7 @@ from nose.plugins.attrib import attr
from courseware.field_overrides import OverrideFieldData # pylint: disable=import-error from courseware.field_overrides import OverrideFieldData # pylint: disable=import-error
from student.tests.factories import UserFactory # pylint: disable=import-error from student.tests.factories import UserFactory # pylint: disable=import-error
from xmodule.fields import Date from xmodule.fields import Date
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
...@@ -102,23 +102,17 @@ class TestParseDatetime(unittest.TestCase): ...@@ -102,23 +102,17 @@ class TestParseDatetime(unittest.TestCase):
@attr('shard_1') @attr('shard_1')
class TestFindUnit(ModuleStoreTestCase): class TestFindUnit(SharedModuleStoreTestCase):
""" """
Test the find_unit function. Test the find_unit function.
""" """
@classmethod
def setUp(self): def setUpClass(cls):
""" super(TestFindUnit, cls).setUpClass()
Fixtures. cls.course = CourseFactory.create()
""" with cls.store.bulk_operations(cls.course.id, emit_signals=False):
super(TestFindUnit, self).setUp() week1 = ItemFactory.create(parent=cls.course)
cls.homework = ItemFactory.create(parent=week1)
course = CourseFactory.create()
week1 = ItemFactory.create(parent=course)
homework = ItemFactory.create(parent=week1)
self.course = course
self.homework = homework
def test_find_unit_success(self): def test_find_unit_success(self):
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment