Commit 24a41dc5 by Bill DeRusha

Improve teams test run times by skipping signals

TNL-3126

add **kwargs to skip_signal method
parent ba1b8421
...@@ -96,3 +96,14 @@ class MockSignalHandlerMixin(object): ...@@ -96,3 +96,14 @@ class MockSignalHandlerMixin(object):
del kwargs['exclude_args'] del kwargs['exclude_args']
self.assertEqual(mock_args, args) self.assertEqual(mock_args, args)
self.assertEqual(mock_kwargs, dict(kwargs, signal=mock_signal)) self.assertEqual(mock_kwargs, dict(kwargs, signal=mock_signal))
@contextmanager
def skip_signal(signal, **kwargs):
"""
ContextManager to skip a signal by disconnecting it, yielding,
and then reconnecting the signal.
"""
signal.disconnect(**kwargs)
yield
signal.connect(**kwargs)
...@@ -88,7 +88,7 @@ class CourseTeamIndexer(object): ...@@ -88,7 +88,7 @@ class CourseTeamIndexer(object):
return settings.FEATURES.get(cls.ENABLE_SEARCH_KEY, False) return settings.FEATURES.get(cls.ENABLE_SEARCH_KEY, False)
@receiver(post_save, sender=CourseTeam) @receiver(post_save, sender=CourseTeam, dispatch_uid='teams.signals.course_team_post_save_callback')
def course_team_post_save_callback(**kwargs): def course_team_post_save_callback(**kwargs):
""" """
Reindex object after save. Reindex object after save.
......
...@@ -4,21 +4,22 @@ import json ...@@ -4,21 +4,22 @@ import json
import pytz import pytz
from datetime import datetime from datetime import datetime
from dateutil import parser from dateutil import parser
import ddt import ddt
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.db.models.signals import post_save
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from rest_framework.test import APITestCase, APIClient from rest_framework.test import APITestCase, APIClient
from courseware.tests.factories import StaffFactory from courseware.tests.factories import StaffFactory
from common.test.utils import skip_signal
from student.tests.factories import UserFactory, AdminFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, AdminFactory, CourseEnrollmentFactory
from student.models import CourseEnrollment from student.models import CourseEnrollment
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from .factories import CourseTeamFactory, LAST_ACTIVITY_AT from .factories import CourseTeamFactory, LAST_ACTIVITY_AT
from ..search_indexes import CourseTeamIndexer from ..search_indexes import CourseTeamIndexer, CourseTeam, course_team_post_save_callback
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from django_comment_common.models import Role, FORUM_ROLE_COMMUNITY_TA from django_comment_common.models import Role, FORUM_ROLE_COMMUNITY_TA
from django_comment_common.utils import seed_permissions_roles from django_comment_common.utils import seed_permissions_roles
...@@ -194,32 +195,39 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): ...@@ -194,32 +195,39 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
username='student_enrolled_other_course_not_on_team' username='student_enrolled_other_course_not_on_team'
) )
# clear the teams search index before rebuilding teams with skip_signal(
CourseTeamIndexer.engine().destroy() post_save,
receiver=course_team_post_save_callback,
# 'solar team' is intentionally lower case to test case insensitivity in name ordering sender=CourseTeam,
self.test_team_1 = CourseTeamFactory.create( dispatch_uid='teams.signals.course_team_post_save_callback'
name=u'sólar team', ):
course_id=self.test_course_1.id, # 'solar team' is intentionally lower case to test case insensitivity in name ordering
topic_id='topic_0' self.test_team_1 = CourseTeamFactory.create(
) name=u'sólar team',
self.test_team_2 = CourseTeamFactory.create(name='Wind Team', course_id=self.test_course_1.id) course_id=self.test_course_1.id,
self.test_team_3 = CourseTeamFactory.create(name='Nuclear Team', course_id=self.test_course_1.id) topic_id='topic_0'
self.test_team_4 = CourseTeamFactory.create(name='Coal Team', course_id=self.test_course_1.id, is_active=False) )
self.test_team_5 = CourseTeamFactory.create(name='Another Team', course_id=self.test_course_2.id) self.test_team_2 = CourseTeamFactory.create(name='Wind Team', course_id=self.test_course_1.id)
self.test_team_6 = CourseTeamFactory.create( self.test_team_3 = CourseTeamFactory.create(name='Nuclear Team', course_id=self.test_course_1.id)
name='Public Profile Team', self.test_team_4 = CourseTeamFactory.create(
course_id=self.test_course_2.id, name='Coal Team',
topic_id='topic_6' course_id=self.test_course_1.id,
) is_active=False
self.test_team_7 = CourseTeamFactory.create( )
name='Search', self.test_team_5 = CourseTeamFactory.create(name='Another Team', course_id=self.test_course_2.id)
description='queryable text', self.test_team_6 = CourseTeamFactory.create(
country='GS', name='Public Profile Team',
language='to', course_id=self.test_course_2.id,
course_id=self.test_course_2.id, topic_id='topic_6'
topic_id='topic_7' )
) self.test_team_7 = CourseTeamFactory.create(
name='Search',
description='queryable text',
country='GS',
language='to',
course_id=self.test_course_2.id,
topic_id='topic_7'
)
self.test_team_name_id_map = {team.name: team for team in ( self.test_team_name_id_map = {team.name: team for team in (
self.test_team_1, self.test_team_1,
...@@ -227,6 +235,8 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase): ...@@ -227,6 +235,8 @@ class TeamAPITestCase(APITestCase, SharedModuleStoreTestCase):
self.test_team_3, self.test_team_3,
self.test_team_4, self.test_team_4,
self.test_team_5, self.test_team_5,
self.test_team_6,
self.test_team_7,
)} )}
for user, course in [('staff', self.test_course_1), ('course_staff', self.test_course_1)]: for user, course in [('staff', self.test_course_1), ('course_staff', self.test_course_1)]:
...@@ -455,9 +465,15 @@ class TestListTeamsAPI(TeamAPITestCase): ...@@ -455,9 +465,15 @@ class TestListTeamsAPI(TeamAPITestCase):
# Make "solar team" the most recently active team. # Make "solar team" the most recently active team.
# The CourseTeamFactory sets the last_activity_at to a fixed time (in the past), so all of the # The CourseTeamFactory sets the last_activity_at to a fixed time (in the past), so all of the
# other teams have the same last_activity_at. # other teams have the same last_activity_at.
solar_team = self.test_team_name_id_map[u'sólar team'] with skip_signal(
solar_team.last_activity_at = datetime.utcnow().replace(tzinfo=pytz.utc) post_save,
solar_team.save() receiver=course_team_post_save_callback,
sender=CourseTeam,
dispatch_uid='teams.signals.course_team_post_save_callback'
):
solar_team = self.test_team_name_id_map[u'sólar team']
solar_team.last_activity_at = datetime.utcnow().replace(tzinfo=pytz.utc)
solar_team.save()
data = {'order_by': field} if field else {} data = {'order_by': field} if field else {}
self.verify_names(data, status, names) self.verify_names(data, status, names)
...@@ -508,6 +524,12 @@ class TestListTeamsAPI(TeamAPITestCase): ...@@ -508,6 +524,12 @@ class TestListTeamsAPI(TeamAPITestCase):
) )
@ddt.unpack @ddt.unpack
def test_text_search(self, text_search, expected_team_names): def test_text_search(self, text_search, expected_team_names):
# clear out the teams search index before reindexing
CourseTeamIndexer.engine().destroy()
for team in self.test_team_name_id_map.values():
CourseTeamIndexer.index(team)
self.verify_names( self.verify_names(
{'course_id': self.test_course_2.id, 'text_search': text_search}, {'course_id': self.test_course_2.id, 'text_search': text_search},
200, 200,
...@@ -797,13 +819,19 @@ class TestListTopicsAPI(TeamAPITestCase): ...@@ -797,13 +819,19 @@ class TestListTopicsAPI(TeamAPITestCase):
) )
@ddt.unpack @ddt.unpack
def test_order_by(self, field, status, names, expected_ordering): def test_order_by(self, field, status, names, expected_ordering):
# Add 2 teams to "Nuclear Power", which previously had no teams. with skip_signal(
CourseTeamFactory.create( post_save,
name=u'Nuclear Team 1', course_id=self.test_course_1.id, topic_id='topic_2' receiver=course_team_post_save_callback,
) sender=CourseTeam,
CourseTeamFactory.create( dispatch_uid='teams.signals.course_team_post_save_callback'
name=u'Nuclear Team 2', course_id=self.test_course_1.id, topic_id='topic_2' ):
) # Add 2 teams to "Nuclear Power", which previously had no teams.
CourseTeamFactory.create(
name=u'Nuclear Team 1', course_id=self.test_course_1.id, topic_id='topic_2'
)
CourseTeamFactory.create(
name=u'Nuclear Team 2', course_id=self.test_course_1.id, topic_id='topic_2'
)
data = {'course_id': self.test_course_1.id} data = {'course_id': self.test_course_1.id}
if field: if field:
data['order_by'] = field data['order_by'] = field
...@@ -817,13 +845,19 @@ class TestListTopicsAPI(TeamAPITestCase): ...@@ -817,13 +845,19 @@ class TestListTopicsAPI(TeamAPITestCase):
Ensure that the secondary sort (alphabetical) when primary sort is team_count Ensure that the secondary sort (alphabetical) when primary sort is team_count
works across pagination boundaries. works across pagination boundaries.
""" """
# Add 2 teams to "Wind Power", which previously had no teams. with skip_signal(
CourseTeamFactory.create( post_save,
name=u'Wind Team 1', course_id=self.test_course_1.id, topic_id='topic_1' receiver=course_team_post_save_callback,
) sender=CourseTeam,
CourseTeamFactory.create( dispatch_uid='teams.signals.course_team_post_save_callback'
name=u'Wind Team 2', course_id=self.test_course_1.id, topic_id='topic_1' ):
) # Add 2 teams to "Wind Power", which previously had no teams.
CourseTeamFactory.create(
name=u'Wind Team 1', course_id=self.test_course_1.id, topic_id='topic_1'
)
CourseTeamFactory.create(
name=u'Wind Team 2', course_id=self.test_course_1.id, topic_id='topic_1'
)
topics = self.get_topics_list(data={ topics = self.get_topics_list(data={
'course_id': self.test_course_1.id, 'course_id': self.test_course_1.id,
......
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