diff --git a/.gitignore b/.gitignore index 2255cd9aa..aa4c87066 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.db *~ .* +coverage.xml html/ coverage/ diff --git a/.travis.yml b/.travis.yml index 0dc878373..dd7e8bc60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ env: install: - pip install $DJANGO - pip install django-filter==0.5.4 --use-mirrors + - pip install -r development.txt - export PYTHONPATH=. script: diff --git a/README.md b/README.md index d4c607768..9e82d95af 100644 --- a/README.md +++ b/README.md @@ -75,13 +75,17 @@ To build the docs. ./mkdocs.py +Both the tests and the code coverage are depended on django-discover-runner. +To start hacking type. + + pip install -r development.txt + To run the tests. ./rest_framework/runtests/runtests.py To run the tests with code coverage. - pip install -r development.txt ./rest_framework/runtests/runcoverage.py # Changelog diff --git a/activate.ps1 b/activate.ps1 new file mode 100644 index 000000000..2485acea7 Binary files /dev/null and b/activate.ps1 differ diff --git a/development.txt b/development.txt index ed9f9cc12..bf33a76c2 100644 --- a/development.txt +++ b/development.txt @@ -1 +1,2 @@ -coverage \ No newline at end of file +coverage +django-discover-runner>=0.2.2 diff --git a/manage.py b/manage.py new file mode 100644 index 000000000..800979bbb --- /dev/null +++ b/manage.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +import os +import sys + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rest_framework.tests.settings") + +from django.core.management import execute_from_command_line + +execute_from_command_line(sys.argv) diff --git a/rest_framework/runtests/runcoverage.py b/rest_framework/runtests/runcoverage.py index bcab1d148..eed63028d 100755 --- a/rest_framework/runtests/runcoverage.py +++ b/rest_framework/runtests/runcoverage.py @@ -11,40 +11,25 @@ import sys # fix sys path so we don't need to setup PYTHONPATH sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) -os.environ['DJANGO_SETTINGS_MODULE'] = 'rest_framework.runtests.settings' +os.environ['DJANGO_SETTINGS_MODULE'] = 'rest_framework.tests.settings' -from coverage import coverage +try: + from coverage import coverage +except ImportError: + print("Coverage is not installed. Aborting...") + exit(1) + +def report(cov, cov_files): + cov.report(cov_files) + + if '--html' in sys.argv: + cov.html_report(cov_files, directory='coverage') + + if '--xml' in sys.argv: + cov.xml_report(cov_files, outfile='../../coverage.xml') -def main(): - """Run the tests for rest_framework and generate a coverage report.""" - - cov = coverage() - cov.erase() - cov.start() - - from django.conf import settings - from django.test.utils import get_runner - TestRunner = get_runner(settings) - - if hasattr(TestRunner, 'func_name'): - # Pre 1.2 test runners were just functions, - # and did not support the 'failfast' option. - import warnings - warnings.warn( - 'Function-based test runners are deprecated. Test runners should be classes with a run_tests() method.', - DeprecationWarning - ) - failures = TestRunner(['tests']) - else: - test_runner = TestRunner() - failures = test_runner.run_tests(['tests']) - cov.stop() - - # Discover the list of all modules that we should test coverage for - import rest_framework - - project_dir = os.path.dirname(rest_framework.__file__) +def prepare_report(project_dir): cov_files = [] for (path, dirs, files) in os.walk(project_dir): @@ -66,9 +51,47 @@ def main(): cov_files.extend([os.path.join(path, file) for file in files if file.endswith('.py')]) - cov.report(cov_files) - if '--html' in sys.argv: - cov.html_report(cov_files, directory='coverage') + return cov_files + + +def run_tests(app): + from django.conf import settings + from django.test.utils import get_runner + + TestRunner = get_runner(settings) + if hasattr(TestRunner, 'func_name'): + # Pre 1.2 test runners were just functions, + # and did not support the 'failfast' option. + import warnings + + warnings.warn( + 'Function-based test runners are deprecated. Test runners should be classes with a run_tests() method.', + DeprecationWarning + ) + failures = TestRunner([app]) + else: + test_runner = TestRunner() + failures = test_runner.run_tests([app]) + return failures + + +def main(): + """Run the tests for rest_framework and generate a coverage report.""" + + cov = coverage() + cov.erase() + cov.start() + + failures = run_tests('rest_framework') + cov.stop() + + # Discover the list of all modules that we should test coverage for + import rest_framework + + project_dir = os.path.dirname(rest_framework.__file__) + cov_files = prepare_report(project_dir) + + report(cov, cov_files) sys.exit(failures) if __name__ == '__main__': diff --git a/rest_framework/runtests/runtests.py b/rest_framework/runtests/runtests.py index 505994e28..9a4b61f78 100755 --- a/rest_framework/runtests/runtests.py +++ b/rest_framework/runtests/runtests.py @@ -1,43 +1,11 @@ #!/usr/bin/env python - -# http://ericholscher.com/blog/2009/jun/29/enable-setuppy-test-your-django-apps/ -# http://www.travisswicegood.com/2010/01/17/django-virtualenv-pip-and-fabric/ -# http://code.djangoproject.com/svn/django/trunk/tests/runtests.py import os import sys -# fix sys path so we don't need to setup PYTHONPATH sys.path.append(os.path.join(os.path.dirname(__file__), "../..")) -os.environ['DJANGO_SETTINGS_MODULE'] = 'rest_framework.runtests.settings' +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rest_framework.tests.settings") -from django.conf import settings -from django.test.utils import get_runner +from django.core.management import execute_from_command_line - -def usage(): - return """ - Usage: python runtests.py [UnitTestClass].[method] - - You can pass the Class name of the `UnitTestClass` you want to test. - - Append a method name if you only want to test a specific method of that class. - """ - - -def main(): - TestRunner = get_runner(settings) - - test_runner = TestRunner() - if len(sys.argv) == 2: - test_case = '.' + sys.argv[1] - elif len(sys.argv) == 1: - test_case = '' - else: - print usage() - sys.exit(1) - failures = test_runner.run_tests(['tests' + test_case]) - - sys.exit(failures) - -if __name__ == '__main__': - main() +sys.argv.append('test') +execute_from_command_line(sys.argv) diff --git a/rest_framework/runtests/settings.py b/rest_framework/runtests/settings.py deleted file mode 100644 index dd5d9dc3c..000000000 --- a/rest_framework/runtests/settings.py +++ /dev/null @@ -1,117 +0,0 @@ -# Django settings for testproject project. - -DEBUG = True -TEMPLATE_DEBUG = DEBUG -DEBUG_PROPAGATE_EXCEPTIONS = True - -ADMINS = ( - # ('Your Name', 'your_email@domain.com'), -) - -MANAGERS = ADMINS - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'sqlite.db', # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. - } -} - -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - } -} - -# Local time zone for this installation. Choices can be found here: -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# although not all choices may be available on all operating systems. -# On Unix systems, a value of None will cause Django to use the same -# timezone as the operating system. -# If running in a Windows environment this must be set to the same as your -# system time zone. -TIME_ZONE = 'Europe/London' - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-uk' - -SITE_ID = 1 - -# If you set this to False, Django will make some optimizations so as not -# to load the internationalization machinery. -USE_I18N = True - -# If you set this to False, Django will not format dates, numbers and -# calendars according to the current locale -USE_L10N = True - -# Absolute filesystem path to the directory that will hold user-uploaded files. -# Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = '' - -# URL that handles the media served from MEDIA_ROOT. Make sure to use a -# trailing slash if there is a path component (optional in other cases). -# Examples: "http://media.lawrence.com", "http://example.com/media/" -MEDIA_URL = '' - -# Make this unique, and don't share it with anybody. -SECRET_KEY = 'u@x-aj9(hoh#rb-^ymf#g2jx_hp0vj7u5#b@ag1n^seu9e!%cy' - -# List of callables that know how to import templates from various sources. -TEMPLATE_LOADERS = ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', -# 'django.template.loaders.eggs.Loader', -) - -MIDDLEWARE_CLASSES = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', -) - -ROOT_URLCONF = 'urls' - -TEMPLATE_DIRS = ( - # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) - -INSTALLED_APPS = ( - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - # Uncomment the next line to enable the admin: - # 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', - 'rest_framework', - 'rest_framework.authtoken', - 'rest_framework.tests' -) - -STATIC_URL = '/static/' - -import django - -if django.VERSION < (1, 3): - INSTALLED_APPS += ('staticfiles',) - - -# If we're running on the Jenkins server we want to archive the coverage reports as XML. -import os -if os.environ.get('HUDSON_URL', None): - TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' - TEST_OUTPUT_VERBOSE = True - TEST_OUTPUT_DESCRIPTIONS = True - TEST_OUTPUT_DIR = 'xmlrunner' diff --git a/rest_framework/tests/settings.py b/rest_framework/tests/settings.py index 0293fdc3e..af5617a9d 100644 --- a/rest_framework/tests/settings.py +++ b/rest_framework/tests/settings.py @@ -1,21 +1,122 @@ -"""Tests for the settings module""" -from django.test import TestCase +# Django settings for testproject project. -from rest_framework.settings import APISettings, DEFAULTS, IMPORT_STRINGS +DEBUG = True +TEMPLATE_DEBUG = DEBUG +DEBUG_PROPAGATE_EXCEPTIONS = True + +ADMINS = ( +# ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': 'sqlite.db', # Or path to database file if using sqlite3. + 'USER': '', # Not used with sqlite3. + 'PASSWORD': '', # Not used with sqlite3. + 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. + 'PORT': '', # Set to empty string for default. Not used with sqlite3. + } +} + +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + } +} + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# On Unix systems, a value of None will cause Django to use the same +# timezone as the operating system. +# If running in a Windows environment this must be set to the same as your +# system time zone. +TIME_ZONE = 'Europe/London' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-uk' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale +USE_L10N = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash if there is a path component (optional in other cases). +# Examples: "http://media.lawrence.com", "http://example.com/media/" +MEDIA_URL = '' + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'u@x-aj9(hoh#rb-^ymf#g2jx_hp0vj7u5#b@ag1n^seu9e!%cy' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', + # 'django.template.loaders.eggs.Loader', + ) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + ) + +ROOT_URLCONF = 'urls' + +TEMPLATE_DIRS = ( +# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". +# Always use forward slashes, even on Windows. +# Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + # Uncomment the next line to enable the admin: + # 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', + 'rest_framework', + 'rest_framework.authtoken', + 'rest_framework.tests', + 'discover_runner' + ) + +TEST_RUNNER = 'discover_runner.runner.DiscoverRunner' + +STATIC_URL = '/static/' + +import django + +if django.VERSION < (1, 3): + INSTALLED_APPS += ('staticfiles',) -class TestSettings(TestCase): - """Tests relating to the api settings""" +# If we're running on the Jenkins server we want to archive the coverage reports as XML. +import os - def test_non_import_errors(self): - """Make sure other errors aren't suppressed.""" - settings = APISettings({'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.tests.extras.bad_import.ModelSerializer'}, DEFAULTS, IMPORT_STRINGS) - with self.assertRaises(ValueError): - settings.DEFAULT_MODEL_SERIALIZER_CLASS - - def test_import_error_message_maintained(self): - """Make sure real import errors are captured and raised sensibly.""" - settings = APISettings({'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.tests.extras.not_here.ModelSerializer'}, DEFAULTS, IMPORT_STRINGS) - with self.assertRaises(ImportError) as cm: - settings.DEFAULT_MODEL_SERIALIZER_CLASS - self.assertTrue('ImportError' in str(cm.exception)) +if os.environ.get('HUDSON_URL', None): + TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' + TEST_OUTPUT_VERBOSE = True + TEST_OUTPUT_DESCRIPTIONS = True + TEST_OUTPUT_DIR = 'xmlrunner' diff --git a/rest_framework/tests/authentication.py b/rest_framework/tests/test_authentication.py similarity index 100% rename from rest_framework/tests/authentication.py rename to rest_framework/tests/test_authentication.py diff --git a/rest_framework/tests/breadcrumbs.py b/rest_framework/tests/test_breadcrumbs.py similarity index 64% rename from rest_framework/tests/breadcrumbs.py rename to rest_framework/tests/test_breadcrumbs.py index df8916832..2391dd68f 100644 --- a/rest_framework/tests/breadcrumbs.py +++ b/rest_framework/tests/test_breadcrumbs.py @@ -35,7 +35,7 @@ urlpatterns = patterns('', class BreadcrumbTests(TestCase): """Tests the breadcrumb functionality used by the HTML renderer.""" - urls = 'rest_framework.tests.breadcrumbs' + urls = 'rest_framework.tests.test_breadcrumbs' def test_root_breadcrumbs(self): url = '/' @@ -44,28 +44,28 @@ class BreadcrumbTests(TestCase): def test_resource_root_breadcrumbs(self): url = '/resource/' self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/')]) + ('Resource Root', '/resource/')]) def test_resource_instance_breadcrumbs(self): url = '/resource/123' self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123')]) + ('Resource Root', '/resource/'), + ('Resource Instance', '/resource/123')]) def test_nested_resource_breadcrumbs(self): url = '/resource/123/' self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123'), - ('Nested Resource Root', '/resource/123/')]) + ('Resource Root', '/resource/'), + ('Resource Instance', '/resource/123'), + ('Nested Resource Root', '/resource/123/')]) def test_nested_resource_instance_breadcrumbs(self): url = '/resource/123/abc' self.assertEqual(get_breadcrumbs(url), [('Root', '/'), - ('Resource Root', '/resource/'), - ('Resource Instance', '/resource/123'), - ('Nested Resource Root', '/resource/123/'), - ('Nested Resource Instance', '/resource/123/abc')]) + ('Resource Root', '/resource/'), + ('Resource Instance', '/resource/123'), + ('Nested Resource Root', '/resource/123/'), + ('Nested Resource Instance', '/resource/123/abc')]) def test_broken_url_breadcrumbs_handled_gracefully(self): url = '/foobar' diff --git a/rest_framework/tests/decorators.py b/rest_framework/tests/test_decorators.py similarity index 100% rename from rest_framework/tests/decorators.py rename to rest_framework/tests/test_decorators.py diff --git a/rest_framework/tests/description.py b/rest_framework/tests/test_description.py similarity index 99% rename from rest_framework/tests/description.py rename to rest_framework/tests/test_description.py index d958b8405..a681ce64b 100644 --- a/rest_framework/tests/description.py +++ b/rest_framework/tests/test_description.py @@ -48,20 +48,25 @@ MARKED_DOWN_gte_21 = """

