mirror of https://github.com/django/django.git
Removed django.test.simple and django.test._doctest per deprecation timeline.
refs #17365, #17366, #18727.
This commit is contained in:
parent
b71f183d2e
commit
bf5430a20b
File diff suppressed because it is too large
Load Diff
|
@ -1,251 +0,0 @@
|
|||
"""
|
||||
This module is pending deprecation as of Django 1.6 and will be removed in
|
||||
version 1.8.
|
||||
|
||||
"""
|
||||
from importlib import import_module
|
||||
import json
|
||||
import re
|
||||
import unittest as real_unittest
|
||||
import warnings
|
||||
|
||||
from django.apps import apps
|
||||
from django.test import _doctest as doctest
|
||||
from django.test import runner
|
||||
from django.test.utils import compare_xml, strip_quotes
|
||||
# django.utils.unittest is deprecated, but so is django.test.simple,
|
||||
# and the latter will be removed before the former.
|
||||
from django.utils import unittest
|
||||
from django.utils.deprecation import RemovedInDjango18Warning
|
||||
from django.utils.module_loading import module_has_submodule
|
||||
|
||||
__all__ = ('DjangoTestSuiteRunner',)
|
||||
|
||||
warnings.warn(
|
||||
"The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
|
||||
"use django.test.runner.DiscoverRunner instead.",
|
||||
RemovedInDjango18Warning)
|
||||
|
||||
# The module name for tests outside models.py
|
||||
TEST_MODULE = 'tests'
|
||||
|
||||
|
||||
normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
|
||||
normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)",
|
||||
lambda m: "Decimal(\"%s\")" % m.groups()[0], s)
|
||||
|
||||
|
||||
class OutputChecker(doctest.OutputChecker):
|
||||
def check_output(self, want, got, optionflags):
|
||||
"""
|
||||
The entry method for doctest output checking. Defers to a sequence of
|
||||
child checkers
|
||||
"""
|
||||
checks = (self.check_output_default,
|
||||
self.check_output_numeric,
|
||||
self.check_output_xml,
|
||||
self.check_output_json)
|
||||
for check in checks:
|
||||
if check(want, got, optionflags):
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_output_default(self, want, got, optionflags):
|
||||
"""
|
||||
The default comparator provided by doctest - not perfect, but good for
|
||||
most purposes
|
||||
"""
|
||||
return doctest.OutputChecker.check_output(self, want, got, optionflags)
|
||||
|
||||
def check_output_numeric(self, want, got, optionflags):
|
||||
"""Doctest does an exact string comparison of output, which means that
|
||||
some numerically equivalent values aren't equal. This check normalizes
|
||||
* long integers (22L) so that they equal normal integers. (22)
|
||||
* Decimals so that they are comparable, regardless of the change
|
||||
made to __repr__ in Python 2.6.
|
||||
"""
|
||||
return doctest.OutputChecker.check_output(self,
|
||||
normalize_decimals(normalize_long_ints(want)),
|
||||
normalize_decimals(normalize_long_ints(got)),
|
||||
optionflags)
|
||||
|
||||
def check_output_xml(self, want, got, optionsflags):
|
||||
try:
|
||||
return compare_xml(want, got)
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def check_output_json(self, want, got, optionsflags):
|
||||
"""
|
||||
Tries to compare want and got as if they were JSON-encoded data
|
||||
"""
|
||||
want, got = strip_quotes(want, got)
|
||||
try:
|
||||
want_json = json.loads(want)
|
||||
got_json = json.loads(got)
|
||||
except Exception:
|
||||
return False
|
||||
return want_json == got_json
|
||||
|
||||
|
||||
class DocTestRunner(doctest.DocTestRunner):
|
||||
def __init__(self, *args, **kwargs):
|
||||
doctest.DocTestRunner.__init__(self, *args, **kwargs)
|
||||
self.optionflags = doctest.ELLIPSIS
|
||||
|
||||
|
||||
doctestOutputChecker = OutputChecker()
|
||||
|
||||
|
||||
def get_tests(app_config):
|
||||
try:
|
||||
test_module = import_module('%s.%s' % (app_config.name, TEST_MODULE))
|
||||
except ImportError:
|
||||
# Couldn't import tests.py. Was it due to a missing file, or
|
||||
# due to an import error in a tests.py that actually exists?
|
||||
if not module_has_submodule(app_config.module, TEST_MODULE):
|
||||
test_module = None
|
||||
else:
|
||||
# The module exists, so there must be an import error in the test
|
||||
# module itself.
|
||||
raise
|
||||
return test_module
|
||||
|
||||
|
||||
def make_doctest(module):
|
||||
return doctest.DocTestSuite(module,
|
||||
checker=doctestOutputChecker,
|
||||
runner=DocTestRunner)
|
||||
|
||||
|
||||
def build_suite(app_config):
|
||||
"""
|
||||
Create a complete Django test suite for the provided application module.
|
||||
"""
|
||||
suite = unittest.TestSuite()
|
||||
|
||||
# Load unit and doctests in the models.py module. If module has
|
||||
# a suite() method, use it. Otherwise build the test suite ourselves.
|
||||
models_module = app_config.models_module
|
||||
if models_module:
|
||||
if hasattr(models_module, 'suite'):
|
||||
suite.addTest(models_module.suite())
|
||||
else:
|
||||
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(
|
||||
models_module))
|
||||
try:
|
||||
suite.addTest(make_doctest(models_module))
|
||||
except ValueError:
|
||||
# No doc tests in models.py
|
||||
pass
|
||||
|
||||
# Check to see if a separate 'tests' module exists parallel to the
|
||||
# models module
|
||||
tests_module = get_tests(app_config)
|
||||
if tests_module:
|
||||
# Load unit and doctests in the tests.py module. If module has
|
||||
# a suite() method, use it. Otherwise build the test suite ourselves.
|
||||
if hasattr(tests_module, 'suite'):
|
||||
suite.addTest(tests_module.suite())
|
||||
else:
|
||||
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(
|
||||
tests_module))
|
||||
try:
|
||||
suite.addTest(make_doctest(tests_module))
|
||||
except ValueError:
|
||||
# No doc tests in tests.py
|
||||
pass
|
||||
return suite
|
||||
|
||||
|
||||
def build_test(label):
|
||||
"""
|
||||
Construct a test case with the specified label. Label should be of the
|
||||
form app_label.TestClass or app_label.TestClass.test_method. Returns an
|
||||
instantiated test or test suite corresponding to the label provided.
|
||||
"""
|
||||
parts = label.split('.')
|
||||
if len(parts) < 2 or len(parts) > 3:
|
||||
raise ValueError("Test label '%s' should be of the form app.TestCase "
|
||||
"or app.TestCase.test_method" % label)
|
||||
|
||||
app_config = apps.get_app_config(parts[0])
|
||||
models_module = app_config.models_module
|
||||
tests_module = get_tests(app_config)
|
||||
|
||||
test_modules = []
|
||||
if models_module:
|
||||
test_modules.append(models_module)
|
||||
if tests_module:
|
||||
test_modules.append(tests_module)
|
||||
|
||||
TestClass = None
|
||||
for module in test_modules:
|
||||
TestClass = getattr(models_module, parts[1], None)
|
||||
if TestClass is not None:
|
||||
break
|
||||
|
||||
try:
|
||||
if issubclass(TestClass, (unittest.TestCase, real_unittest.TestCase)):
|
||||
if len(parts) == 2: # label is app.TestClass
|
||||
try:
|
||||
return unittest.TestLoader().loadTestsFromTestCase(
|
||||
TestClass)
|
||||
except TypeError:
|
||||
raise ValueError(
|
||||
"Test label '%s' does not refer to a test class"
|
||||
% label)
|
||||
else: # label is app.TestClass.test_method
|
||||
return TestClass(parts[2])
|
||||
except TypeError:
|
||||
# TestClass isn't a TestClass - it must be a method or normal class
|
||||
pass
|
||||
|
||||
#
|
||||
# If there isn't a TestCase, look for a doctest that matches
|
||||
#
|
||||
tests = []
|
||||
for module in test_modules:
|
||||
try:
|
||||
doctests = make_doctest(module)
|
||||
# Now iterate over the suite, looking for doctests whose name
|
||||
# matches the pattern that was given
|
||||
for test in doctests:
|
||||
if test._dt_test.name in (
|
||||
'%s.%s' % (module.__name__, '.'.join(parts[1:])),
|
||||
'%s.__test__.%s' % (
|
||||
module.__name__, '.'.join(parts[1:]))):
|
||||
tests.append(test)
|
||||
except ValueError:
|
||||
# No doctests found.
|
||||
pass
|
||||
|
||||
# If no tests were found, then we were given a bad test label.
|
||||
if not tests:
|
||||
raise ValueError("Test label '%s' does not refer to a test" % label)
|
||||
|
||||
# Construct a suite out of the tests that matched.
|
||||
return unittest.TestSuite(tests)
|
||||
|
||||
|
||||
class DjangoTestSuiteRunner(runner.DiscoverRunner):
|
||||
|
||||
def build_suite(self, test_labels, extra_tests=None, **kwargs):
|
||||
suite = unittest.TestSuite()
|
||||
|
||||
if test_labels:
|
||||
for label in test_labels:
|
||||
if '.' in label:
|
||||
suite.addTest(build_test(label))
|
||||
else:
|
||||
app_config = apps.get_app_config(label)
|
||||
suite.addTest(build_suite(app_config))
|
||||
else:
|
||||
for app_config in apps.get_app_configs():
|
||||
suite.addTest(build_suite(app_config))
|
||||
|
||||
if extra_tests:
|
||||
for test in extra_tests:
|
||||
suite.addTest(test)
|
||||
|
||||
return runner.reorder_suite(suite, (unittest.TestCase,))
|
|
@ -2067,11 +2067,6 @@ Default: ``'django.test.runner.DiscoverRunner'``
|
|||
The name of the class to use for starting the test suite. See
|
||||
:ref:`other-testing-frameworks`.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
|
||||
Previously the default ``TEST_RUNNER`` was
|
||||
``django.test.simple.DjangoTestSuiteRunner``.
|
||||
|
||||
.. setting:: THOUSAND_SEPARATOR
|
||||
|
||||
THOUSAND_SEPARATOR
|
||||
|
|
|
@ -3,7 +3,7 @@ doc_files = docs extras AUTHORS INSTALL LICENSE README.rst
|
|||
install-script = scripts/rpm-install.sh
|
||||
|
||||
[flake8]
|
||||
exclude=build,.git,./django/utils/dictconfig.py,./django/utils/unittest.py,./django/utils/lru_cache.py,./tests/comment_tests/*,./django/test/_doctest.py,./django/utils/six.py,./django/conf/app_template/*,./django/dispatch/weakref_backports.py
|
||||
exclude=build,.git,./django/utils/dictconfig.py,./django/utils/unittest.py,./django/utils/lru_cache.py,./django/utils/six.py,./django/conf/app_template/*,./django/dispatch/weakref_backports.py
|
||||
ignore=E128,E501,W601
|
||||
|
||||
[metadata]
|
||||
|
|
|
@ -4,7 +4,6 @@ Tests for django test runner
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from optparse import make_option
|
||||
import types
|
||||
import unittest
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
@ -12,7 +11,7 @@ from django.core.management import call_command
|
|||
from django import db
|
||||
from django.test import runner, TestCase, TransactionTestCase, skipUnlessDBFeature
|
||||
from django.test.testcases import connections_support_transactions
|
||||
from django.test.utils import IgnoreAllDeprecationWarningsMixin, override_system_checks
|
||||
from django.test.utils import override_system_checks
|
||||
from django.utils import six
|
||||
|
||||
from admin_scripts.tests import AdminScriptTestCase
|
||||
|
@ -221,27 +220,6 @@ class Ticket17477RegressionTests(AdminScriptTestCase):
|
|||
self.assertNoOutput(err)
|
||||
|
||||
|
||||
class ModulesTestsPackages(IgnoreAllDeprecationWarningsMixin, unittest.TestCase):
|
||||
|
||||
def test_get_tests(self):
|
||||
"Check that the get_tests helper function can find tests in a directory"
|
||||
from django.apps import AppConfig
|
||||
from django.test.simple import get_tests
|
||||
app_config = AppConfig.create('test_runner.valid_app')
|
||||
app_config.import_models({})
|
||||
tests = get_tests(app_config)
|
||||
self.assertIsInstance(tests, types.ModuleType)
|
||||
|
||||
def test_import_error(self):
|
||||
"Test for #12658 - Tests with ImportError's shouldn't fail silently"
|
||||
from django.apps import AppConfig
|
||||
from django.test.simple import get_tests
|
||||
app_config = AppConfig.create('test_runner_invalid_app')
|
||||
app_config.import_models({})
|
||||
with self.assertRaises(ImportError):
|
||||
get_tests(app_config)
|
||||
|
||||
|
||||
class Sqlite3InMemoryTestDbs(TestCase):
|
||||
|
||||
available_apps = []
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import unittest
|
||||
|
||||
from django.apps import apps
|
||||
from django.test.utils import IgnoreAllDeprecationWarningsMixin
|
||||
|
||||
|
||||
def suite():
|
||||
testSuite = unittest.TestSuite()
|
||||
testSuite.addTest(SuiteOverrideTest('test_suite_override'))
|
||||
return testSuite
|
||||
|
||||
|
||||
class SuiteOverrideTest(IgnoreAllDeprecationWarningsMixin, unittest.TestCase):
|
||||
|
||||
def test_suite_override(self):
|
||||
"""
|
||||
Validate that you can define a custom suite when running tests with
|
||||
``django.test.simple.DjangoTestSuiteRunner`` (which builds up a test
|
||||
suite using ``build_suite``).
|
||||
"""
|
||||
|
||||
from django.test.simple import build_suite
|
||||
app_config = apps.get_app_config("test_suite_override")
|
||||
suite = build_suite(app_config)
|
||||
self.assertEqual(suite.countTestCases(), 1)
|
||||
|
||||
|
||||
class SampleTests(unittest.TestCase):
|
||||
"""These tests should not be discovered, due to the custom suite."""
|
||||
def test_one(self):
|
||||
pass
|
||||
|
||||
def test_two(self):
|
||||
pass
|
||||
|
||||
def test_three(self):
|
||||
pass
|
|
@ -1,77 +0,0 @@
|
|||
from django.utils import six
|
||||
|
||||
__test__ = {"API_TEST": r"""
|
||||
# Some checks of the doctest output normalizer.
|
||||
# Standard doctests do fairly
|
||||
>>> import json
|
||||
>>> from django.utils.xmlutils import SimplerXMLGenerator
|
||||
>>> from django.utils.six import StringIO
|
||||
|
||||
>>> def produce_json():
|
||||
... return json.dumps(['foo', {'bar': ('baz', None, 1.0, 2), 'whiz': 42}])
|
||||
|
||||
>>> def produce_xml():
|
||||
... stream = StringIO()
|
||||
... xml = SimplerXMLGenerator(stream, encoding='utf-8')
|
||||
... xml.startDocument()
|
||||
... xml.startElement("foo", {"aaa" : "1.0", "bbb": "2.0"})
|
||||
... xml.startElement("bar", {"ccc" : "3.0"})
|
||||
... xml.characters("Hello")
|
||||
... xml.endElement("bar")
|
||||
... xml.startElement("whiz", {})
|
||||
... xml.characters("Goodbye")
|
||||
... xml.endElement("whiz")
|
||||
... xml.endElement("foo")
|
||||
... xml.endDocument()
|
||||
... return stream.getvalue()
|
||||
|
||||
>>> def produce_xml_fragment():
|
||||
... stream = StringIO()
|
||||
... xml = SimplerXMLGenerator(stream, encoding='utf-8')
|
||||
... xml.startElement("foo", {"aaa": "1.0", "bbb": "2.0"})
|
||||
... xml.characters("Hello")
|
||||
... xml.endElement("foo")
|
||||
... xml.startElement("bar", {"ccc": "3.0", "ddd": "4.0"})
|
||||
... xml.endElement("bar")
|
||||
... return stream.getvalue()
|
||||
|
||||
# JSON output is normalized for field order, so it doesn't matter
|
||||
# which order json dictionary attributes are listed in output
|
||||
>>> produce_json()
|
||||
'["foo", {"bar": ["baz", null, 1.0, 2], "whiz": 42}]'
|
||||
|
||||
>>> produce_json()
|
||||
'["foo", {"whiz": 42, "bar": ["baz", null, 1.0, 2]}]'
|
||||
|
||||
# XML output is normalized for attribute order, so it doesn't matter
|
||||
# which order XML element attributes are listed in output
|
||||
>>> produce_xml()
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n<foo aaa="1.0" bbb="2.0"><bar ccc="3.0">Hello</bar><whiz>Goodbye</whiz></foo>'
|
||||
|
||||
>>> produce_xml()
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n<foo bbb="2.0" aaa="1.0"><bar ccc="3.0">Hello</bar><whiz>Goodbye</whiz></foo>'
|
||||
|
||||
>>> produce_xml_fragment()
|
||||
'<foo aaa="1.0" bbb="2.0">Hello</foo><bar ccc="3.0" ddd="4.0"></bar>'
|
||||
|
||||
>>> produce_xml_fragment()
|
||||
'<foo bbb="2.0" aaa="1.0">Hello</foo><bar ddd="4.0" ccc="3.0"></bar>'
|
||||
|
||||
"""}
|
||||
|
||||
if six.PY2:
|
||||
__test__["API_TEST"] += """
|
||||
>>> def produce_long():
|
||||
... return 42L
|
||||
|
||||
>>> def produce_int():
|
||||
... return 42
|
||||
|
||||
# Long values are normalized and are comparable to normal integers ...
|
||||
>>> produce_long()
|
||||
42
|
||||
|
||||
# ... and vice versa
|
||||
>>> produce_int()
|
||||
42L
|
||||
"""
|
|
@ -11,8 +11,7 @@ from django.http import HttpResponse
|
|||
from django.template.loader import render_to_string
|
||||
from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature
|
||||
from django.test.html import HTMLParseError, parse_html
|
||||
from django.test.utils import (CaptureQueriesContext,
|
||||
IgnoreAllDeprecationWarningsMixin, override_settings)
|
||||
from django.test.utils import CaptureQueriesContext, override_settings
|
||||
from django.utils import six
|
||||
|
||||
from .models import Person
|
||||
|
@ -623,15 +622,6 @@ class AssertFieldOutputTests(SimpleTestCase):
|
|||
self.assertFieldOutput(MyCustomField, {}, {}, empty_value=None)
|
||||
|
||||
|
||||
class DoctestNormalizerTest(IgnoreAllDeprecationWarningsMixin, SimpleTestCase):
|
||||
|
||||
def test_normalizer(self):
|
||||
from django.test.simple import make_doctest
|
||||
suite = make_doctest("test_utils.doctest_output")
|
||||
failures = unittest.TextTestRunner(stream=six.StringIO()).run(suite)
|
||||
self.assertEqual(failures.failures, [])
|
||||
|
||||
|
||||
# for OverrideSettingsTests
|
||||
def fake_view(request):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue