Moved sys.path-extending decorator to django.test.utils and used throughout test suite.

Thanks Aymeric for the suggestion.
This commit is contained in:
Carl Meyer 2014-01-25 22:50:40 -07:00
parent 8bc3780b67
commit ca95f8e435
6 changed files with 85 additions and 94 deletions

View File

@ -526,3 +526,15 @@ class TransRealMixin(object):
requires_tz_support = skipUnless(TZ_SUPPORT,
"This test relies on the ability to run a program in an arbitrary "
"time zone, but your operating system isn't able to do that.")
@contextmanager
def extend_sys_path(*paths):
"""Context manager to temporarily add paths to sys.path."""
_orig_sys_path = sys.path[:]
sys.path.extend(paths)
try:
yield
finally:
sys.path = _orig_sys_path

View File

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import os
import sys
from django.apps import apps
from django.test import TestCase
from django.test.utils import extend_sys_path
from django.utils._os import upath
from django.utils import six
@ -12,56 +12,54 @@ from django.utils import six
class EggLoadingTest(TestCase):
def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
def tearDown(self):
apps.clear_cache()
sys.path = self.old_path
def test_egg1(self):
"""Models module can be loaded from an app in an egg"""
egg_name = '%s/modelapp.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
del apps.all_models['app_with_models']
def test_egg2(self):
"""Loading an app from an egg that has no models returns no models (and no error)"""
egg_name = '%s/nomodelapp.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
del apps.all_models['app_no_models']
def test_egg3(self):
"""Models module can be loaded from an app located under an egg's top-level package"""
egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['omelet.app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['omelet.app_with_models']):
models_module = apps.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
del apps.all_models['app_with_models']
def test_egg4(self):
"""Loading an app with no models from under the top-level egg package generates no error"""
egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['omelet.app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['omelet.app_no_models']):
models_module = apps.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
del apps.all_models['app_no_models']
def test_egg5(self):
"""Loading an app from an egg that has an import error in its models module raises that error"""
egg_name = '%s/brokenapp.egg' % self.egg_dir
sys.path.append(egg_name)
with six.assertRaisesRegex(self, ImportError, 'modelz'):
with self.settings(INSTALLED_APPS=['broken_app']):
pass
with extend_sys_path(egg_name):
with six.assertRaisesRegex(self, ImportError, 'modelz'):
with self.settings(INSTALLED_APPS=['broken_app']):
pass
class GetModelsTest(TestCase):

View File

@ -1,6 +1,5 @@
from __future__ import absolute_import, unicode_literals
from contextlib import contextmanager
import os
import sys
from unittest import skipUnless
@ -10,6 +9,7 @@ from django.apps.registry import Apps
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.test import TestCase, override_settings
from django.test.utils import extend_sys_path
from django.utils._os import upath
from django.utils import six
@ -189,21 +189,11 @@ class NamespacePackageAppTests(TestCase):
other_location = os.path.join(HERE, 'namespace_package_other_base')
app_path = os.path.join(base_location, 'nsapp')
@contextmanager
def add_to_path(self, *paths):
"""Context manager to temporarily add paths to sys.path."""
_orig_sys_path = sys.path[:]
sys.path.extend(paths)
try:
yield
finally:
sys.path = _orig_sys_path
def test_single_path(self):
"""
A Py3.3+ namespace package can be an app if it has only one path.
"""
with self.add_to_path(self.base_location):
with extend_sys_path(self.base_location):
with self.settings(INSTALLED_APPS=['nsapp']):
app_config = apps.get_app_config('nsapp')
self.assertEqual(app_config.path, upath(self.app_path))
@ -218,7 +208,7 @@ class NamespacePackageAppTests(TestCase):
"""
# Temporarily add two directories to sys.path that both contain
# components of the "nsapp" package.
with self.add_to_path(self.base_location, self.other_location):
with extend_sys_path(self.base_location, self.other_location):
with self.assertRaises(ImproperlyConfigured):
with self.settings(INSTALLED_APPS=['nsapp']):
pass
@ -229,7 +219,7 @@ class NamespacePackageAppTests(TestCase):
"""
# Temporarily add two directories to sys.path that both contain
# components of the "nsapp" package.
with self.add_to_path(self.base_location, self.other_location):
with extend_sys_path(self.base_location, self.other_location):
with self.settings(INSTALLED_APPS=['nsapp.apps.NSAppConfig']):
app_config = apps.get_app_config('nsapp')
self.assertEqual(app_config.path, upath(self.app_path))

View File

@ -1,11 +1,10 @@
from __future__ import absolute_import, unicode_literals
import os
import sys
from django.core.management import call_command
from django.test import TestCase, TransactionTestCase
from django.test.utils import override_system_checks
from django.test.utils import override_system_checks, extend_sys_path
from django.utils._os import upath
from .models import (ConcreteModel, ConcreteModelSubclass,
@ -20,23 +19,17 @@ class ProxyModelInheritanceTests(TransactionTestCase):
"""
available_apps = []
def setUp(self):
self.old_sys_path = sys.path[:]
sys.path.append(os.path.dirname(os.path.abspath(upath(__file__))))
def tearDown(self):
sys.path = self.old_sys_path
# `auth` app is imported, but not installed in this test, so we need to
# exclude checks registered by this app.
@override_system_checks([])
def test_table_exists(self):
with self.modify_settings(INSTALLED_APPS={'append': ['app1', 'app2']}):
call_command('migrate', verbosity=0)
from app1.models import ProxyModel
from app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0)
self.assertEqual(ProxyModel.objects.all().count(), 0)
with extend_sys_path(os.path.dirname(os.path.abspath(upath(__file__)))):
with self.modify_settings(INSTALLED_APPS={'append': ['app1', 'app2']}):
call_command('migrate', verbosity=0)
from app1.models import ProxyModel
from app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0)
self.assertEqual(ProxyModel.objects.all().count(), 0)
class MultiTableInheritanceProxyTest(TestCase):

View File

@ -22,7 +22,8 @@ from django.template import (base as template_base, loader, Context,
from django.template.loaders import app_directories, filesystem, cached
from django.test import RequestFactory, TestCase
from django.test.utils import (setup_test_template_loader,
restore_template_loaders, override_settings, TransRealMixin)
restore_template_loaders, override_settings, TransRealMixin,
extend_sys_path)
from django.utils.encoding import python_2_unicode_compatible
from django.utils.formats import date_format
from django.utils._os import upath
@ -1857,13 +1858,11 @@ class TemplateTests(TransRealMixin, TestCase):
class TemplateTagLoading(TestCase):
def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
self.old_tag_modules = template_base.templatetags_modules
template_base.templatetags_modules = []
def tearDown(self):
sys.path = self.old_path
template_base.templatetags_modules = self.old_tag_modules
def test_load_error(self):
@ -1878,23 +1877,23 @@ class TemplateTagLoading(TestCase):
def test_load_error_egg(self):
ttext = "{% load broken_egg %}"
egg_name = '%s/tagsegg.egg' % self.egg_dir
sys.path.append(egg_name)
with self.assertRaises(template.TemplateSyntaxError):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
try:
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
except template.TemplateSyntaxError as e:
self.assertTrue('ImportError' in e.args[0])
self.assertTrue('Xtemplate' in e.args[0])
with extend_sys_path(egg_name):
with self.assertRaises(template.TemplateSyntaxError):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
try:
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
except template.TemplateSyntaxError as e:
self.assertTrue('ImportError' in e.args[0])
self.assertTrue('Xtemplate' in e.args[0])
def test_load_working_egg(self):
ttext = "{% load working_egg %}"
egg_name = '%s/tagsegg.egg' % self.egg_dir
sys.path.append(egg_name)
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
with extend_sys_path(egg_name):
with self.settings(INSTALLED_APPS=['tagsegg']):
template.Template(ttext)
class RequestContextTests(unittest.TestCase):

View File

@ -7,6 +7,7 @@ from zipimport import zipimporter
from django.core.exceptions import ImproperlyConfigured
from django.test import SimpleTestCase, modify_settings
from django.test.utils import extend_sys_path
from django.utils import six
from django.utils.module_loading import autodiscover_modules, import_by_path, module_has_submodule
from django.utils._os import upath
@ -54,11 +55,9 @@ class DefaultLoader(unittest.TestCase):
class EggLoader(unittest.TestCase):
def setUp(self):
self.old_path = sys.path[:]
self.egg_dir = '%s/eggs' % os.path.dirname(upath(__file__))
def tearDown(self):
sys.path = self.old_path
sys.path_importer_cache.clear()
sys.modules.pop('egg_module.sub1.sub2.bad_module', None)
@ -72,40 +71,40 @@ class EggLoader(unittest.TestCase):
def test_shallow_loader(self):
"Module existence can be tested inside eggs"
egg_name = '%s/test_egg.egg' % self.egg_dir
sys.path.append(egg_name)
egg_module = import_module('egg_module')
with extend_sys_path(egg_name):
egg_module = import_module('egg_module')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.good_module')
self.assertEqual(mod.content, 'Good Module')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.good_module')
self.assertEqual(mod.content, 'Good Module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.bad_module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.bad_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.no_such_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.no_such_module')
def test_deep_loader(self):
"Modules deep inside an egg can still be tested for existence"
egg_name = '%s/test_egg.egg' % self.egg_dir
sys.path.append(egg_name)
egg_module = import_module('egg_module.sub1.sub2')
with extend_sys_path(egg_name):
egg_module = import_module('egg_module.sub1.sub2')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.sub1.sub2.good_module')
self.assertEqual(mod.content, 'Deep Good Module')
# An importable child
self.assertTrue(module_has_submodule(egg_module, 'good_module'))
mod = import_module('egg_module.sub1.sub2.good_module')
self.assertEqual(mod.content, 'Deep Good Module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.bad_module')
# A child that exists, but will generate an import error if loaded
self.assertTrue(module_has_submodule(egg_module, 'bad_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.bad_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')
# A child that doesn't exist
self.assertFalse(module_has_submodule(egg_module, 'no_such_module'))
self.assertRaises(ImportError, import_module, 'egg_module.sub1.sub2.no_such_module')
class ModuleImportTestCase(unittest.TestCase):