diff --git a/tests/templates/priority/foo.html b/tests/template_tests/other_templates/priority/foo.html
similarity index 100%
rename from tests/templates/priority/foo.html
rename to tests/template_tests/other_templates/priority/foo.html
diff --git a/tests/template_tests/templates/index.html b/tests/template_tests/templates/index.html
new file mode 100644
index 0000000000..9015a7a32c
--- /dev/null
+++ b/tests/template_tests/templates/index.html
@@ -0,0 +1 @@
+index
diff --git a/tests/template_tests/test_engine.py b/tests/template_tests/test_engine.py
new file mode 100644
index 0000000000..77f3c995b5
--- /dev/null
+++ b/tests/template_tests/test_engine.py
@@ -0,0 +1,125 @@
+import os
+
+from django.template import Context
+from django.template.engine import Engine
+from django.test import SimpleTestCase, ignore_warnings
+from django.utils.deprecation import RemovedInDjango20Warning
+
+from .utils import ROOT, TEMPLATE_DIR
+
+OTHER_DIR = os.path.join(ROOT, 'other_templates')
+
+
+@ignore_warnings(category=RemovedInDjango20Warning)
+class DeprecatedRenderToStringTest(SimpleTestCase):
+
+    def setUp(self):
+        self.engine = Engine(dirs=[TEMPLATE_DIR])
+
+    def test_basic_context(self):
+        self.assertEqual(
+            self.engine.render_to_string('test_context.html', {'obj': 'test'}),
+            'obj:test\n',
+        )
+
+    def test_existing_context_kept_clean(self):
+        context = Context({'obj': 'before'})
+        output = self.engine.render_to_string(
+            'test_context.html', {'obj': 'after'}, context_instance=context,
+        )
+        self.assertEqual(output, 'obj:after\n')
+        self.assertEqual(context['obj'], 'before')
+
+    def test_no_empty_dict_pushed_to_stack(self):
+        """
+        #21741 -- An empty dict should not be pushed to the context stack when
+        render_to_string is called without a context argument.
+        """
+
+        # The stack should have a length of 1, corresponding to the builtins
+        self.assertEqual(
+            '1',
+            self.engine.render_to_string('test_context_stack.html').strip(),
+        )
+        self.assertEqual(
+            '1',
+            self.engine.render_to_string(
+                'test_context_stack.html',
+                context_instance=Context()
+            ).strip(),
+        )
+
+
+class LoaderTests(SimpleTestCase):
+
+    def test_debug_nodelist_name(self):
+        engine = Engine(dirs=[TEMPLATE_DIR], debug=True)
+        template_name = 'index.html'
+        template = engine.get_template(template_name)
+        name = template.nodelist[0].source[0].name
+        self.assertTrue(name.endswith(template_name))
+
+    def test_origin(self):
+        engine = Engine(dirs=[TEMPLATE_DIR], debug=True)
+        template = engine.get_template('index.html')
+        self.assertEqual(template.origin.loadname, 'index.html')
+
+    def test_origin_debug_false(self):
+        engine = Engine(dirs=[TEMPLATE_DIR], debug=False)
+        template = engine.get_template('index.html')
+        self.assertEqual(template.origin, None)
+
+    def test_loader_priority(self):
+        """
+        #21460 -- Check that the order of template loader works.
+        """
+        loaders = [
+            'django.template.loaders.filesystem.Loader',
+            'django.template.loaders.app_directories.Loader',
+        ]
+        engine = Engine(dirs=[OTHER_DIR, TEMPLATE_DIR], loaders=loaders)
+        template = engine.get_template('priority/foo.html')
+        self.assertEqual(template.render(Context()), 'priority\n')
+
+    def test_cached_loader_priority(self):
+        """
+        Check that the order of template loader works. Refs #21460.
+        """
+        loaders = [
+            ('django.template.loaders.cached.Loader', [
+                'django.template.loaders.filesystem.Loader',
+                'django.template.loaders.app_directories.Loader',
+            ]),
+        ]
+        engine = Engine(dirs=[OTHER_DIR, TEMPLATE_DIR], loaders=loaders)
+
+        template = engine.get_template('priority/foo.html')
+        self.assertEqual(template.render(Context()), 'priority\n')
+
+        template = engine.get_template('priority/foo.html')
+        self.assertEqual(template.render(Context()), 'priority\n')
+
+
+@ignore_warnings(category=RemovedInDjango20Warning)
+class TemplateDirsOverrideTests(SimpleTestCase):
+    DIRS = ((OTHER_DIR, ), [OTHER_DIR])
+
+    def setUp(self):
+        self.engine = Engine()
+
+    def test_render_to_string(self):
+        for dirs in self.DIRS:
+            self.assertEqual(
+                self.engine.render_to_string('test_dirs.html', dirs=dirs),
+                'spam eggs\n',
+            )
+
+    def test_get_template(self):
+        for dirs in self.DIRS:
+            template = self.engine.get_template('test_dirs.html', dirs=dirs)
+            self.assertEqual(template.render(Context()), 'spam eggs\n')
+
+    def test_select_template(self):
+        for dirs in self.DIRS:
+            template = self.engine.select_template(['test_dirs.html'], dirs=dirs)
+            self.assertEqual(template.render(Context()), 'spam eggs\n')
diff --git a/tests/template_tests/test_loaders.py b/tests/template_tests/test_loaders.py
index e8f5298851..5eb4f64cea 100644
--- a/tests/template_tests/test_loaders.py
+++ b/tests/template_tests/test_loaders.py
@@ -1,22 +1,18 @@
-"""
-Test cases for the template loaders
-
-Note: This test requires setuptools!
-"""
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
 
 import os.path
 import sys
 import types
 import unittest
