diff options
| author | Carl Meyer <carl@oddbird.net> | 2013-05-10 23:08:45 -0400 |
|---|---|---|
| committer | Carl Meyer <carl@oddbird.net> | 2013-05-10 23:08:45 -0400 |
| commit | 9012833af857e081b515ce760685b157638efcef (patch) | |
| tree | 467982b071026047cab406e4eaae9cb1a2d2f77d /tests | |
| parent | c0d8932a6d03e9326a4e407e944b09bf43cf929c (diff) | |
Fixed #17365, #17366, #18727 -- Switched to discovery test runner.
Thanks to Preston Timmons for the bulk of the work on the patch, especially
updating Django's own test suite to comply with the requirements of the new
runner. Thanks also to Jannis Leidel and Mahdi Yusuf for earlier work on the
patch and the discovery runner.
Refs #11077, #17032, and #18670.
Diffstat (limited to 'tests')
23 files changed, 183 insertions, 129 deletions
diff --git a/tests/admin_scripts/tests.py b/tests/admin_scripts/tests.py index 5071977b2d..c8986770f3 100644 --- a/tests/admin_scripts/tests.py +++ b/tests/admin_scripts/tests.py @@ -19,9 +19,9 @@ from django import conf, get_version from django.conf import settings from django.core.management import BaseCommand, CommandError from django.db import connection -from django.test.simple import DjangoTestSuiteRunner +from django.test.runner import DiscoverRunner from django.utils import unittest -from django.utils.encoding import force_str, force_text +from django.utils.encoding import force_text from django.utils._os import upath from django.utils.six import StringIO from django.test import LiveServerTestCase @@ -1090,7 +1090,7 @@ class ManageValidate(AdminScriptTestCase): self.assertOutput(out, '0 errors found') -class CustomTestRunner(DjangoTestSuiteRunner): +class CustomTestRunner(DiscoverRunner): def __init__(self, *args, **kwargs): assert 'liveserver' not in kwargs diff --git a/tests/generic_views/tests.py b/tests/generic_views/tests.py deleted file mode 100644 index 244aa3c701..0000000000 --- a/tests/generic_views/tests.py +++ /dev/null @@ -1,11 +0,0 @@ -from __future__ import absolute_import - -from .test_base import (ViewTest, TemplateViewTest, RedirectViewTest, - GetContextDataTest) -from .test_dates import (ArchiveIndexViewTests, YearArchiveViewTests, - MonthArchiveViewTests, WeekArchiveViewTests, DayArchiveViewTests, - DateDetailViewTests) -from .test_detail import DetailViewTest -from .test_edit import (FormMixinTests, BasicFormTests, ModelFormMixinTests, - CreateViewTests, UpdateViewTests, DeleteViewTests) -from .test_list import ListViewTests diff --git a/tests/i18n/tests.py b/tests/i18n/tests.py index d26a201efa..1022c8d2f1 100644 --- a/tests/i18n/tests.py +++ b/tests/i18n/tests.py @@ -43,14 +43,8 @@ if can_run_compilation_tests: from .commands.compilation import (PoFileTests, PoFileContentsTests, PercentRenderingTests, MultipleLocaleCompilationTests, CompilationErrorHandling) -from .contenttypes.tests import ContentTypeTests from .forms import I18nForm, SelectDateForm, SelectDateWidget, CompanyForm from .models import Company, TestModel -from .patterns.tests import (URLRedirectWithoutTrailingSlashTests, - URLTranslationTests, URLDisabledTests, URLTagTests, URLTestCaseBase, - URLRedirectWithoutTrailingSlashSettingTests, URLNamespaceTests, - URLPrefixTests, URLResponseTests, URLRedirectTests, PathUnusedTests, - URLVaryAcceptLanguageTests) here = os.path.dirname(os.path.abspath(upath(__file__))) diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index 035a5c2ae3..e1e38d0ec7 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -15,11 +15,6 @@ from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, DataModel, Document, RenamedField, VerboseNameField, FksToBooleans) -from .test_imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests, - TwoImageFieldTests, ImageFieldNoDimensionsTests, - ImageFieldOneDimensionTests, ImageFieldDimensionsFirstTests, - ImageFieldUsingFileTests) - class BasicFieldTests(test.TestCase): def test_show_hidden_initial(self): diff --git a/tests/runtests.py b/tests/runtests.py index ee2488c4a1..cb124f2541 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -10,16 +10,23 @@ from django import contrib from django.utils._os import upath from django.utils import six -CONTRIB_DIR_NAME = 'django.contrib' +CONTRIB_MODULE_PATH = 'django.contrib' TEST_TEMPLATE_DIR = 'templates' RUNTESTS_DIR = os.path.abspath(os.path.dirname(upath(__file__))) CONTRIB_DIR = os.path.dirname(upath(contrib.__file__)) + TEMP_DIR = tempfile.mkdtemp(prefix='django_') os.environ['DJANGO_TEST_TEMP_DIR'] = TEMP_DIR -SUBDIRS_TO_SKIP = ['templates'] +SUBDIRS_TO_SKIP = [ + 'templates', + 'test_discovery_sample', + 'test_discovery_sample2', + 'test_runner_deprecation_app', + 'test_runner_invalid_app', +] ALWAYS_INSTALLED_APPS = [ 'shared_models', @@ -40,17 +47,12 @@ ALWAYS_INSTALLED_APPS = [ 'staticfiles_tests.apps.no_label', ] -def geodjango(settings): - # All databases must have spatial backends to run GeoDjango tests. - spatial_dbs = [name for name, db_dict in settings.DATABASES.items() - if db_dict['ENGINE'].startswith('django.contrib.gis')] - return len(spatial_dbs) == len(settings.DATABASES) def get_test_modules(): modules = [] - for loc, dirpath in ( + for modpath, dirpath in ( (None, RUNTESTS_DIR), - (CONTRIB_DIR_NAME, CONTRIB_DIR)): + (CONTRIB_MODULE_PATH, CONTRIB_DIR)): for f in os.listdir(dirpath): if ('.' in f or # Python 3 byte code dirs (PEP 3147) @@ -59,9 +61,14 @@ def get_test_modules(): os.path.basename(f) in SUBDIRS_TO_SKIP or os.path.isfile(f)): continue - modules.append((loc, f)) + modules.append((modpath, f)) return modules +def get_installed(): + from django.db.models.loading import get_apps + return [app.__name__.rsplit('.', 1)[0] for app in get_apps()] + + def setup(verbosity, test_labels): from django.conf import settings from django.db.models.loading import get_apps, load_app @@ -95,25 +102,45 @@ def setup(verbosity, test_labels): get_apps() # Load all the test model apps. - test_labels_set = set([label.split('.')[0] for label in test_labels]) test_modules = get_test_modules() + # Reduce given test labels to just the app module path + test_labels_set = set() + for label in test_labels: + bits = label.split('.') + if bits[:2] == ['django', 'contrib']: + bits = bits[:3] + else: + bits = bits[:1] + test_labels_set.add('.'.join(bits)) + # If GeoDjango, then we'll want to add in the test applications # that are a part of its test suite. - if geodjango(settings): + from django.contrib.gis.tests.utils import HAS_SPATIAL_DB + if HAS_SPATIAL_DB: from django.contrib.gis.tests import geo_apps - test_modules.extend(geo_apps(runtests=True)) + test_modules.extend(geo_apps()) settings.INSTALLED_APPS.extend(['django.contrib.gis', 'django.contrib.sitemaps']) - for module_dir, module_name in test_modules: - if module_dir: - module_label = '.'.join([module_dir, module_name]) + for modpath, module_name in test_modules: + if modpath: + module_label = '.'.join([modpath, module_name]) else: module_label = module_name - # if the module was named on the command line, or + # if the module (or an ancestor) was named on the command line, or # no modules were named (i.e., run all), import - # this module and add it to the list to test. - if not test_labels or module_name in test_labels_set: + # this module and add it to INSTALLED_APPS. + if not test_labels: + module_found_in_labels = True + else: + match = lambda label: ( + module_label == label or # exact match + module_label.startswith(label + '.') # ancestor match + ) + + module_found_in_labels = any(match(l) for l in test_labels_set) + + if module_found_in_labels: if verbosity >= 2: print("Importing application %s" % module_name) mod = load_app(module_label) @@ -139,21 +166,16 @@ def django_tests(verbosity, interactive, failfast, test_labels): state = setup(verbosity, test_labels) extra_tests = [] - # If GeoDjango is used, add it's tests that aren't a part of - # an application (e.g., GEOS, GDAL, Distance objects). - if geodjango(settings) and (not test_labels or 'gis' in test_labels): - from django.contrib.gis.tests import geodjango_suite - extra_tests.append(geodjango_suite(apps=False)) - # Run the test suite, including the extra validation tests. - from django.test.utils import get_runner - if not hasattr(settings, 'TEST_RUNNER'): - settings.TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner' - TestRunner = get_runner(settings) + from django.test.runner import DiscoverRunner - test_runner = TestRunner(verbosity=verbosity, interactive=interactive, - failfast=failfast) - failures = test_runner.run_tests(test_labels, extra_tests=extra_tests) + test_runner = DiscoverRunner( + verbosity=verbosity, + interactive=interactive, + failfast=failfast, + ) + failures = test_runner.run_tests( + test_labels or get_installed(), extra_tests=extra_tests) teardown(state) return failures @@ -162,10 +184,7 @@ def django_tests(verbosity, interactive, failfast, test_labels): def bisect_tests(bisection_label, options, test_labels): state = setup(int(options.verbosity), test_labels) - if not test_labels: - # Get the full list of test labels to use for bisection - from django.db.models.loading import get_apps - test_labels = [app.__name__.split('.')[-2] for app in get_apps()] + test_labels = test_labels or get_installed() print('***** Bisecting test suite: %s' % ' '.join(test_labels)) @@ -222,11 +241,7 @@ def bisect_tests(bisection_label, options, test_labels): def paired_tests(paired_test, options, test_labels): state = setup(int(options.verbosity), test_labels) - if not test_labels: - print("") - # Get the full list of test labels to use for bisection - from django.db.models.loading import get_apps - test_labels = [app.__name__.split('.')[-2] for app in get_apps()] + test_labels = test_labels or get_installed() print('***** Trying paired execution') diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py index da1562d2d5..2aeaee9464 100644 --- a/tests/template_tests/tests.py +++ b/tests/template_tests/tests.py @@ -36,15 +36,6 @@ from django.utils.safestring import mark_safe from django.utils import six from django.utils.tzinfo import LocalTimezone -from .test_callables import CallableVariablesTests -from .test_context import ContextTests -from .test_custom import CustomTagTests, CustomFilterTests -from .test_parser import ParserTests -from .test_unicode import UnicodeTests -from .test_nodelist import NodelistTest, ErrorIndexTest -from .test_smartif import SmartIfTests -from .test_response import (TemplateResponseTest, CacheMiddlewareTest, - SimpleTemplateResponseTest, CustomURLConfTest) try: from .loaders import RenderToStringTest, EggLoaderTest diff --git a/tests/test_runner/deprecation_app/__init__.py b/tests/test_discovery_sample/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/test_runner/deprecation_app/__init__.py +++ b/tests/test_discovery_sample/__init__.py diff --git a/tests/test_discovery_sample/pattern_tests.py b/tests/test_discovery_sample/pattern_tests.py new file mode 100644 index 0000000000..f62a233d75 --- /dev/null +++ b/tests/test_discovery_sample/pattern_tests.py @@ -0,0 +1,7 @@ +from unittest import TestCase + + +class Test(TestCase): + + def test_sample(self): + self.assertEqual(1, 1) diff --git a/tests/test_runner/invalid_app/models/__init__.py b/tests/test_discovery_sample/tests/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/test_runner/invalid_app/models/__init__.py +++ b/tests/test_discovery_sample/tests/__init__.py diff --git a/tests/test_discovery_sample/tests/tests.py b/tests/test_discovery_sample/tests/tests.py new file mode 100644 index 0000000000..58bd4e7f1e --- /dev/null +++ b/tests/test_discovery_sample/tests/tests.py @@ -0,0 +1,7 @@ +from unittest import TestCase + + +class Test(TestCase): + + def test_sample(self): + pass diff --git a/tests/test_discovery_sample/tests_sample.py b/tests/test_discovery_sample/tests_sample.py new file mode 100644 index 0000000000..c541bc4cd6 --- /dev/null +++ b/tests/test_discovery_sample/tests_sample.py @@ -0,0 +1,22 @@ +from unittest import TestCase as UnitTestCase + +from django.test import TestCase as DjangoTestCase +from django.utils.unittest import TestCase as UT2TestCase + + +class TestVanillaUnittest(UnitTestCase): + + def test_sample(self): + self.assertEqual(1, 1) + + +class TestUnittest2(UT2TestCase): + + def test_sample(self): + self.assertEqual(1, 1) + + +class TestDjangoTestCase(DjangoTestCase): + + def test_sample(self): + self.assertEqual(1, 1) diff --git a/tests/test_discovery_sample2/__init__.py b/tests/test_discovery_sample2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/test_discovery_sample2/__init__.py diff --git a/tests/test_discovery_sample2/tests.py b/tests/test_discovery_sample2/tests.py new file mode 100644 index 0000000000..232054a9f1 --- /dev/null +++ b/tests/test_discovery_sample2/tests.py @@ -0,0 +1,7 @@ +from django.test import TestCase + + +class Test(TestCase): + + def test_sample(self): + pass diff --git a/tests/test_runner/test_discover_runner.py b/tests/test_runner/test_discover_runner.py new file mode 100644 index 0000000000..3dc364b351 --- /dev/null +++ b/tests/test_runner/test_discover_runner.py @@ -0,0 +1,68 @@ +from django.test import TestCase +from django.test.runner import DiscoverRunner + + +class DiscoverRunnerTest(TestCase): + + def test_dotted_test_module(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample"], + ).countTestCases() + + self.assertEqual(count, 3) + + def test_dotted_test_class_vanilla_unittest(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestVanillaUnittest"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_dotted_test_class_unittest2(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestUnittest2"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_dotted_test_class_django_testcase(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestDjangoTestCase"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_dotted_test_method_vanilla_unittest(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestVanillaUnittest.test_sample"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_dotted_test_method_unittest2(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestUnittest2.test_sample"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_dotted_test_method_django_testcase(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample.tests_sample.TestDjangoTestCase.test_sample"], + ).countTestCases() + + self.assertEqual(count, 1) + + def test_pattern(self): + count = DiscoverRunner( + pattern="*_tests.py", + ).build_suite(["test_discovery_sample"]).countTestCases() + + self.assertEqual(count, 1) + + def test_file_path(self): + count = DiscoverRunner().build_suite( + ["test_discovery_sample/"], + ).countTestCases() + + self.assertEqual(count, 4) diff --git a/tests/test_runner/tests.py b/tests/test_runner/tests.py index 9f0cc794b7..95ccf0242a 100644 --- a/tests/test_runner/tests.py +++ b/tests/test_runner/tests.py @@ -9,7 +9,7 @@ from optparse import make_option from django.core.exceptions import ImproperlyConfigured from django.core.management import call_command from django import db -from django.test import simple, TransactionTestCase, skipUnlessDBFeature +from django.test import runner, TransactionTestCase, skipUnlessDBFeature from django.test.simple import DjangoTestSuiteRunner, get_tests from django.test.testcases import connections_support_transactions from django.utils import unittest @@ -20,7 +20,7 @@ from .models import Person TEST_APP_OK = 'test_runner.valid_app.models' -TEST_APP_ERROR = 'test_runner.invalid_app.models' +TEST_APP_ERROR = 'test_runner_invalid_app.models' class DependencyOrderingTests(unittest.TestCase): @@ -36,7 +36,7 @@ class DependencyOrderingTests(unittest.TestCase): 'bravo': ['charlie'], } - ordered = simple.dependency_ordered(raw, dependencies=dependencies) + ordered = runner.dependency_ordered(raw, dependencies=dependencies) ordered_sigs = [sig for sig,value in ordered] self.assertIn('s1', ordered_sigs) @@ -56,7 +56,7 @@ class DependencyOrderingTests(unittest.TestCase): 'bravo': ['charlie'], } - ordered = simple.dependency_ordered(raw, dependencies=dependencies) + ordered = runner.dependency_ordered(raw, dependencies=dependencies) ordered_sigs = [sig for sig,value in ordered] self.assertIn('s1', ordered_sigs) @@ -83,7 +83,7 @@ class DependencyOrderingTests(unittest.TestCase): 'delta': ['charlie'], } - ordered = simple.dependency_ordered(raw, dependencies=dependencies) + ordered = runner.dependency_ordered(raw, dependencies=dependencies) ordered_sigs = [sig for sig,aliases in ordered] self.assertIn('s1', ordered_sigs) @@ -110,7 +110,7 @@ class DependencyOrderingTests(unittest.TestCase): 'alpha': ['bravo'], } - self.assertRaises(ImproperlyConfigured, simple.dependency_ordered, raw, dependencies=dependencies) + self.assertRaises(ImproperlyConfigured, runner.dependency_ordered, raw, dependencies=dependencies) def test_own_alias_dependency(self): raw = [ @@ -121,7 +121,7 @@ class DependencyOrderingTests(unittest.TestCase): } with self.assertRaises(ImproperlyConfigured): - simple.dependency_ordered(raw, dependencies=dependencies) + runner.dependency_ordered(raw, dependencies=dependencies) # reordering aliases shouldn't matter raw = [ @@ -129,7 +129,7 @@ class DependencyOrderingTests(unittest.TestCase): ] with self.assertRaises(ImproperlyConfigured): - simple.dependency_ordered(raw, dependencies=dependencies) + runner.dependency_ordered(raw, dependencies=dependencies) class MockTestRunner(object): @@ -156,7 +156,7 @@ class ManageCommandTests(unittest.TestCase): testrunner='test_runner.NonExistentRunner') -class CustomOptionsTestRunner(simple.DjangoTestSuiteRunner): +class CustomOptionsTestRunner(runner.DiscoverRunner): option_list = ( make_option('--option_a','-a', action='store', dest='option_a', default='1'), make_option('--option_b','-b', action='store', dest='option_b', default='2'), @@ -289,15 +289,16 @@ class DummyBackendTest(unittest.TestCase): class DeprecationDisplayTest(AdminScriptTestCase): # tests for 19546 def setUp(self): - settings = {'INSTALLED_APPS': '("test_runner.deprecation_app",)', - 'DATABASES': '{"default": {"ENGINE":"django.db.backends.sqlite3", "NAME":":memory:"}}' } + settings = { + 'DATABASES': '{"default": {"ENGINE":"django.db.backends.sqlite3", "NAME":":memory:"}}' + } self.write_settings('settings.py', sdict=settings) def tearDown(self): self.remove_settings('settings.py') def test_runner_deprecation_verbosity_default(self): - args = ['test', '--settings=test_project.settings'] + args = ['test', '--settings=test_project.settings', 'test_runner_deprecation_app'] out, err = self.run_django_admin(args) self.assertIn("DeprecationWarning: warning from test", err) self.assertIn("DeprecationWarning: module-level warning from deprecation_app", err) diff --git a/tests/test_runner_deprecation_app/__init__.py b/tests/test_runner_deprecation_app/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/test_runner_deprecation_app/__init__.py diff --git a/tests/test_runner/deprecation_app/models.py b/tests/test_runner_deprecation_app/models.py index 71a8362390..71a8362390 100644 --- a/tests/test_runner/deprecation_app/models.py +++ b/tests/test_runner_deprecation_app/models.py diff --git a/tests/test_runner/deprecation_app/tests.py b/tests/test_runner_deprecation_app/tests.py index 6dee0888ec..24d716f2bb 100644 --- a/tests/test_runner/deprecation_app/tests.py +++ b/tests/test_runner_deprecation_app/tests.py @@ -7,5 +7,3 @@ warnings.warn("module-level warning from deprecation_app", DeprecationWarning) class DummyTest(TestCase): def test_warn(self): warnings.warn("warning from test", DeprecationWarning) - - diff --git a/tests/test_runner/invalid_app/__init__.py b/tests/test_runner_invalid_app/__init__.py index 45efd37d3e..45efd37d3e 100644 --- a/tests/test_runner/invalid_app/__init__.py +++ b/tests/test_runner_invalid_app/__init__.py diff --git a/tests/test_runner_invalid_app/models/__init__.py b/tests/test_runner_invalid_app/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/test_runner_invalid_app/models/__init__.py diff --git a/tests/test_runner/invalid_app/tests/__init__.py b/tests/test_runner_invalid_app/tests/__init__.py index b4ed71824b..b4ed71824b 100644 --- a/tests/test_runner/invalid_app/tests/__init__.py +++ b/tests/test_runner_invalid_app/tests/__init__.py diff --git a/tests/utils_tests/tests.py b/tests/utils_tests/tests.py deleted file mode 100644 index 8d7fda4800..0000000000 --- a/tests/utils_tests/tests.py +++ /dev/null @@ -1,34 +0,0 @@ -""" -Tests for django.utils. -""" -from __future__ import absolute_import - -from .test_archive import TestBzip2Tar, TestGzipTar, TestTar, TestZip -from .test_baseconv import TestBaseConv -from .test_checksums import TestUtilsChecksums -from .test_crypto import TestUtilsCryptoMisc, TestUtilsCryptoPBKDF2 -from .test_datastructures import (DictWrapperTests, ImmutableListTests, - MergeDictTests, MultiValueDictTests, SortedDictTests) -from .test_dateformat import DateFormatTests -from .test_dateparse import DateParseTests -from .test_datetime_safe import DatetimeTests -from .test_decorators import DecoratorFromMiddlewareTests -from .test_encoding import TestEncodingUtils -from .test_feedgenerator import FeedgeneratorTest -from .test_functional import FunctionalTestCase -from .test_html import TestUtilsHtml -from .test_http import TestUtilsHttp, ETagProcessingTests, HttpDateProcessingTests -from .test_itercompat import TestIsIterator -from .test_ipv6 import TestUtilsIPv6 -from .test_jslex import JsToCForGettextTest, JsTokensTest -from .test_module_loading import (CustomLoader, DefaultLoader, EggLoader, - ModuleImportTestCase) -from .test_numberformat import TestNumberFormat -from .test_os_utils import SafeJoinTests -from .test_regex_helper import NormalizeTests -from .test_simplelazyobject import TestUtilsSimpleLazyObject -from .test_termcolors import TermColorTests -from .test_text import TestUtilsText -from .test_timesince import TimesinceTests -from .test_timezone import TimezoneTests -from .test_tzinfo import TzinfoTests diff --git a/tests/validation/tests.py b/tests/validation/tests.py index ead1b57981..b571e0c298 100644 --- a/tests/validation/tests.py +++ b/tests/validation/tests.py @@ -8,12 +8,6 @@ from . import ValidationTestCase from .models import (Author, Article, ModelToValidate, GenericIPAddressTestModel, GenericIPAddrUnpackUniqueTest) -# Import other tests for this package. -from .test_custom_messages import CustomMessagesTest -from .test_error_messages import ValidationMessagesTest -from .test_unique import GetUniqueCheckTests, PerformUniqueChecksTest -from .test_validators import TestModelsWithValidators - class BaseModelValidationTests(ValidationTestCase): |
