Commit 9d74b4d2 by John Eskew

Merge pull request #11700 from edx/jeskew/my_unittest_speedups

Unit test speedups - Add context manager to SharedModuleStoreTestCase.
parents 9de6b912 b777530d
......@@ -4,6 +4,7 @@ Modulestore configuration for test cases.
"""
import functools
from uuid import uuid4
from contextlib import contextmanager
from mock import patch
......@@ -267,9 +268,10 @@ class SharedModuleStoreTestCase(TestCase):
MODULESTORE = mixed_store_config(mkdtemp_clean(), {}, include_xml=False)
@classmethod
def setUpClass(cls):
super(SharedModuleStoreTestCase, cls).setUpClass()
def _setUpModuleStore(cls): # pylint: disable=invalid-name
"""
Set up the modulestore for an entire test class.
"""
cls._settings_override = override_settings(MODULESTORE=cls.MODULESTORE)
cls._settings_override.__enter__()
XMODULE_FACTORY_LOCK.enable()
......@@ -277,6 +279,40 @@ class SharedModuleStoreTestCase(TestCase):
cls.store = modulestore()
@classmethod
@contextmanager
def setUpClassAndTestData(cls): # pylint: disable=invalid-name
"""
For use when the test class has a setUpTestData() method that uses variables
that are setup during setUpClass() of the same test class.
Use it like so:
@classmethod
def setUpClass(cls):
with super(MyTestClass, cls).setUpClassAndTestData():
<all the cls.setUpClass() setup code that performs modulestore setup...>
@classmethod
def setUpTestData(cls):
<all the setup code that creates Django models per test class...>
<these models can use variables (courses) setup in setUpClass() above>
"""
cls._setUpModuleStore()
# Now yield to allow the test class to run its setUpClass() setup code.
yield
# Now call the base class, which calls back into the test class's setUpTestData().
super(SharedModuleStoreTestCase, cls).setUpClass()
@classmethod
def setUpClass(cls):
"""
For use when the test class has no setUpTestData() method -or-
when that method does not use variable set up in setUpClass().
"""
super(SharedModuleStoreTestCase, cls).setUpClass()
cls._setUpModuleStore()
@classmethod
def tearDownClass(cls):
drop_mongo_collections() # pylint: disable=no-value-for-parameter
clear_all_caches()
......
......@@ -25,16 +25,12 @@ class TestCCXModulestoreWrapper(SharedModuleStoreTestCase):
@classmethod
def setUpClass(cls):
super(TestCCXModulestoreWrapper, cls).setUpClass()
cls.course = course = CourseFactory.create()
cls.mooc_start = start = datetime.datetime(
2010, 5, 12, 2, 42, tzinfo=pytz.UTC
)
cls.mooc_due = due = datetime.datetime(
2010, 7, 7, 0, 0, tzinfo=pytz.UTC
)
cls.course = CourseFactory.create()
start = datetime.datetime(2010, 5, 12, 2, 42, tzinfo=pytz.UTC)
due = datetime.datetime(2010, 7, 7, 0, 0, tzinfo=pytz.UTC)
# Create a course outline
cls.chapters = chapters = [
ItemFactory.create(start=start, parent=course) for _ in xrange(2)
ItemFactory.create(start=start, parent=cls.course) for _ in xrange(2)
]
cls.sequentials = sequentials = [
ItemFactory.create(parent=c) for _ in xrange(2) for c in chapters
......@@ -48,20 +44,24 @@ class TestCCXModulestoreWrapper(SharedModuleStoreTestCase):
ItemFactory.create(parent=v, category='html') for _ in xrange(2) for v in verticals
]
@classmethod
def setUpTestData(cls):
"""
Set up models for the whole TestCase.
"""
cls.user = UserFactory.create()
# Create instructor account
cls.coach = AdminFactory.create()
def setUp(self):
"""
Set up tests
"""
super(TestCCXModulestoreWrapper, self).setUp()
self.user = UserFactory.create()
# Create instructor account
coach = AdminFactory.create()
self.ccx = ccx = CustomCourseForEdX(
course_id=self.course.id,
display_name='Test CCX',
coach=coach
coach=self.coach
)
ccx.save()
......@@ -132,6 +132,7 @@ class TestCCXModulestoreWrapper(SharedModuleStoreTestCase):
def test_publication_api(self):
"""verify that we can correctly discern a published item by ccx key"""
with self.store.bulk_operations(self.ccx_locator):
for expected in self.blocks:
block_key = self.ccx_locator.make_usage_key(
expected.location.block_type, expected.location.block_id
......
......@@ -7,7 +7,7 @@ from nose.plugins.attrib import attr
from django.test.utils import override_settings
from xblock.field_data import DictFieldData
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from ..field_overrides import (
disable_overrides,
......@@ -23,14 +23,21 @@ TESTUSER = "testuser"
@attr('shard_1')
@override_settings(FIELD_OVERRIDE_PROVIDERS=(
'courseware.tests.test_field_overrides.TestOverrideProvider',))
class OverrideFieldDataTests(ModuleStoreTestCase):
class OverrideFieldDataTests(SharedModuleStoreTestCase):
"""
Tests for `OverrideFieldData`.
"""
@classmethod
def setUpClass(cls):
"""
Course is created here and shared by all the class's tests.
"""
super(OverrideFieldDataTests, cls).setUpClass()
cls.course = CourseFactory.create(enable_ccx=True)
def setUp(self):
super(OverrideFieldDataTests, self).setUp()
self.course = CourseFactory.create(enable_ccx=True)
OverrideFieldData.provider_classes = None
def tearDown(self):
......
......@@ -200,7 +200,7 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
@classmethod
def setUpClass(cls):
super(TeamAPITestCase, cls).setUpClass()
with super(TeamAPITestCase, cls).setUpClassAndTestData():
teams_configuration_1 = {
'topics':
[
......@@ -246,43 +246,44 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
teams_configuration=teams_configuration_2
)
def setUp(self):
super(TeamAPITestCase, self).setUp()
self.topics_count = 4
self.users = {
'staff': AdminFactory.create(password=self.test_password),
'course_staff': StaffFactory.create(course_key=self.test_course_1.id, password=self.test_password)
@classmethod
def setUpTestData(cls):
super(TeamAPITestCase, cls).setUpTestData()
cls.topics_count = 4
cls.users = {
'staff': AdminFactory.create(password=cls.test_password),
'course_staff': StaffFactory.create(course_key=cls.test_course_1.id, password=cls.test_password)
}
self.create_and_enroll_student(username='student_enrolled')
self.create_and_enroll_student(username='student_enrolled_not_on_team')
self.create_and_enroll_student(username='student_unenrolled', courses=[])
cls.create_and_enroll_student(username='student_enrolled')
cls.create_and_enroll_student(username='student_enrolled_not_on_team')
cls.create_and_enroll_student(username='student_unenrolled', courses=[])
# Make this student a community TA.
self.create_and_enroll_student(username='community_ta')
seed_permissions_roles(self.test_course_1.id)
community_ta_role = Role.objects.get(name=FORUM_ROLE_COMMUNITY_TA, course_id=self.test_course_1.id)
community_ta_role.users.add(self.users['community_ta'])
cls.create_and_enroll_student(username='community_ta')
seed_permissions_roles(cls.test_course_1.id)
community_ta_role = Role.objects.get(name=FORUM_ROLE_COMMUNITY_TA, course_id=cls.test_course_1.id)
community_ta_role.users.add(cls.users['community_ta'])
# This student is enrolled in both test courses and is a member of a team in each course, but is not on the
# same team as student_enrolled.
self.create_and_enroll_student(
courses=[self.test_course_1, self.test_course_2],
cls.create_and_enroll_student(
courses=[cls.test_course_1, cls.test_course_2],
username='student_enrolled_both_courses_other_team'
)
# Make this student have a public profile
self.create_and_enroll_student(
courses=[self.test_course_2],
cls.create_and_enroll_student(
courses=[cls.test_course_2],
username='student_enrolled_public_profile'
)
profile = self.users['student_enrolled_public_profile'].profile
profile = cls.users['student_enrolled_public_profile'].profile
profile.year_of_birth = 1970
profile.save()
# This student is enrolled in the other course, but not yet a member of a team. This is to allow
# course_2 to use a max_team_size of 1 without breaking other tests on course_1
self.create_and_enroll_student(
courses=[self.test_course_2],
cls.create_and_enroll_student(
courses=[cls.test_course_2],
username='student_enrolled_other_course_not_on_team'
)
......@@ -292,58 +293,58 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
sender=CourseTeam,
dispatch_uid='teams.signals.course_team_post_save_callback'
):
self.solar_team = CourseTeamFactory.create(
cls.solar_team = CourseTeamFactory.create(
name=u'Sólar team',
course_id=self.test_course_1.id,
course_id=cls.test_course_1.id,
topic_id='topic_0'
)
self.wind_team = CourseTeamFactory.create(name='Wind Team', course_id=self.test_course_1.id)
self.nuclear_team = CourseTeamFactory.create(name='Nuclear Team', course_id=self.test_course_1.id)
self.another_team = CourseTeamFactory.create(name='Another Team', course_id=self.test_course_2.id)
self.public_profile_team = CourseTeamFactory.create(
cls.wind_team = CourseTeamFactory.create(name='Wind Team', course_id=cls.test_course_1.id)
cls.nuclear_team = CourseTeamFactory.create(name='Nuclear Team', course_id=cls.test_course_1.id)
cls.another_team = CourseTeamFactory.create(name='Another Team', course_id=cls.test_course_2.id)
cls.public_profile_team = CourseTeamFactory.create(
name='Public Profile Team',
course_id=self.test_course_2.id,
course_id=cls.test_course_2.id,
topic_id='topic_6'
)
self.search_team = CourseTeamFactory.create(
cls.search_team = CourseTeamFactory.create(
name='Search',
description='queryable text',
country='GS',
language='to',
course_id=self.test_course_2.id,
course_id=cls.test_course_2.id,
topic_id='topic_7'
)
self.chinese_team = CourseTeamFactory.create(
cls.chinese_team = CourseTeamFactory.create(
name=u'著文企臺個',
description=u'共樣地面較,件展冷不護者這與民教過住意,國制銀產物助音是勢一友',
country='CN',
language='zh_HANS',
course_id=self.test_course_2.id,
course_id=cls.test_course_2.id,
topic_id='topic_7'
)
self.test_team_name_id_map = {team.name: team for team in (
self.solar_team,
self.wind_team,
self.nuclear_team,
self.another_team,
self.public_profile_team,
self.search_team,
self.chinese_team,
cls.test_team_name_id_map = {team.name: team for team in (
cls.solar_team,
cls.wind_team,
cls.nuclear_team,
cls.another_team,
cls.public_profile_team,
cls.search_team,
cls.chinese_team,
)}
for user, course in [('staff', self.test_course_1), ('course_staff', self.test_course_1)]:
for user, course in [('staff', cls.test_course_1), ('course_staff', cls.test_course_1)]:
CourseEnrollment.enroll(
self.users[user], course.id, check_access=True
cls.users[user], course.id, check_access=True
)
# Django Rest Framework v3 requires us to pass a request to serializers
# that have URL fields. Since we're invoking this code outside the context
# of a request, we need to simulate that there's a request.
self.solar_team.add_user(self.users['student_enrolled'])
self.nuclear_team.add_user(self.users['student_enrolled_both_courses_other_team'])
self.another_team.add_user(self.users['student_enrolled_both_courses_other_team'])
self.public_profile_team.add_user(self.users['student_enrolled_public_profile'])
cls.solar_team.add_user(cls.users['student_enrolled'])
cls.nuclear_team.add_user(cls.users['student_enrolled_both_courses_other_team'])
cls.another_team.add_user(cls.users['student_enrolled_both_courses_other_team'])
cls.public_profile_team.add_user(cls.users['student_enrolled_public_profile'])
def build_membership_data_raw(self, username, team):
"""Assembles a membership creation payload based on the raw values provided."""
......@@ -353,21 +354,22 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
"""Assembles a membership creation payload based on the username and team model provided."""
return self.build_membership_data_raw(self.users[username].username, team.team_id)
def create_and_enroll_student(self, courses=None, username=None):
@classmethod
def create_and_enroll_student(cls, courses=None, username=None):
""" Creates a new student and enrolls that student in the course.
Adds the new user to the self.users dictionary with the username as the key.
Adds the new user to the cls.users dictionary with the username as the key.
Returns the username once the user has been created.
"""
if username is not None:
user = UserFactory.create(password=self.test_password, username=username)
user = UserFactory.create(password=cls.test_password, username=username)
else:
user = UserFactory.create(password=self.test_password)
courses = courses if courses is not None else [self.test_course_1]
user = UserFactory.create(password=cls.test_password)
courses = courses if courses is not None else [cls.test_course_1]
for course in courses:
CourseEnrollment.enroll(user, course.id, check_access=True)
self.users[user.username] = user
cls.users[user.username] = user
return user.username
......
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