+from contextlib import contextmanager
 
-from django.template import Context, TemplateDoesNotExist, loader
+from django.template import Context, TemplateDoesNotExist
 from django.template.engine import Engine
-from django.template.loaders import cached, eggs
-from django.test import SimpleTestCase, ignore_warnings, override_settings
+from django.test import SimpleTestCase, override_settings
 from django.utils import six
-from django.utils._os import upath
-from django.utils.deprecation import RemovedInDjango20Warning
-from django.utils.six import StringIO
+
+from .utils import TEMPLATE_DIR
 
 try:
     import pkg_resources
@@ -24,38 +20,86 @@ except ImportError:
     pkg_resources = None
 
 
-TEMPLATES_DIR = os.path.join(os.path.dirname(upath(__file__)), 'templates')
+class CachedLoaderTests(SimpleTestCase):
 
-GLOBAL_TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.dirname(upath(__file__))), 'templates')
+    def create_engine(self, **kwargs):
+        return Engine(
+            loaders=[
+                ('django.template.loaders.cached.Loader', [
+                    'django.template.loaders.filesystem.Loader',
+                ]),
+            ],
+        )
 
+    def test_templatedir_caching(self):
+        """
+        #13573 -- Template directories should be part of the cache key.
+        """
+        engine = self.create_engine()
 
-# Mock classes and objects for pkg_resources functions.
-class MockLoader(object):
-    pass
+        # Retrieve a template specifying a template directory to check
+        t1, name = engine.find_template('test.html', (os.path.join(TEMPLATE_DIR, 'first'),))
+        # Now retrieve the same template name, but from a different directory
+        t2, name = engine.find_template('test.html', (os.path.join(TEMPLATE_DIR, 'second'),))
 
+        # The two templates should not have the same content
+        self.assertNotEqual(t1.render(Context({})), t2.render(Context({})))
 