an example docstring

class TestViewNamesAndDescriptions(TestCase): def test_resource_name_uses_classname_by_default(self): """Ensure Resource names are based on the classname by default.""" + class MockView(APIView): pass + self.assertEquals(MockView().get_name(), 'Mock') def test_resource_name_can_be_set_explicitly(self): """Ensure Resource names can be set using the 'get_name' method.""" example = 'Some Other Name' + class MockView(APIView): def get_name(self): return example + self.assertEquals(MockView().get_name(), example) def test_resource_description_uses_docstring_by_default(self): """Ensure Resource names are based on the docstring by default.""" + class MockView(APIView): """an example docstring ==================== @@ -86,8 +91,10 @@ class TestViewNamesAndDescriptions(TestCase): class MockView(APIView): """docstring""" + def get_description(self): return example + self.assertEquals(MockView().get_description(), example) def test_resource_description_does_not_require_docstring(self): @@ -97,12 +104,15 @@ class TestViewNamesAndDescriptions(TestCase): class MockView(APIView): def get_description(self): return example + self.assertEquals(MockView().get_description(), example) def test_resource_description_can_be_empty(self): """Ensure that if a resource has no doctring or 'description' class attribute, then it's description is the empty string.""" + class MockView(APIView): pass + self.assertEquals(MockView().get_description(), '') def test_markdown(self): diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/test_fields.py similarity index 100% rename from rest_framework/tests/fields.py rename to rest_framework/tests/test_fields.py diff --git a/rest_framework/tests/files.py b/rest_framework/tests/test_files.py similarity index 100% rename from rest_framework/tests/files.py rename to rest_framework/tests/test_files.py diff --git a/rest_framework/tests/filterset.py b/rest_framework/tests/test_filterset.py similarity index 98% rename from rest_framework/tests/filterset.py rename to rest_framework/tests/test_filterset.py index af2e6c2e7..afc329993 100644 --- a/rest_framework/tests/filterset.py +++ b/rest_framework/tests/test_filterset.py @@ -9,7 +9,6 @@ from rest_framework.tests.models import FilterableItem, BasicModel factory = RequestFactory() - if django_filters: # Basic filter on a list view. class FilterFieldsRootView(generics.ListCreateAPIView): @@ -142,7 +141,7 @@ class IntegrationTestFiltering(TestCase): response = view(request).render() self.assertEquals(response.status_code, status.HTTP_200_OK) expected_data = [f for f in self.data if f['date'] > search_date and - f['decimal'] < search_decimal] + f['decimal'] < search_decimal] self.assertEquals(response.data, expected_data) @unittest.skipUnless(django_filters, 'django-filters not installed') diff --git a/rest_framework/tests/genericrelations.py b/rest_framework/tests/test_genericrelations.py similarity index 100% rename from rest_framework/tests/genericrelations.py rename to rest_framework/tests/test_genericrelations.py diff --git a/rest_framework/tests/generics.py b/rest_framework/tests/test_generics.py similarity index 100% rename from rest_framework/tests/generics.py rename to rest_framework/tests/test_generics.py diff --git a/rest_framework/tests/htmlrenderer.py b/rest_framework/tests/test_htmlrenderer.py similarity index 97% rename from rest_framework/tests/htmlrenderer.py rename to rest_framework/tests/test_htmlrenderer.py index 239fcc5c7..bd9055131 100644 --- a/rest_framework/tests/htmlrenderer.py +++ b/rest_framework/tests/test_htmlrenderer.py @@ -40,7 +40,7 @@ urlpatterns = patterns('', class TemplateHTMLRendererTests(TestCase): - urls = 'rest_framework.tests.htmlrenderer' + urls = 'rest_framework.tests.test_htmlrenderer' def setUp(self): """ @@ -80,7 +80,7 @@ class TemplateHTMLRendererTests(TestCase): class TemplateHTMLRendererExceptionTests(TestCase): - urls = 'rest_framework.tests.htmlrenderer' + urls = 'rest_framework.tests.test_htmlrenderer' def setUp(self): """ diff --git a/rest_framework/tests/hyperlinkedserializers.py b/rest_framework/tests/test_hyperlinkedserializers.py similarity index 96% rename from rest_framework/tests/hyperlinkedserializers.py rename to rest_framework/tests/test_hyperlinkedserializers.py index df0666ac3..a6642ade8 100644 --- a/rest_framework/tests/hyperlinkedserializers.py +++ b/rest_framework/tests/test_hyperlinkedserializers.py @@ -96,7 +96,7 @@ urlpatterns = patterns('', class TestBasicHyperlinkedView(TestCase): - urls = 'rest_framework.tests.hyperlinkedserializers' + urls = 'rest_framework.tests.test_hyperlinkedserializers' def setUp(self): """ @@ -133,7 +133,7 @@ class TestBasicHyperlinkedView(TestCase): class TestManyToManyHyperlinkedView(TestCase): - urls = 'rest_framework.tests.hyperlinkedserializers' + urls = 'rest_framework.tests.test_hyperlinkedserializers' def setUp(self): """ @@ -181,7 +181,7 @@ class TestManyToManyHyperlinkedView(TestCase): class TestCreateWithForeignKeys(TestCase): - urls = 'rest_framework.tests.hyperlinkedserializers' + urls = 'rest_framework.tests.test_hyperlinkedserializers' def setUp(self): """ @@ -205,7 +205,7 @@ class TestCreateWithForeignKeys(TestCase): class TestCreateWithForeignKeysAndCustomSlug(TestCase): - urls = 'rest_framework.tests.hyperlinkedserializers' + urls = 'rest_framework.tests.test_hyperlinkedserializers' def setUp(self): """ @@ -230,7 +230,7 @@ class TestCreateWithForeignKeysAndCustomSlug(TestCase): class TestOptionalRelationHyperlinkedView(TestCase): - urls = 'rest_framework.tests.hyperlinkedserializers' + urls = 'rest_framework.tests.test_hyperlinkedserializers' def setUp(self): """ diff --git a/rest_framework/tests/negotiation.py b/rest_framework/tests/test_negotiation.py similarity index 100% rename from rest_framework/tests/negotiation.py rename to rest_framework/tests/test_negotiation.py diff --git a/rest_framework/tests/pagination.py b/rest_framework/tests/test_pagination.py similarity index 99% rename from rest_framework/tests/pagination.py rename to rest_framework/tests/test_pagination.py index 3b5508779..fe9953ade 100644 --- a/rest_framework/tests/pagination.py +++ b/rest_framework/tests/test_pagination.py @@ -62,8 +62,8 @@ class IntegrationTestPagination(TestCase): BasicModel(text=char * 3).save() self.objects = BasicModel.objects self.data = [ - {'id': obj.id, 'text': obj.text} - for obj in self.objects.all() + {'id': obj.id, 'text': obj.text} + for obj in self.objects.all() ] self.view = RootView.as_view() @@ -97,7 +97,6 @@ class IntegrationTestPagination(TestCase): class IntegrationTestPaginationAndFiltering(TestCase): - def setUp(self): """ Create 50 FilterableItem instances. diff --git a/rest_framework/tests/parsers.py b/rest_framework/tests/test_parsers.py similarity index 100% rename from rest_framework/tests/parsers.py rename to rest_framework/tests/test_parsers.py diff --git a/rest_framework/tests/relations.py b/rest_framework/tests/test_relations.py similarity index 100% rename from rest_framework/tests/relations.py rename to rest_framework/tests/test_relations.py diff --git a/rest_framework/tests/relations_hyperlink.py b/rest_framework/tests/test_relations_hyperlink.py similarity index 84% rename from rest_framework/tests/relations_hyperlink.py rename to rest_framework/tests/test_relations_hyperlink.py index 6d137f68d..0ad78dfbd 100644 --- a/rest_framework/tests/relations_hyperlink.py +++ b/rest_framework/tests/test_relations_hyperlink.py @@ -59,7 +59,7 @@ class NullableOneToOneTargetSerializer(serializers.HyperlinkedModelSerializer): # TODO: Add test that .data cannot be accessed prior to .is_valid class HyperlinkedManyToManyTests(TestCase): - urls = 'rest_framework.tests.relations_hyperlink' + urls = 'rest_framework.tests.test_relations_hyperlink' def setUp(self): for idx in range(1, 4): @@ -74,9 +74,11 @@ class HyperlinkedManyToManyTests(TestCase): queryset = ManyToManySource.objects.all() serializer = ManyToManySourceSerializer(queryset) expected = [ - {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/']}, - {'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, - {'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} + {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/']}, + {'url': '/manytomanysource/2/', 'name': u'source-2', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, + {'url': '/manytomanysource/3/', 'name': u'source-3', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} ] self.assertEquals(serializer.data, expected) @@ -84,14 +86,17 @@ class HyperlinkedManyToManyTests(TestCase): queryset = ManyToManyTarget.objects.all() serializer = ManyToManyTargetSerializer(queryset) expected = [ - {'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']}, - {'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, + {'url': '/manytomanytarget/1/', 'name': u'target-1', + 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']}, + {'url': '/manytomanytarget/2/', 'name': u'target-2', + 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, {'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']} ] self.assertEquals(serializer.data, expected) def test_many_to_many_update(self): - data = {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} + data = {'url': '/manytomanysource/1/', 'name': u'source-1', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} instance = ManyToManySource.objects.get(pk=1) serializer = ManyToManySourceSerializer(instance, data=data) self.assertTrue(serializer.is_valid()) @@ -102,9 +107,12 @@ class HyperlinkedManyToManyTests(TestCase): queryset = ManyToManySource.objects.all() serializer = ManyToManySourceSerializer(queryset) expected = [ - {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}, - {'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, - {'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} + {'url': '/manytomanysource/1/', 'name': u'source-1', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}, + {'url': '/manytomanysource/2/', 'name': u'source-2', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, + {'url': '/manytomanysource/3/', 'name': u'source-3', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']} ] self.assertEquals(serializer.data, expected) @@ -121,14 +129,16 @@ class HyperlinkedManyToManyTests(TestCase): serializer = ManyToManyTargetSerializer(queryset) expected = [ {'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/']}, - {'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, + {'url': '/manytomanytarget/2/', 'name': u'target-2', + 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, {'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']} ] self.assertEquals(serializer.data, expected) def test_many_to_many_create(self): - data = {'url': '/manytomanysource/4/', 'name': u'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']} + data = {'url': '/manytomanysource/4/', 'name': u'source-4', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']} serializer = ManyToManySourceSerializer(data=data) self.assertTrue(serializer.is_valid()) obj = serializer.save() @@ -140,14 +150,18 @@ class HyperlinkedManyToManyTests(TestCase): serializer = ManyToManySourceSerializer(queryset) expected = [ {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/']}, - {'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, - {'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}, - {'url': '/manytomanysource/4/', 'name': u'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']} + {'url': '/manytomanysource/2/', 'name': u'source-2', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']}, + {'url': '/manytomanysource/3/', 'name': u'source-3', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}, + {'url': '/manytomanysource/4/', 'name': u'source-4', + 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']} ] self.assertEquals(serializer.data, expected) def test_reverse_many_to_many_create(self): - data = {'url': '/manytomanytarget/4/', 'name': u'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']} + data = {'url': '/manytomanytarget/4/', 'name': u'target-4', + 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']} serializer = ManyToManyTargetSerializer(data=data) self.assertTrue(serializer.is_valid()) obj = serializer.save() @@ -158,16 +172,19 @@ class HyperlinkedManyToManyTests(TestCase): queryset = ManyToManyTarget.objects.all() serializer = ManyToManyTargetSerializer(queryset) expected = [ - {'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']}, - {'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, + {'url': '/manytomanytarget/1/', 'name': u'target-1', + 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']}, + {'url': '/manytomanytarget/2/', 'name': u'target-2', + 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']}, {'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']}, - {'url': '/manytomanytarget/4/', 'name': u'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']} + {'url': '/manytomanytarget/4/', 'name': u'target-4', + 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']} ] self.assertEquals(serializer.data, expected) class HyperlinkedForeignKeyTests(TestCase): - urls = 'rest_framework.tests.relations_hyperlink' + urls = 'rest_framework.tests.test_relations_hyperlink' def setUp(self): target = ForeignKeyTarget(name='target-1') @@ -192,7 +209,8 @@ class HyperlinkedForeignKeyTests(TestCase): queryset = ForeignKeyTarget.objects.all() serializer = ForeignKeyTargetSerializer(queryset) expected = [ - {'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']}, + {'url': '/foreignkeytarget/1/', 'name': u'target-1', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']}, {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []}, ] self.assertEquals(serializer.data, expected) @@ -223,7 +241,8 @@ class HyperlinkedForeignKeyTests(TestCase): self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected url string, received int.']}) def test_reverse_foreign_key_update(self): - data = {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']} + data = {'url': '/foreignkeytarget/2/', 'name': u'target-2', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']} instance = ForeignKeyTarget.objects.get(pk=2) serializer = ForeignKeyTargetSerializer(instance, data=data) self.assertTrue(serializer.is_valid()) @@ -232,7 +251,8 @@ class HyperlinkedForeignKeyTests(TestCase): queryset = ForeignKeyTarget.objects.all() new_serializer = ForeignKeyTargetSerializer(queryset) expected = [ - {'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']}, + {'url': '/foreignkeytarget/1/', 'name': u'target-1', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']}, {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []}, ] self.assertEquals(new_serializer.data, expected) @@ -245,7 +265,8 @@ class HyperlinkedForeignKeyTests(TestCase): serializer = ForeignKeyTargetSerializer(queryset) expected = [ {'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/2/']}, - {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}, + {'url': '/foreignkeytarget/2/', 'name': u'target-2', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}, ] self.assertEquals(serializer.data, expected) @@ -269,7 +290,8 @@ class HyperlinkedForeignKeyTests(TestCase): self.assertEquals(serializer.data, expected) def test_reverse_foreign_key_create(self): - data = {'url': '/foreignkeytarget/3/', 'name': u'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']} + data = {'url': '/foreignkeytarget/3/', 'name': u'target-3', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']} serializer = ForeignKeyTargetSerializer(data=data) self.assertTrue(serializer.is_valid()) obj = serializer.save() @@ -282,7 +304,8 @@ class HyperlinkedForeignKeyTests(TestCase): expected = [ {'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/2/']}, {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []}, - {'url': '/foreignkeytarget/3/', 'name': u'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}, + {'url': '/foreignkeytarget/3/', 'name': u'target-3', + 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}, ] self.assertEquals(serializer.data, expected) @@ -295,7 +318,7 @@ class HyperlinkedForeignKeyTests(TestCase): class HyperlinkedNullableForeignKeyTests(TestCase): - urls = 'rest_framework.tests.relations_hyperlink' + urls = 'rest_framework.tests.test_relations_hyperlink' def setUp(self): target = ForeignKeyTarget(name='target-1') @@ -400,30 +423,30 @@ class HyperlinkedNullableForeignKeyTests(TestCase): ] self.assertEquals(serializer.data, expected) - # reverse foreign keys MUST be read_only - # In the general case they do not provide .remove() or .clear() - # and cannot be arbitrarily set. + # reverse foreign keys MUST be read_only + # In the general case they do not provide .remove() or .clear() + # and cannot be arbitrarily set. - # def test_reverse_foreign_key_update(self): - # data = {'id': 1, 'name': u'target-1', 'sources': [1]} - # instance = ForeignKeyTarget.objects.get(pk=1) - # serializer = ForeignKeyTargetSerializer(instance, data=data) - # self.assertTrue(serializer.is_valid()) - # self.assertEquals(serializer.data, data) - # serializer.save() + # def test_reverse_foreign_key_update(self): + # data = {'id': 1, 'name': u'target-1', 'sources': [1]} + # instance = ForeignKeyTarget.objects.get(pk=1) + # serializer = ForeignKeyTargetSerializer(instance, data=data) + # self.assertTrue(serializer.is_valid()) + # self.assertEquals(serializer.data, data) + # serializer.save() - # # Ensure target 1 is updated, and everything else is as expected - # queryset = ForeignKeyTarget.objects.all() - # serializer = ForeignKeyTargetSerializer(queryset) - # expected = [ - # {'id': 1, 'name': u'target-1', 'sources': [1]}, - # {'id': 2, 'name': u'target-2', 'sources': []}, - # ] - # self.assertEquals(serializer.data, expected) + # # Ensure target 1 is updated, and everything else is as expected + # queryset = ForeignKeyTarget.objects.all() + # serializer = ForeignKeyTargetSerializer(queryset) + # expected = [ + # {'id': 1, 'name': u'target-1', 'sources': [1]}, + # {'id': 2, 'name': u'target-2', 'sources': []}, + # ] + # self.assertEquals(serializer.data, expected) class HyperlinkedNullableOneToOneTests(TestCase): - urls = 'rest_framework.tests.relations_hyperlink' + urls = 'rest_framework.tests.test_relations_hyperlink' def setUp(self): target = OneToOneTarget(name='target-1') diff --git a/rest_framework/tests/relations_nested.py b/rest_framework/tests/test_relations_nested.py similarity index 100% rename from rest_framework/tests/relations_nested.py rename to rest_framework/tests/test_relations_nested.py diff --git a/rest_framework/tests/relations_pk.py b/rest_framework/tests/test_relations_pk.py similarity index 92% rename from rest_framework/tests/relations_pk.py rename to rest_framework/tests/test_relations_pk.py index 3391e60af..88895b772 100644 --- a/rest_framework/tests/relations_pk.py +++ b/rest_framework/tests/test_relations_pk.py @@ -56,9 +56,9 @@ class PKManyToManyTests(TestCase): queryset = ManyToManySource.objects.all() serializer = ManyToManySourceSerializer(queryset) expected = [ - {'id': 1, 'name': u'source-1', 'targets': [1]}, - {'id': 2, 'name': u'source-2', 'targets': [1, 2]}, - {'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]} + {'id': 1, 'name': u'source-1', 'targets': [1]}, + {'id': 2, 'name': u'source-2', 'targets': [1, 2]}, + {'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]} ] self.assertEquals(serializer.data, expected) @@ -84,9 +84,9 @@ class PKManyToManyTests(TestCase): queryset = ManyToManySource.objects.all() serializer = ManyToManySourceSerializer(queryset) expected = [ - {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]}, - {'id': 2, 'name': u'source-2', 'targets': [1, 2]}, - {'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]} + {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]}, + {'id': 2, 'name': u'source-2', 'targets': [1, 2]}, + {'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]} ] self.assertEquals(serializer.data, expected) @@ -377,26 +377,26 @@ class PKNullableForeignKeyTests(TestCase): ] self.assertEquals(serializer.data, expected) - # reverse foreign keys MUST be read_only - # In the general case they do not provide .remove() or .clear() - # and cannot be arbitrarily set. + # reverse foreign keys MUST be read_only + # In the general case they do not provide .remove() or .clear() + # and cannot be arbitrarily set. - # def test_reverse_foreign_key_update(self): - # data = {'id': 1, 'name': u'target-1', 'sources': [1]} - # instance = ForeignKeyTarget.objects.get(pk=1) - # serializer = ForeignKeyTargetSerializer(instance, data=data) - # self.assertTrue(serializer.is_valid()) - # self.assertEquals(serializer.data, data) - # serializer.save() + # def test_reverse_foreign_key_update(self): + # data = {'id': 1, 'name': u'target-1', 'sources': [1]} + # instance = ForeignKeyTarget.objects.get(pk=1) + # serializer = ForeignKeyTargetSerializer(instance, data=data) + # self.assertTrue(serializer.is_valid()) + # self.assertEquals(serializer.data, data) + # serializer.save() - # # Ensure target 1 is updated, and everything else is as expected - # queryset = ForeignKeyTarget.objects.all() - # serializer = ForeignKeyTargetSerializer(queryset) - # expected = [ - # {'id': 1, 'name': u'target-1', 'sources': [1]}, - # {'id': 2, 'name': u'target-2', 'sources': []}, - # ] - # self.assertEquals(serializer.data, expected) + # # Ensure target 1 is updated, and everything else is as expected + # queryset = ForeignKeyTarget.objects.all() + # serializer = ForeignKeyTargetSerializer(queryset) + # expected = [ + # {'id': 1, 'name': u'target-1', 'sources': [1]}, + # {'id': 2, 'name': u'target-2', 'sources': []}, + # ] + # self.assertEquals(serializer.data, expected) class PKNullableOneToOneTests(TestCase): diff --git a/rest_framework/tests/relations_slug.py b/rest_framework/tests/test_relations_slug.py similarity index 100% rename from rest_framework/tests/relations_slug.py rename to rest_framework/tests/test_relations_slug.py diff --git a/rest_framework/tests/renderers.py b/rest_framework/tests/test_renderers.py similarity index 100% rename from rest_framework/tests/renderers.py rename to rest_framework/tests/test_renderers.py diff --git a/rest_framework/tests/request.py b/rest_framework/tests/test_request.py similarity index 62% rename from rest_framework/tests/request.py rename to rest_framework/tests/test_request.py index 4b0324056..cf09a759a 100644 --- a/rest_framework/tests/request.py +++ b/rest_framework/tests/test_request.py @@ -15,7 +15,7 @@ from rest_framework.parsers import ( FormParser, MultiPartParser, JSONParser -) + ) from rest_framework.request import Request from rest_framework.response import Response from rest_framework.settings import api_settings @@ -111,8 +111,9 @@ class TestContentParsing(TestCase): if VERSION >= (1, 5): from django.test.client import MULTIPART_CONTENT, BOUNDARY, encode_multipart + request = Request(factory.put('/', encode_multipart(BOUNDARY, data), - content_type=MULTIPART_CONTENT)) + content_type=MULTIPART_CONTENT)) else: request = Request(factory.put('/', data)) @@ -145,88 +146,88 @@ class TestContentParsing(TestCase): request.parsers = (JSONParser(), ) self.assertEqual(request.DATA, json_data) - # def test_accessing_post_after_data_form(self): - # """ - # Ensures request.POST can be accessed after request.DATA in - # form request. - # """ - # data = {'qwerty': 'uiop'} - # request = factory.post('/', data=data) - # self.assertEqual(request.DATA.items(), data.items()) - # self.assertEqual(request.POST.items(), data.items()) + # def test_accessing_post_after_data_form(self): + # """ + # Ensures request.POST can be accessed after request.DATA in + # form request. + # """ + # data = {'qwerty': 'uiop'} + # request = factory.post('/', data=data) + # self.assertEqual(request.DATA.items(), data.items()) + # self.assertEqual(request.POST.items(), data.items()) - # def test_accessing_post_after_data_for_json(self): - # """ - # Ensures request.POST can be accessed after request.DATA in - # json request. - # """ - # data = {'qwerty': 'uiop'} - # content = json.dumps(data) - # content_type = 'application/json' - # parsers = (JSONParser, ) + # def test_accessing_post_after_data_for_json(self): + # """ + # Ensures request.POST can be accessed after request.DATA in + # json request. + # """ + # data = {'qwerty': 'uiop'} + # content = json.dumps(data) + # content_type = 'application/json' + # parsers = (JSONParser, ) - # request = factory.post('/', content, content_type=content_type, - # parsers=parsers) - # self.assertEqual(request.DATA.items(), data.items()) - # self.assertEqual(request.POST.items(), []) + # request = factory.post('/', content, content_type=content_type, + # parsers=parsers) + # self.assertEqual(request.DATA.items(), data.items()) + # self.assertEqual(request.POST.items(), []) - # def test_accessing_post_after_data_for_overloaded_json(self): - # """ - # Ensures request.POST can be accessed after request.DATA in overloaded - # json request. - # """ - # data = {'qwerty': 'uiop'} - # content = json.dumps(data) - # content_type = 'application/json' - # parsers = (JSONParser, ) - # form_data = {Request._CONTENT_PARAM: content, - # Request._CONTENTTYPE_PARAM: content_type} + # def test_accessing_post_after_data_for_overloaded_json(self): + # """ + # Ensures request.POST can be accessed after request.DATA in overloaded + # json request. + # """ + # data = {'qwerty': 'uiop'} + # content = json.dumps(data) + # content_type = 'application/json' + # parsers = (JSONParser, ) + # form_data = {Request._CONTENT_PARAM: content, + # Request._CONTENTTYPE_PARAM: content_type} - # request = factory.post('/', form_data, parsers=parsers) - # self.assertEqual(request.DATA.items(), data.items()) - # self.assertEqual(request.POST.items(), form_data.items()) + # request = factory.post('/', form_data, parsers=parsers) + # self.assertEqual(request.DATA.items(), data.items()) + # self.assertEqual(request.POST.items(), form_data.items()) - # def test_accessing_data_after_post_form(self): - # """ - # Ensures request.DATA can be accessed after request.POST in - # form request. - # """ - # data = {'qwerty': 'uiop'} - # parsers = (FormParser, MultiPartParser) - # request = factory.post('/', data, parsers=parsers) + # def test_accessing_data_after_post_form(self): + # """ + # Ensures request.DATA can be accessed after request.POST in + # form request. + # """ + # data = {'qwerty': 'uiop'} + # parsers = (FormParser, MultiPartParser) + # request = factory.post('/', data, parsers=parsers) - # self.assertEqual(request.POST.items(), data.items()) - # self.assertEqual(request.DATA.items(), data.items()) + # self.assertEqual(request.POST.items(), data.items()) + # self.assertEqual(request.DATA.items(), data.items()) - # def test_accessing_data_after_post_for_json(self): - # """ - # Ensures request.DATA can be accessed after request.POST in - # json request. - # """ - # data = {'qwerty': 'uiop'} - # content = json.dumps(data) - # content_type = 'application/json' - # parsers = (JSONParser, ) - # request = factory.post('/', content, content_type=content_type, - # parsers=parsers) - # self.assertEqual(request.POST.items(), []) - # self.assertEqual(request.DATA.items(), data.items()) + # def test_accessing_data_after_post_for_json(self): + # """ + # Ensures request.DATA can be accessed after request.POST in + # json request. + # """ + # data = {'qwerty': 'uiop'} + # content = json.dumps(data) + # content_type = 'application/json' + # parsers = (JSONParser, ) + # request = factory.post('/', content, content_type=content_type, + # parsers=parsers) + # self.assertEqual(request.POST.items(), []) + # self.assertEqual(request.DATA.items(), data.items()) - # def test_accessing_data_after_post_for_overloaded_json(self): - # """ - # Ensures request.DATA can be accessed after request.POST in overloaded - # json request - # """ - # data = {'qwerty': 'uiop'} - # content = json.dumps(data) - # content_type = 'application/json' - # parsers = (JSONParser, ) - # form_data = {Request._CONTENT_PARAM: content, - # Request._CONTENTTYPE_PARAM: content_type} + # def test_accessing_data_after_post_for_overloaded_json(self): + # """ + # Ensures request.DATA can be accessed after request.POST in overloaded + # json request + # """ + # data = {'qwerty': 'uiop'} + # content = json.dumps(data) + # content_type = 'application/json' + # parsers = (JSONParser, ) + # form_data = {Request._CONTENT_PARAM: content, + # Request._CONTENTTYPE_PARAM: content_type} - # request = factory.post('/', form_data, parsers=parsers) - # self.assertEqual(request.POST.items(), form_data.items()) - # self.assertEqual(request.DATA.items(), data.items()) + # request = factory.post('/', form_data, parsers=parsers) + # self.assertEqual(request.POST.items(), form_data.items()) + # self.assertEqual(request.DATA.items(), data.items()) class MockView(APIView): @@ -244,7 +245,7 @@ urlpatterns = patterns('', class TestContentParsingWithAuthentication(TestCase): - urls = 'rest_framework.tests.request' + urls = 'rest_framework.tests.test_request' def setUp(self): self.csrf_client = Client(enforce_csrf_checks=True) @@ -266,21 +267,20 @@ class TestContentParsingWithAuthentication(TestCase): response = self.csrf_client.post('/', content) self.assertEqual(status.HTTP_200_OK, response.status_code) - # def test_user_logged_in_authentication_has_post_when_logged_in(self): - # """Ensures request.POST exists after UserLoggedInAuthentication when user does log in""" - # self.client.login(username='john', password='password') - # self.csrf_client.login(username='john', password='password') - # content = {'example': 'example'} + # def test_user_logged_in_authentication_has_post_when_logged_in(self): + # """Ensures request.POST exists after UserLoggedInAuthentication when user does log in""" + # self.client.login(username='john', password='password') + # self.csrf_client.login(username='john', password='password') + # content = {'example': 'example'} - # response = self.client.post('/', content) - # self.assertEqual(status.OK, response.status_code, "POST data is malformed") + # response = self.client.post('/', content) + # self.assertEqual(status.OK, response.status_code, "POST data is malformed") - # response = self.csrf_client.post('/', content) - # self.assertEqual(status.OK, response.status_code, "POST data is malformed") + # response = self.csrf_client.post('/', content) + # self.assertEqual(status.OK, response.status_code, "POST data is malformed") class TestUserSetter(TestCase): - def setUp(self): # Pass request object through session middleware so session is # available to login and logout functions @@ -306,7 +306,6 @@ class TestUserSetter(TestCase): class TestAuthSetter(TestCase): - def test_auth_can_be_set(self): request = Request(factory.get('/')) request.auth = 'DUMMY' diff --git a/rest_framework/tests/response.py b/rest_framework/tests/test_response.py similarity index 97% rename from rest_framework/tests/response.py rename to rest_framework/tests/test_response.py index 875f4d422..777e4acf5 100644 --- a/rest_framework/tests/response.py +++ b/rest_framework/tests/test_response.py @@ -7,7 +7,7 @@ from rest_framework.renderers import ( BaseRenderer, JSONRenderer, BrowsableAPIRenderer -) + ) from rest_framework.settings import api_settings @@ -78,7 +78,7 @@ class RendererIntegrationTests(TestCase): End-to-end testing of renderers using an ResponseMixin on a generic view. """ - urls = 'rest_framework.tests.response' + urls = 'rest_framework.tests.test_response' def test_default_renderer_serializes_content(self): """If the Accept header is not set the default renderer should serialize the response.""" @@ -122,7 +122,7 @@ class RendererIntegrationTests(TestCase): param = '?%s=%s' % ( api_settings.URL_ACCEPT_OVERRIDE, RendererB.media_type - ) + ) resp = self.client.get('/' + param) self.assertEquals(resp['Content-Type'], RendererB.media_type) self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT)) @@ -148,7 +148,7 @@ class RendererIntegrationTests(TestCase): """If both a 'format' query and a matching Accept header specified, the renderer with the matching format attribute should serialize the response.""" resp = self.client.get('/?format=%s' % RendererB.format, - HTTP_ACCEPT=RendererB.media_type) + HTTP_ACCEPT=RendererB.media_type) self.assertEquals(resp['Content-Type'], RendererB.media_type) self.assertEquals(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT)) self.assertEquals(resp.status_code, DUMMYSTATUS) @@ -158,7 +158,7 @@ class Issue122Tests(TestCase): """ Tests that covers #122. """ - urls = 'rest_framework.tests.response' + urls = 'rest_framework.tests.test_response' def test_only_html_renderer(self): """ diff --git a/rest_framework/tests/reverse.py b/rest_framework/tests/test_reverse.py similarity index 92% rename from rest_framework/tests/reverse.py rename to rest_framework/tests/test_reverse.py index 01801a8e5..506b03b0a 100644 --- a/rest_framework/tests/reverse.py +++ b/rest_framework/tests/test_reverse.py @@ -18,7 +18,7 @@ class ReverseTests(TestCase): """ Tests for fully qualified URLs when using `reverse`. """ - urls = 'rest_framework.tests.reverse' + urls = 'rest_framework.tests.test_reverse' def test_reversed_urls_are_fully_qualified(self): request = factory.get('/view') diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/test_serializer.py similarity index 96% rename from rest_framework/tests/serializer.py rename to rest_framework/tests/test_serializer.py index b4428ca31..21d591717 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -3,8 +3,8 @@ import pickle from django.test import TestCase from rest_framework import serializers from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, - BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel, - ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) + BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel, + ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) class SubComment(object): @@ -49,7 +49,6 @@ class BookSerializer(serializers.ModelSerializer): class ActionItemSerializer(serializers.ModelSerializer): - class Meta: model = ActionItem @@ -64,7 +63,6 @@ class PersonSerializer(serializers.ModelSerializer): class AlbumsSerializer(serializers.ModelSerializer): - class Meta: model = Album fields = ['title'] # lists are also valid options @@ -148,7 +146,7 @@ class BasicTests(TestCase): """ serializer = PersonSerializer(self.person) self.assertEquals(set(serializer.data.keys()), - set(['name', 'age', 'info'])) + set(['name', 'age', 'info'])) def test_field_with_dictionary(self): """ @@ -182,17 +180,19 @@ class ValidationTests(TestCase): 'content': 'x' * 1001, 'created': datetime.datetime(2012, 1, 1) } - self.actionitem = ActionItem(title='Some to do item',) + self.actionitem = ActionItem(title='Some to do item', ) def test_create(self): serializer = CommentSerializer(data=self.data) self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']}) + self.assertEquals(serializer.errors, + {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']}) def test_update(self): serializer = CommentSerializer(self.comment, data=self.data) self.assertEquals(serializer.is_valid(), False) - self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']}) + self.assertEquals(serializer.errors, + {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']}) def test_update_missing_field(self): data = { @@ -234,9 +234,7 @@ class ValidationTests(TestCase): self.assertEquals(serializer.errors, {'non_field_errors': [u'Invalid data']}) def test_cross_field_validation(self): - class CommentSerializerWithCrossFieldValidator(CommentSerializer): - def validate(self, attrs): if attrs["email"] not in attrs["content"]: raise serializers.ValidationError("Email address not in content") @@ -285,7 +283,6 @@ class ValidationTests(TestCase): class CustomValidationTests(TestCase): class CommentSerializerWithFieldValidator(CommentSerializer): - def validate_email(self, attrs, source): value = attrs[source] @@ -356,7 +353,7 @@ class ModelValidationTests(TestCase): serializer.save() second_serializer = AlbumsSerializer(data={'title': 'a'}) self.assertFalse(second_serializer.is_valid()) - self.assertEqual(second_serializer.errors, {'title': [u'Album with this Title already exists.']}) + self.assertEqual(second_serializer.errors, {'title': [u'Album with this Title already exists.']}) def test_foreign_key_with_partial(self): """ @@ -383,8 +380,8 @@ class ModelValidationTests(TestCase): # Updating only the description photo_serializer = PhotoSerializer(instance=photo, - data={'description': 'new'}, - partial=True) + data={'description': 'new'}, + partial=True) self.assertTrue(photo_serializer.is_valid()) self.assertTrue(photo_serializer.save()) @@ -718,12 +715,12 @@ class RelatedTraversalTest(TestCase): expected = { 'title': u'Test blog post', 'comments': [{ - 'text': u'I love this blog post', - 'post_owner': { - "name": u"django", - "age": None - } - }] + 'text': u'I love this blog post', + 'post_owner': { + "name": u"django", + "age": None + } + }] } self.assertEqual(serializer.data, expected) @@ -731,7 +728,6 @@ class RelatedTraversalTest(TestCase): class SerializerMethodFieldTests(TestCase): def setUp(self): - class BoopSerializer(serializers.Serializer): beep = serializers.SerializerMethodField('get_beep') boop = serializers.Field() @@ -746,7 +742,6 @@ class SerializerMethodFieldTests(TestCase): self.serializer_class = BoopSerializer def test_serializer_method_field(self): - class MyModel(object): boop = ['a', 'b', 'c'] @@ -766,7 +761,6 @@ class SerializerMethodFieldTests(TestCase): # Test for issue #324 class BlankFieldTests(TestCase): def setUp(self): - class BlankFieldModelSerializer(serializers.ModelSerializer): class Meta: model = BlankFieldModel @@ -825,6 +819,7 @@ class SerializerPickleTests(TestCase): """ Test pickleability of the output of Serializers """ + def test_pickle_simple_model_serializer_data(self): """ Test simple serializer @@ -837,10 +832,12 @@ class SerializerPickleTests(TestCase): have unpickleable meta data--in order to make sure metadata doesn't get pulled into the pickle. See DictWithMetadata.__getstate__ """ + class InnerPersonSerializer(serializers.ModelSerializer): class Meta: model = Person fields = ('name', 'age') + pickle.dumps(InnerPersonSerializer(Person(name="Noah", age=950)).data) @@ -882,13 +879,13 @@ class DepthTest(TestCase): class NestedSerializerContextTests(TestCase): - def test_nested_serializer_context(self): """ Regression for #497 https://github.com/tomchristie/django-rest-framework/issues/497 """ + class PhotoSerializer(serializers.ModelSerializer): class Meta: model = Photo diff --git a/rest_framework/tests/test_settings.py b/rest_framework/tests/test_settings.py new file mode 100644 index 000000000..8e17ce581 --- /dev/null +++ b/rest_framework/tests/test_settings.py @@ -0,0 +1,25 @@ +"""Tests for the settings module""" +from django.test import TestCase + +from rest_framework.settings import APISettings, DEFAULTS, IMPORT_STRINGS + + +class TestSettings(TestCase): + """Tests relating to the api settings""" + + def test_non_import_errors(self): + """Make sure other errors aren't suppressed.""" + settings = APISettings( + {'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.tests.extras.bad_import.ModelSerializer'}, DEFAULTS, + IMPORT_STRINGS) + with self.assertRaises(ValueError): + settings.DEFAULT_MODEL_SERIALIZER_CLASS + + def test_import_error_message_maintained(self): + """Make sure real import errors are captured and raised sensibly.""" + settings = APISettings( + {'DEFAULT_MODEL_SERIALIZER_CLASS': 'rest_framework.tests.extras.not_here.ModelSerializer'}, DEFAULTS, + IMPORT_STRINGS) + with self.assertRaises(ImportError) as cm: + settings.DEFAULT_MODEL_SERIALIZER_CLASS + self.assertTrue('ImportError' in str(cm.exception)) diff --git a/rest_framework/tests/status.py b/rest_framework/tests/test_status.py similarity index 99% rename from rest_framework/tests/status.py rename to rest_framework/tests/test_status.py index e8d44447d..0b5d378e0 100644 --- a/rest_framework/tests/status.py +++ b/rest_framework/tests/test_status.py @@ -162,7 +162,7 @@ class TestStatus(TestCase): """Ensure that HTTP_500_INTERNAL_SERVER_ERROR equals 500.""" self.assertEquals(status.HTTP_500_INTERNAL_SERVER_ERROR, 500) - def HTTP_501_NOT_IMPLEMENTED(self): + def test_status_HTTP_501_NOT_IMPLEMENTED(self): """Ensure that HTTP_501_NOT_IMPLEMENTED equals 501.""" self.assertEquals(status.HTTP_501_NOT_IMPLEMENTED, 501) diff --git a/rest_framework/tests/testcases.py b/rest_framework/tests/test_testcases.py similarity index 96% rename from rest_framework/tests/testcases.py rename to rest_framework/tests/test_testcases.py index 97f492ff4..0ecf1796f 100644 --- a/rest_framework/tests/testcases.py +++ b/rest_framework/tests/test_testcases.py @@ -16,13 +16,14 @@ class TestSettingsManager(object): modified. """ + def __init__(self): self._original_settings = {} def set(self, **kwargs): for k, v in kwargs.iteritems(): self._original_settings.setdefault(k, getattr(settings, k, - NO_SETTING)) + NO_SETTING)) setattr(settings, k, v) if 'INSTALLED_APPS' in kwargs: self.syncdb() @@ -51,6 +52,7 @@ class SettingsTestCase(TestCase): self.settings_manager.revert(). """ + def __init__(self, *args, **kwargs): super(SettingsTestCase, self).__init__(*args, **kwargs) self.settings_manager = TestSettingsManager() diff --git a/rest_framework/tests/throttling.py b/rest_framework/tests/test_throttling.py similarity index 90% rename from rest_framework/tests/throttling.py rename to rest_framework/tests/test_throttling.py index 4b98b9414..0ca2e5b06 100644 --- a/rest_framework/tests/throttling.py +++ b/rest_framework/tests/test_throttling.py @@ -37,7 +37,7 @@ class MockView_MinuteThrottling(APIView): class ThrottlingTests(TestCase): - urls = 'rest_framework.tests.throttling' + urls = 'rest_framework.tests.test_throttling' def setUp(self): """ @@ -113,22 +113,22 @@ class ThrottlingTests(TestCase): Ensure for second based throttles. """ self.ensure_response_header_contains_proper_throttle_field(MockView, - ((0, None), - (0, None), - (0, None), - (0, '1') - )) + ((0, None), + (0, None), + (0, None), + (0, '1') + )) def test_minutes_fields(self): """ Ensure for minute based throttles. """ self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling, - ((0, None), - (0, None), - (0, None), - (0, '60') - )) + ((0, None), + (0, None), + (0, None), + (0, '60') + )) def test_next_rate_remains_constant_if_followed(self): """ @@ -136,9 +136,9 @@ class ThrottlingTests(TestCase): the throttling rate should stay constant. """ self.ensure_response_header_contains_proper_throttle_field(MockView_MinuteThrottling, - ((0, None), - (20, None), - (40, None), - (60, None), - (80, None) - )) + ((0, None), + (20, None), + (40, None), + (60, None), + (80, None) + )) diff --git a/rest_framework/tests/urlpatterns.py b/rest_framework/tests/test_urlpatterns.py similarity index 99% rename from rest_framework/tests/urlpatterns.py rename to rest_framework/tests/test_urlpatterns.py index 43e8ef692..49f6def09 100644 --- a/rest_framework/tests/urlpatterns.py +++ b/rest_framework/tests/test_urlpatterns.py @@ -21,6 +21,7 @@ class FormatSuffixTests(TestCase): """ Tests `format_suffix_patterns` against different URLPatterns to ensure the URLs still resolve properly, including any captured parameters. """ + def _resolve_urlpatterns(self, urlpatterns, test_paths): factory = RequestFactory() try: diff --git a/rest_framework/tests/validators.py b/rest_framework/tests/test_validators.py similarity index 100% rename from rest_framework/tests/validators.py rename to rest_framework/tests/test_validators.py diff --git a/rest_framework/tests/views.py b/rest_framework/tests/test_views.py similarity index 100% rename from rest_framework/tests/views.py rename to rest_framework/tests/test_views.py diff --git a/rest_framework/tests/tests.py b/rest_framework/tests/tests.py deleted file mode 100644 index adeaf6da3..000000000 --- a/rest_framework/tests/tests.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -Force import of all modules in this package in order to get the standard test -runner to pick up the tests. Yowzers. -""" -import os - -modules = [filename.rsplit('.', 1)[0] - for filename in os.listdir(os.path.dirname(__file__)) - if filename.endswith('.py') and not filename.startswith('_')] -__test__ = dict() - -for module in modules: - exec("from rest_framework.tests.%s import *" % module) diff --git a/rest_framework/runtests/urls.py b/rest_framework/tests/urls.py similarity index 100% rename from rest_framework/runtests/urls.py rename to rest_framework/tests/urls.py