From 6c24694a7ce16eea38d6af31a414aef70fad928a Mon Sep 17 00:00:00 2001
From: Calen Pennington <cale@edx.org>
Date: Thu, 6 Jun 2013 12:48:59 -0400
Subject: [PATCH] Fix tests that vary urls.py

Create a mixin class that can be used for tests that customize urls.py
to force django to reload it, so that they don't break other tests.
---
 common/djangoapps/mitxmako/tests.py           |  9 ++---
 common/djangoapps/util/testing.py             | 34 +++++++++++++++++++
 .../django_comment_client/base/tests.py       | 15 +++++++-
 lms/envs/test.py                              |  6 ++--
 4 files changed, 55 insertions(+), 9 deletions(-)
 create mode 100644 common/djangoapps/util/testing.py

diff --git a/common/djangoapps/mitxmako/tests.py b/common/djangoapps/mitxmako/tests.py
index f419daa6817..e7e56a94724 100644
--- a/common/djangoapps/mitxmako/tests.py
+++ b/common/djangoapps/mitxmako/tests.py
@@ -1,18 +1,15 @@
 from django.test import TestCase
 from django.test.utils import override_settings
 from django.core.urlresolvers import reverse
-from django.conf import settings
 from mitxmako.shortcuts import marketing_link
 from mock import patch
-from nose.plugins.skip import SkipTest
+from util.testing import UrlResetMixin
 
-class ShortcutsTests(TestCase):
+
+class ShortcutsTests(UrlResetMixin, TestCase):
     """
     Test the mitxmako shortcuts file
     """
-    # TODO: fix this test. It is causing intermittent test failures on
-    # subsequent tests due to the way urls are loaded
-    raise SkipTest()
     @override_settings(MKTG_URLS={'ROOT': 'dummy-root', 'ABOUT': '/about-us'})
     @override_settings(MKTG_URL_LINK_MAP={'ABOUT': 'login'})
     def test_marketing_link(self):
diff --git a/common/djangoapps/util/testing.py b/common/djangoapps/util/testing.py
new file mode 100644
index 00000000000..d33f1c8f8b9
--- /dev/null
+++ b/common/djangoapps/util/testing.py
@@ -0,0 +1,34 @@
+import sys
+
+from django.conf import settings
+from django.core.urlresolvers import clear_url_caches
+
+
+class UrlResetMixin(object):
+    """Mixin to reset urls.py before and after a test
+
+    Django memoizes the function that reads the urls module (whatever module
+    urlconf names). The module itself is also stored by python in sys.modules.
+    To fully reload it, we need to reload the python module, and also clear django's
+    cache of the parsed urls.
+
+    However, the order in which we do this doesn't matter, because neither one will
+    get reloaded until the next request
+
+    Doing this is expensive, so it should only be added to tests that modify settings
+    that affect the contents of urls.py
+    """
+
+    def _reset_urls(self, urlconf=None):
+        if urlconf is None:
+            urlconf = settings.ROOT_URLCONF
+
+        if urlconf in sys.modules:
+            reload(sys.modules[urlconf])
+        clear_url_caches()
+
+    def setUp(self):
+        """Reset django default urlconf before tests and after tests"""
+        super(UrlResetMixin, self).setUp()
+        self._reset_urls()
+        self.addCleanup(self._reset_urls)
diff --git a/lms/djangoapps/django_comment_client/base/tests.py b/lms/djangoapps/django_comment_client/base/tests.py
index 3e06402ddda..aa5b657bd61 100644
--- a/lms/djangoapps/django_comment_client/base/tests.py
+++ b/lms/djangoapps/django_comment_client/base/tests.py
@@ -1,5 +1,6 @@
 import logging
 
+from django.conf import settings
 from django.test.utils import override_settings
 from django.test.client import Client
 from django.contrib.auth.models import User
@@ -8,6 +9,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
 from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
 from django.core.urlresolvers import reverse
 from django.core.management import call_command
+from util.testing import UrlResetMixin
 
 from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
 from nose.tools import assert_true, assert_equal
@@ -18,8 +20,19 @@ log = logging.getLogger(__name__)
 
 @override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
 @patch('comment_client.utils.requests.request')
-class ViewsTestCase(ModuleStoreTestCase):
+class ViewsTestCase(UrlResetMixin, ModuleStoreTestCase):
     def setUp(self):
+
+        # This feature affects the contents of urls.py, so we change
+        # it before the call to super.setUp() which reloads urls.py (because
+        # of the UrlResetMixin)
+
+        # This setting is cleaned up at the end of the test by @override_settings, which
+        # restores all of the old settings
+        settings.MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
+
+        super(ViewsTestCase, self).setUp()
+
         # create a course
         self.course = CourseFactory.create(org='MITx', course='999',
                                            display_name='Robot Super Course')
diff --git a/lms/envs/test.py b/lms/envs/test.py
index 6691d50106e..3ccfa240144 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -20,8 +20,10 @@ from path import path
 # can test everything else :)
 MITX_FEATURES['DISABLE_START_DATES'] = True
 
-# Until we have discussion actually working in test mode, just turn it off
-MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = True
+# Most tests don't use the discussion service, so we turn it off to speed them up.
+# Tests that do can enable this flag, but must use the UrlResetMixin class to force urls.py
+# to reload
+MITX_FEATURES['ENABLE_DISCUSSION_SERVICE'] = False
 
 MITX_FEATURES['ENABLE_SERVICE_STATUS'] = True
 
-- 
GitLab