-def create_egg(name, resources):
-    """
-    Creates a mock egg with a list of resources.
+    def test_missing_template_is_cached(self):
+        """
+        #19949 -- TemplateDoesNotExist exceptions should be cached.
+        """
+        engine = self.create_engine()
+        loader = engine.template_loaders[0]
 
-    name: The name of the module.
-    resources: A dictionary of resources. Keys are the names and values the data.
-    """
-    egg = types.ModuleType(name)
-    egg.__loader__ = MockLoader()
-    egg.__path__ = ['/some/bogus/path/']
-    egg.__file__ = '/some/bogus/path/__init__.pyc'
-    egg._resources = resources
-    sys.modules[name] = egg
+        self.assertFalse('missing.html' in loader.template_cache)
+
+        with self.assertRaises(TemplateDoesNotExist):
+            loader.load_template("missing.html")
+
+        self.assertEqual(
+            loader.template_cache["missing.html"],
+            TemplateDoesNotExist,
+            "Cached loader failed to cache the TemplateDoesNotExist exception",
+        )
+
+    def test_debug_nodelist_name(self):
+        template_name = 'index.html'
+        engine = Engine(dirs=[TEMPLATE_DIR], debug=True)
+
+        template = engine.get_template(template_name)
+        name = template.nodelist[0].source[0].name
+        self.assertTrue(
+            name.endswith(template_name),
+            'Template loaded through cached loader has incorrect name for debug page: %s' % template_name,
+        )
+
+        template = engine.get_template(template_name)
+        name = template.nodelist[0].source[0].name
+        self.assertTrue(
+            name.endswith(template_name),
+            'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name,
+        )
 
 
 @unittest.skipUnless(pkg_resources, 'setuptools is not installed')
-class EggLoaderTest(SimpleTestCase):
+class EggLoaderTests(SimpleTestCase):
 
-    def setUp(self):
-        self.loader = eggs.Loader(Engine.get_default())
+    @contextmanager
+    def create_egg(self, name, resources):
+        """
+        Creates a mock egg with a list of resources.
+
+        name: The name of the module.
+        resources: A dictionary of template names mapped to file-like objects.
+        """
+
+        if six.PY2:
+            name = name.encode('utf-8')
+
+        class MockLoader(object):
+            pass
 
-        # Defined here b/c at module scope we may not have pkg_resources
         class MockProvider(pkg_resources.NullProvider):
             def __init__(self, module):
                 pkg_resources.NullProvider.__init__(self, module)
@@ -76,181 +120,123 @@ class EggLoaderTest(SimpleTestCase):
             def _fn(self, base, resource_name):
                 return os.path.normcase(resource_name)
 
+        egg = types.ModuleType(name)
+        egg.__loader__ = MockLoader()
+        egg.__path__ = ['/some/bogus/path/']
+        egg.__file__ = '/some/bogus/path/__init__.pyc'
+        egg._resources = resources
+        sys.modules[name] = egg
         pkg_resources._provider_factories[MockLoader] = MockProvider
 
-        self.empty_egg = create_egg("egg_empty", {})
-        self.egg_1 = create_egg("egg_1", {
-            os.path.normcase('templates/y.html'): StringIO("y"),
-            os.path.normcase('templates/x.txt'): StringIO("x"),
-        })
-
-    @override_settings(INSTALLED_APPS=['egg_empty'])
-    def test_empty(self):
-        "Loading any template on an empty egg should fail"
-        with self.assertRaises(TemplateDoesNotExist):
-            self.loader.load_template_source("not-existing.html")
-
-    @override_settings(INSTALLED_APPS=['egg_1'])
-    def test_non_existing(self):
-        "Template loading fails if the template is not in the egg"
-        with self.assertRaises(TemplateDoesNotExist):
-            self.loader.load_template_source("not-existing.html")
-
-    @override_settings(INSTALLED_APPS=['egg_1'])
-    def test_existing(self):
-        "A template can be loaded from an egg"
-        contents, template_name = self.loader.load_template_source("y.html")
-        self.assertEqual(contents, "y")
-        self.assertEqual(template_name, "egg:egg_1:templates/y.html")
-
-    def test_not_installed(self):
-        "Loading an existent template from an egg not included in any app should fail"
-        with self.assertRaises(TemplateDoesNotExist):
-            self.loader.load_template_source("y.html")
-
-
-class CachedLoader(SimpleTestCase):
+        try:
+            yield
+        finally:
+            del sys.modules[name]
+            del pkg_resources._provider_factories[MockLoader]
 
     def setUp(self):
-        self.loader = cached.Loader(Engine.get_default(), [
-            'django.template.loaders.filesystem.Loader',
+        engine = Engine(loaders=[
+            'django.template.loaders.eggs.Loader',
         ])
+        self.loader = engine.template_loaders[0]
 
-    def test_templatedir_caching(self):
-        "Check that the template directories form part of the template cache key. Refs #13573"
-        # Retrieve a template specifying a template directory to check
-        t1, name = self.loader.find_template('test.html', (os.path.join(TEMPLATES_DIR, 'first'),))
-        # Now retrieve the same template name, but from a different directory
-        t2, name = self.loader.find_template('test.html', (os.path.join(TEMPLATES_DIR, 'second'),))
+    def test_existing(self):
+        templates = {
+            os.path.normcase('templates/y.html'): six.StringIO("y"),
+        }
 
-        # The two templates should not have the same content
-        self.assertNotEqual(t1.render(Context({})), t2.render(Context({})))
+        with self.create_egg('egg', templates):
+            with override_settings(INSTALLED_APPS=['egg']):
+                contents, template_name = self.loader.load_template_source("y.html")
+                self.assertEqual(contents, "y")
+                self.assertEqual(template_name, "egg:egg:templates/y.html")
 
-    def test_missing_template_is_cached(self):
-        "#19949 -- Check that the missing template is cached."
-        # Check that 'missing.html' isn't already in cache before 'missing.html' is loaded
-        with self.assertRaises(KeyError):
-            self.loader.template_cache["missing.html"]
-        # Try to load it, it should fail
-        with self.assertRaises(TemplateDoesNotExist):
-            self.loader.load_template("missing.html")
-        # Verify that the fact that the missing template, which hasn't been found, has actually
-        # been cached:
-        cached_miss = self.loader.template_cache["missing.html"]
-        self.assertEqual(cached_miss, TemplateDoesNotExist,
-                         "Cached template loader doesn't cache file lookup misses. It should.")
-
-
-@override_settings(TEMPLATES=[{
-    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    'DIRS': [TEMPLATES_DIR],
-}])
-class RenderToStringTest(SimpleTestCase):
-    def test_basic(self):
-        self.assertEqual(loader.render_to_string('test_context.html'), 'obj:\n')
-
-    def test_basic_context(self):
-        self.assertEqual(loader.render_to_string('test_context.html',
-                                                 {'obj': 'test'}), 'obj:test\n')
-
-    def test_empty_list(self):
-        six.assertRaisesRegex(self, TemplateDoesNotExist,
-            'No template names provided$',
-            loader.render_to_string, [])
-
-    def test_select_templates_from_empty_list(self):
-        six.assertRaisesRegex(self, TemplateDoesNotExist,
-            'No template names provided$',
-            loader.select_template, [])
-
-
-@ignore_warnings(category=RemovedInDjango20Warning)
-@override_settings(TEMPLATES=[{
-    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    'DIRS': [TEMPLATES_DIR],
-}])
-class DeprecatedRenderToStringTest(SimpleTestCase):
-
-    def test_existing_context_kept_clean(self):
-        context = Context({'obj': 'before'})
-        output = loader.render_to_string('test_context.html', {'obj': 'after'},
-                                         context_instance=context)
-        self.assertEqual(output, 'obj:after\n')
-        self.assertEqual(context['obj'], 'before')
-
-    def test_no_empty_dict_pushed_to_stack(self):
+    def test_non_existing(self):
         """
-        No empty dict should be pushed to the context stack when render_to_string
-        is called without any argument (#21741).
+        Template loading fails if the template is not in the egg.
         """
+        with self.create_egg('egg', {}):
+            with override_settings(INSTALLED_APPS=['egg']):
+                with self.assertRaises(TemplateDoesNotExist):
+                    self.loader.load_template_source("not-existing.html")
 
-        # The stack should have a length of 1, corresponding to the builtins
-        self.assertEqual('1',
-            loader.render_to_string('test_context_stack.html').strip())
-        self.assertEqual('1',
-            loader.render_to_string('test_context_stack.html', context_instance=Context()).strip())
-
-
-@ignore_warnings(category=RemovedInDjango20Warning)
-@override_settings(TEMPLATES=[{
-    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-}])
-class TemplateDirsOverrideTest(SimpleTestCase):
-
-    dirs_tuple = (os.path.join(os.path.dirname(upath(__file__)), 'other_templates'),)
-    dirs_list = list(dirs_tuple)
-    dirs_iter = (dirs_tuple, dirs_list)
-
-    def test_render_to_string(self):
-        for dirs in self.dirs_iter:
-            self.assertEqual(loader.render_to_string('test_dirs.html', dirs=dirs), 'spam eggs\n')
-
-    def test_get_template(self):
-        for dirs in self.dirs_iter:
-            template = loader.get_template('test_dirs.html', dirs=dirs)
-            self.assertEqual(template.render(), 'spam eggs\n')
-
-    def test_select_template(self):
-        for dirs in self.dirs_iter:
-            template = loader.select_template(['test_dirs.html'], dirs=dirs)
-            self.assertEqual(template.render(), 'spam eggs\n')
-
-
-@override_settings(TEMPLATES=[{
-    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    'DIRS': [GLOBAL_TEMPLATES_DIR],
-    'OPTIONS': {
-        'loaders': [
-            ('django.template.loaders.cached.Loader', [
-                'django.template.loaders.filesystem.Loader',
-                'django.template.loaders.app_directories.Loader',
-            ]),
-        ],
-    },
-}])
-class PriorityCacheLoader(SimpleTestCase):
-    def test_basic(self):
+    def test_not_installed(self):
         """
-        Check that the order of template loader works. Refs #21460.
+        Template loading fails if the egg is not in INSTALLED_APPS.
         """
-        t1 = loader.get_template('priority/foo.html')
-        self.assertEqual(t1.render(), 'priority\n')
+        templates = {
+            os.path.normcase('templates/y.html'): six.StringIO("y"),
+        }
+
+        with self.create_egg('egg', templates):
+            with self.assertRaises(TemplateDoesNotExist):
+                self.loader.load_template_source("y.html")
 
 
-@override_settings(TEMPLATES=[{
-    'BACKEND': 'django.template.backends.django.DjangoTemplates',
-    'DIRS': [GLOBAL_TEMPLATES_DIR],
-    'OPTIONS': {
-        'loaders': [
-            'django.template.loaders.filesystem.Loader',
-            'django.template.loaders.app_directories.Loader',
-        ],
-    },
-}])
-class PriorityLoader(SimpleTestCase):
-    def test_basic(self):
+class FileSystemLoaderTests(SimpleTestCase):
+
+    def setUp(self):
+        self.engine = Engine()
+
+    @contextmanager
+    def source_checker(self, dirs):
+        loader = self.engine.template_loaders[0]
+
+        def check_sources(path, expected_sources):
+            expected_sources = [os.path.abspath(s) for s in expected_sources]
+            self.assertEqual(
+                list(loader.get_template_sources(path, dirs)),
+                expected_sources,
+            )
+
+        yield check_sources
+
+    def test_directory_security(self):
+        with self.source_checker(['/dir1', '/dir2']) as check_sources:
+            check_sources('index.html', ['/dir1/index.html', '/dir2/index.html'])
+            check_sources('/etc/passwd', [])
+            check_sources('etc/passwd', ['/dir1/etc/passwd', '/dir2/etc/passwd'])
+            check_sources('../etc/passwd', [])
+            check_sources('../../../etc/passwd', [])
+            check_sources('/dir1/index.html', ['/dir1/index.html'])
+            check_sources('../dir2/index.html', ['/dir2/index.html'])
+            check_sources('/dir1blah', [])
+            check_sources('../dir1blah', [])
+
+    def test_unicode_template_name(self):
+        with self.source_checker(['/dir1', '/dir2']) as check_sources:
+            # UTF-8 bytestrings are permitted.
+            check_sources(b'\xc3\x85ngstr\xc3\xb6m', ['/dir1/Ångström', '/dir2/Ångström'])
+            # Unicode strings are permitted.
+            check_sources('Ångström', ['/dir1/Ångström', '/dir2/Ångström'])
+
+    def test_utf8_bytestring(self):
         """
-        Check that the order of template loader works. Refs #21460.
+        Invalid UTF-8 encoding in bytestrings should raise a useful error
         """
-        t1 = loader.get_template('priority/foo.html')
-        self.assertEqual(t1.render(), 'priority\n')
+        engine = Engine()
+        loader = engine.template_loaders[0]
+        with self.assertRaises(UnicodeDecodeError):
+            list(loader.get_template_sources(b'\xc3\xc3', ['/dir1']))
+
+    def test_unicode_dir_name(self):
+        with self.source_checker([b'/Stra\xc3\x9fe']) as check_sources:
+            check_sources('Ångström', ['/Straße/Ångström'])
+            check_sources(b'\xc3\x85ngstr\xc3\xb6m', ['/Straße/Ångström'])
+
+    @unittest.skipUnless(
+        os.path.normcase('/TEST') == os.path.normpath('/test'),
+        "This test only runs on case-sensitive file systems.",
+    )
+    def test_case_sensitivity(self):
+        with self.source_checker(['/dir1', '/DIR2']) as check_sources:
+            check_sources('index.html', ['/dir1/index.html', '/DIR2/index.html'])
+            check_sources('/DIR1/index.HTML', ['/DIR1/index.HTML'])
+
+
+class AppDirectoriesLoaderTest(FileSystemLoaderTests):
+
+    def setUp(self):
+        self.engine = Engine(
+            loaders=['django.template.loaders.app_directories.Loader'],
+        )
diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py
index 77115d061a..b405c5feea 100644
--- a/tests/template_tests/tests.py
+++ b/tests/template_tests/tests.py
@@ -13,7 +13,6 @@ from django.template import (
     base as template_base, engines, loader,
 )
 from django.template.engine import Engine
-from django.template.loaders import app_directories, filesystem
 from django.test import RequestFactory, SimpleTestCase
 from django.test.utils import (
     extend_sys_path, ignore_warnings, override_settings,
@@ -21,126 +20,18 @@ from django.test.utils import (
 from django.utils._os import upath
 from django.utils.deprecation import RemovedInDjango20Warning
 
-TESTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(upath(__file__))))
-
-TEMPLATES_DIR = os.path.join(TESTS_DIR, 'templates')
+TEMPLATES_DIR = os.path.join(os.path.dirname(upath(__file__)), 'templates')
 
 
-class TemplateLoaderTests(SimpleTestCase):
-
-    def test_loaders_security(self):
-        ad_loader = app_directories.Loader(Engine.get_default())
-        fs_loader = filesystem.Loader(Engine.get_default())
-
-        def test_template_sources(path, template_dirs, expected_sources):
-            if isinstance(expected_sources, list):
-                # Fix expected sources so they are abspathed
-                expected_sources = [os.path.abspath(s) for s in expected_sources]
-            # Test the two loaders (app_directores and filesystem).
-            func1 = lambda p, t: list(ad_loader.get_template_sources(p, t))
-            func2 = lambda p, t: list(fs_loader.get_template_sources(p, t))
-            for func in (func1, func2):
-                if isinstance(expected_sources, list):
-                    self.assertEqual(func(path, template_dirs), expected_sources)
-                else:
-                    self.assertRaises(expected_sources, func, path, template_dirs)
-
-        template_dirs = ['/dir1', '/dir2']
-        test_template_sources('index.html', template_dirs,
-                              ['/dir1/index.html', '/dir2/index.html'])
-        test_template_sources('/etc/passwd', template_dirs, [])
-        test_template_sources('etc/passwd', template_dirs,
-                              ['/dir1/etc/passwd', '/dir2/etc/passwd'])
-        test_template_sources('../etc/passwd', template_dirs, [])
-        test_template_sources('../../../etc/passwd', template_dirs, [])
-        test_template_sources('/dir1/index.html', template_dirs,
-                              ['/dir1/index.html'])
-        test_template_sources('../dir2/index.html', template_dirs,
-                              ['/dir2/index.html'])
-        test_template_sources('/dir1blah', template_dirs, [])
-        test_template_sources('../dir1blah', template_dirs, [])
-
-        # UTF-8 bytestrings are permitted.
-        test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', template_dirs,
-                              ['/dir1/Ångström', '/dir2/Ångström'])
-        # Unicode strings are permitted.
-        test_template_sources('Ångström', template_dirs,
-                              ['/dir1/Ångström', '/dir2/Ångström'])
-        test_template_sources('Ångström', [b'/Stra\xc3\x9fe'], ['/Straße/Ångström'])
-        test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', [b'/Stra\xc3\x9fe'],
-                              ['/Straße/Ångström'])
-        # Invalid UTF-8 encoding in bytestrings is not. Should raise a
-        # semi-useful error message.
-        test_template_sources(b'\xc3\xc3', template_dirs, UnicodeDecodeError)
-
-        # Case insensitive tests (for win32). Not run unless we're on
-        # a case insensitive operating system.
-        if os.path.normcase('/TEST') == os.path.normpath('/test'):
-            template_dirs = ['/dir1', '/DIR2']
-            test_template_sources('index.html', template_dirs,
-                                  ['/dir1/index.html', '/DIR2/index.html'])
-            test_template_sources('/DIR1/index.HTML', template_dirs,
-                                  ['/DIR1/index.HTML'])
-
-    @override_settings(TEMPLATES=[{
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [TEMPLATES_DIR],
-        'OPTIONS': {
-            # Turn DEBUG on, so that the origin file name will be kept with
-            # the compiled templates.
-            'debug': True,
-        }
-    }])
-    def test_loader_debug_origin(self):
-        load_name = 'login.html'
-
-        # We rely on the fact the file system and app directories loaders both
-        # inherit the load_template method from the base Loader class, so we
-        # only need to test one of them.
-        template = loader.get_template(load_name).template
-        template_name = template.nodelist[0].source[0].name
-        self.assertTrue(template_name.endswith(load_name),
-            'Template loaded by filesystem loader has incorrect name for debug page: %s' % template_name)
-
-    @override_settings(TEMPLATES=[{
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [TEMPLATES_DIR],
-        'OPTIONS': {
-            'debug': True,
-            'loaders': [
-                ('django.template.loaders.cached.Loader', [
-                    'django.template.loaders.filesystem.Loader',
-                ]),
-            ],
-        },
-    }])
-    def test_cached_loader_debug_origin(self):
-        load_name = 'login.html'
-
-        # Test the cached loader separately since it overrides load_template.
-        template = loader.get_template(load_name).template
-        template_name = template.nodelist[0].source[0].name
-        self.assertTrue(template_name.endswith(load_name),
-            'Template loaded through cached loader has incorrect name for debug page: %s' % template_name)
-
-        template = loader.get_template(load_name).template
-        template_name = template.nodelist[0].source[0].name
-        self.assertTrue(template_name.endswith(load_name),
-            'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name)
-
-    @override_settings(DEBUG=True)
-    def test_loader_origin(self):
-        template = loader.get_template('login.html')
-        self.assertEqual(template.origin.loadname, 'login.html')
+class TemplateTests(SimpleTestCase):
 
     @override_settings(DEBUG=True)
     def test_string_origin(self):
         template = Template('string template')
         self.assertEqual(template.origin.source, 'string template')
 
-    def test_debug_false_origin(self):
-        template = loader.get_template('login.html')
-        self.assertEqual(template.origin, None)
+
+class IncludeTests(SimpleTestCase):
 
     # Test the base loader class via the app loader. load_template
     # from base is used by all shipped loaders excepting cached,
diff --git a/tests/template_tests/utils.py b/tests/template_tests/utils.py
index d5af69bdd6..36f4d95678 100644
--- a/tests/template_tests/utils.py
+++ b/tests/template_tests/utils.py
@@ -15,6 +15,7 @@ from django.utils.encoding import python_2_unicode_compatible
 from django.utils.safestring import mark_safe
 
 ROOT = os.path.dirname(os.path.abspath(upath(__file__)))
+TEMPLATE_DIR = os.path.join(ROOT, 'templates')
 
 
 def setup(templates, *args, **kwargs):