Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit 9012833af857e081b515ce760685b157638efcef 1 parent c0d8932
@carljm carljm authored
Showing with 959 additions and 1,019 deletions.
  1. +1 −1  .gitignore
  2. +1 −1  django/conf/global_settings.py
  3. +0 −1  django/contrib/admindocs/tests/__init__.py
  4. +0 −15 django/contrib/auth/tests/__init__.py
  5. +1 −1  django/contrib/auth/tests/test_handlers.py
  6. +1 −1  django/contrib/auth/tests/test_management.py
  7. +0 −6 django/contrib/flatpages/tests/__init__.py
  8. +0 −2  django/contrib/formtools/tests/__init__.py
  9. +1 −1  django/contrib/formtools/tests/urls.py
  10. +4 −3 django/contrib/gis/gdal/__init__.py
  11. +0 −28 django/contrib/gis/gdal/tests/__init__.py
  12. +9 −10 django/contrib/gis/gdal/tests/test_driver.py
  13. +33 −35 django/contrib/gis/gdal/tests/test_ds.py
  14. +8 −10 django/contrib/gis/gdal/tests/test_envelope.py
  15. +9 −10 django/contrib/gis/gdal/tests/test_geom.py
  16. +7 −9 django/contrib/gis/gdal/tests/test_srs.py
  17. +15 −11 django/contrib/gis/geoip/tests.py
  18. +15 −9 django/contrib/gis/geos/__init__.py
  19. +0 −28 django/contrib/gis/geos/tests/__init__.py
  20. +23 −21 django/contrib/gis/geos/tests/test_geos.py
  21. +13 −14 django/contrib/gis/geos/tests/test_geos_mutation.py
  22. +7 −9 django/contrib/gis/geos/tests/test_io.py
  23. +0 −12 django/contrib/gis/geos/tests/test_mutable_list.py
  24. +2 −95 django/contrib/gis/tests/__init__.py
  25. +20 −11 django/contrib/gis/tests/distapp/tests.py
  26. +14 −5 django/contrib/gis/tests/geo3d/tests.py
  27. +9 −3 django/contrib/gis/tests/geoadmin/tests.py
  28. +6 −1 django/contrib/gis/tests/geoapp/test_feeds.py
  29. +6 −1 django/contrib/gis/tests/geoapp/test_regress.py
  30. +6 −1 django/contrib/gis/tests/geoapp/test_sitemaps.py
  31. +18 −11 django/contrib/gis/tests/geoapp/tests.py
  32. +8 −3 django/contrib/gis/tests/geogapp/tests.py
  33. +9 −3 django/contrib/gis/tests/inspectapp/tests.py
  34. +13 −7 django/contrib/gis/tests/layermap/tests.py
  35. +10 −5 django/contrib/gis/tests/relatedapp/tests.py
  36. +0 −1  django/contrib/gis/tests/test_spatialrefsys.py
  37. +9 −0 django/contrib/gis/tests/utils.py
  38. +0 −5 django/contrib/messages/tests/__init__.py
  39. +0 −4 django/contrib/sitemaps/tests/__init__.py
  40. +7 −0 django/test/_doctest.py
  41. +289 −0 django/test/runner.py
  42. +15 −200 django/test/simple.py
  43. +10 −0 django/test/testcases.py
  44. +1 −1  django/utils/unittest/loader.py
  45. +0 −1  docs/index.txt
  46. +10 −1 docs/internals/deprecation.txt
  47. +3 −2 docs/intro/tutorial05.txt
  48. +9 −48 docs/ref/contrib/gis/testing.txt
  49. +6 −1 docs/ref/settings.txt
  50. +1 −1  docs/releases/1.2.4.txt
  51. +1 −1  docs/releases/1.3.txt
  52. +57 −0 docs/releases/1.6.txt
  53. +44 −33 docs/topics/testing/advanced.txt
  54. +0 −81 docs/topics/testing/doctests.txt
  55. +3 −74 docs/topics/testing/index.txt
  56. +42 −52 docs/topics/testing/overview.txt
  57. +3 −3 tests/admin_scripts/tests.py
  58. +0 −11 tests/generic_views/tests.py
  59. +0 −6 tests/i18n/tests.py
  60. +0 −5 tests/model_fields/tests.py
  61. +56 −41 tests/runtests.py
  62. +0 −9 tests/template_tests/tests.py
  63. 0  tests/{test_runner/invalid_app/models → test_discovery_sample}/__init__.py
  64. +7 −0 tests/test_discovery_sample/pattern_tests.py
  65. 0  tests/{test_runner/deprecation_app → test_discovery_sample/tests}/__init__.py
  66. +7 −0 tests/test_discovery_sample/tests/tests.py
  67. +22 −0 tests/test_discovery_sample/tests_sample.py
  68. 0  tests/test_discovery_sample2/__init__.py
  69. +7 −0 tests/test_discovery_sample2/tests.py
  70. +68 −0 tests/test_runner/test_discover_runner.py
  71. +13 −12 tests/test_runner/tests.py
  72. 0  tests/test_runner_deprecation_app/__init__.py
  73. 0  tests/{test_runner/deprecation_app → test_runner_deprecation_app}/models.py
  74. +0 −2  tests/{test_runner/deprecation_app → test_runner_deprecation_app}/tests.py
  75. 0  tests/{test_runner/invalid_app → test_runner_invalid_app}/__init__.py
  76. 0  tests/test_runner_invalid_app/models/__init__.py
  77. 0  tests/{test_runner/invalid_app → test_runner_invalid_app}/tests/__init__.py
  78. +0 −34 tests/utils_tests/tests.py
  79. +0 −6 tests/validation/tests.py
View
2  .gitignore
@@ -5,4 +5,4 @@ MANIFEST
dist/
docs/_build/
tests/coverage_html/
-tests/.coverage
+tests/.coverage
View
2  django/conf/global_settings.py
@@ -576,7 +576,7 @@
###########
# The name of the class to use to run the test suite
-TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner'
+TEST_RUNNER = 'django.test.runner.DiscoverRunner'
############
# FIXTURES #
View
1  django/contrib/admindocs/tests/__init__.py
@@ -1 +0,0 @@
-from .test_fields import TestFieldType
View
15 django/contrib/auth/tests/__init__.py
@@ -1,16 +1 @@
-from django.contrib.auth.tests.test_custom_user import *
-from django.contrib.auth.tests.test_auth_backends import *
-from django.contrib.auth.tests.test_basic import *
-from django.contrib.auth.tests.test_context_processors import *
-from django.contrib.auth.tests.test_decorators import *
-from django.contrib.auth.tests.test_forms import *
-from django.contrib.auth.tests.test_remote_user import *
-from django.contrib.auth.tests.test_management import *
-from django.contrib.auth.tests.test_models import *
-from django.contrib.auth.tests.test_handlers import *
-from django.contrib.auth.tests.test_hashers import *
-from django.contrib.auth.tests.test_signals import *
-from django.contrib.auth.tests.test_tokens import *
-from django.contrib.auth.tests.test_views import *
-
# The password for the fixture data users is 'password'
View
2  django/contrib/auth/tests/test_handlers.py
@@ -2,7 +2,7 @@
from django.contrib.auth.handlers.modwsgi import check_password, groups_for_user
from django.contrib.auth.models import User, Group
-from django.contrib.auth.tests import CustomUser
+from django.contrib.auth.tests.test_custom_user import CustomUser
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.test import TransactionTestCase
from django.test.utils import override_settings
View
2  django/contrib/auth/tests/test_management.py
@@ -5,7 +5,7 @@
from django.contrib.auth.management import create_permissions
from django.contrib.auth.management.commands import changepassword
from django.contrib.auth.models import User
-from django.contrib.auth.tests import CustomUser
+from django.contrib.auth.tests.test_custom_user import CustomUser
from django.contrib.auth.tests.utils import skipIfCustomUser
from django.core.management import call_command
from django.core.management.base import CommandError
View
6 django/contrib/flatpages/tests/__init__.py
@@ -1,6 +0,0 @@
-from django.contrib.flatpages.tests.test_csrf import *
-from django.contrib.flatpages.tests.test_forms import *
-from django.contrib.flatpages.tests.test_models import *
-from django.contrib.flatpages.tests.test_middleware import *
-from django.contrib.flatpages.tests.test_templatetags import *
-from django.contrib.flatpages.tests.test_views import *
View
2  django/contrib/formtools/tests/__init__.py
@@ -1,2 +0,0 @@
-from django.contrib.formtools.tests.tests import *
-from django.contrib.formtools.tests.wizard import *
View
2  django/contrib/formtools/tests/urls.py
@@ -5,7 +5,7 @@
from __future__ import absolute_import
from django.conf.urls import patterns, url
-from django.contrib.formtools.tests import TestFormPreview
+from django.contrib.formtools.tests.tests import TestFormPreview
from django.contrib.formtools.tests.forms import TestForm
View
7 django/contrib/gis/gdal/__init__.py
@@ -31,6 +31,9 @@
to a non-existant file location (e.g., `GDAL_LIBRARY_PATH='/null/path'`;
setting to None/False/'' will not work as a string must be given).
"""
+from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError, SRSException
+from django.contrib.gis.gdal.geomtype import OGRGeomType
+
# Attempting to import objects that depend on the GDAL library. The
# HAS_GDAL flag will be set to True if the library is present on
# the system.
@@ -41,7 +44,7 @@
from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
from django.contrib.gis.gdal.geometries import OGRGeometry
HAS_GDAL = True
-except Exception:
+except OGRException:
HAS_GDAL = False
try:
@@ -50,5 +53,3 @@
# No ctypes, but don't raise an exception.
pass
-from django.contrib.gis.gdal.error import check_err, OGRException, OGRIndexError, SRSException
-from django.contrib.gis.gdal.geomtype import OGRGeomType
View
28 django/contrib/gis/gdal/tests/__init__.py
@@ -1,28 +0,0 @@
-"""
-Module for executing all of the GDAL tests. None
-of these tests require the use of the database.
-"""
-from __future__ import absolute_import
-
-from django.utils.unittest import TestSuite, TextTestRunner
-
-# Importing the GDAL test modules.
-from . import test_driver, test_ds, test_envelope, test_geom, test_srs
-
-test_suites = [test_driver.suite(),
- test_ds.suite(),
- test_envelope.suite(),
- test_geom.suite(),
- test_srs.suite(),
- ]
-
-def suite():
- "Builds a test suite for the GDAL tests."
- s = TestSuite()
- for test_suite in test_suites:
- s.addTest(test_suite)
- return s
-
-def run(verbosity=1):
- "Runs the GDAL tests."
- TextTestRunner(verbosity=verbosity).run(suite())
View
19 django/contrib/gis/gdal/tests/test_driver.py
@@ -1,5 +1,10 @@
-import unittest
-from django.contrib.gis.gdal import Driver, OGRException
+from django.contrib.gis.gdal import HAS_GDAL
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import Driver, OGRException
+
valid_drivers = ('ESRI Shapefile', 'MapInfo File', 'TIGER', 'S57', 'DGN',
'Memory', 'CSV', 'GML', 'KML')
@@ -12,6 +17,8 @@
'sHp' : 'ESRI Shapefile',
}
+
+@skipUnless(HAS_GDAL, "GDAL is required")
class DriverTest(unittest.TestCase):
def test01_valid_driver(self):
@@ -30,11 +37,3 @@ def test03_aliases(self):
for alias, full_name in aliases.items():
dr = Driver(alias)
self.assertEqual(full_name, str(dr))
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(DriverTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
68 django/contrib/gis/gdal/tests/test_ds.py
@@ -1,32 +1,38 @@
import os
-import unittest
-from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, OGRException, OGRIndexError, GDAL_VERSION
-from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
-from django.contrib.gis.geometry.test_data import get_ds_file, TestDS, TEST_DATA
-
-
-# List of acceptable data sources.
-ds_list = (TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
- fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
- extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
- srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
- field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : list(range(1, 6)), 'str' : [str(i) for i in range(1, 6)]},
- fids=range(5)),
- TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype='Point25D', driver='VRT',
- fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
- extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
- field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
- fids=range(1,4)),
- TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
- driver='ESRI Shapefile',
- fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
- extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
- srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
- )
-
-bad_ds = (TestDS('foo'),
- )
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.geometry.test_data import get_ds_file, TestDS, TEST_DATA
+from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, OGRException, OGRIndexError, GDAL_VERSION
+ from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
+
+ # List of acceptable data sources.
+ ds_list = (
+ TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
+ fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
+ extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
+ srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
+ field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : list(range(1, 6)), 'str' : [str(i) for i in range(1, 6)]},
+ fids=range(5)),
+ TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype='Point25D', driver='VRT',
+ fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
+ extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
+ field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
+ fids=range(1,4)),
+ TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
+ driver='ESRI Shapefile',
+ fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
+ extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
+ srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
+ )
+
+bad_ds = (TestDS('foo'),)
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
class DataSourceTest(unittest.TestCase):
def test01_valid_shp(self):
@@ -236,11 +242,3 @@ def test07_integer_overflow(self):
feat = ds[0][0]
# Reference value obtained using `ogrinfo`.
self.assertEqual(676586997978, feat.get('ALAND10'))
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(DataSourceTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
18 django/contrib/gis/gdal/tests/test_envelope.py
@@ -1,5 +1,9 @@
-from django.contrib.gis.gdal import Envelope, OGRException
+from django.contrib.gis.gdal import HAS_GDAL
from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import Envelope, OGRException
class TestPoint(object):
@@ -7,11 +11,13 @@ def __init__(self, x, y):
self.x = x
self.y = y
+
+@skipUnless(HAS_GDAL, "GDAL is required")
class EnvelopeTest(unittest.TestCase):
def setUp(self):
self.e = Envelope(0, 0, 5, 5)
-
+
def test01_init(self):
"Testing Envelope initilization."
e1 = Envelope((0, 0, 5, 5))
@@ -85,11 +91,3 @@ def test08_expand_to_include_point(self):
self.assertEqual((-1, 0, 5, 5), self.e)
self.e.expand_to_include(TestPoint(10, 10))
self.assertEqual((-1, 0, 10, 10), self.e)
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(EnvelopeTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
19 django/contrib/gis/gdal/tests/test_geom.py
@@ -5,12 +5,19 @@
except ImportError:
import pickle
-from django.contrib.gis.gdal import (OGRGeometry, OGRGeomType, OGRException,
- OGRIndexError, SpatialReference, CoordTransform, GDAL_VERSION)
+from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geometry.test_data import TestDataMixin
from django.utils.six.moves import xrange
from django.utils import unittest
+from django.utils.unittest import skipUnless
+if HAS_GDAL:
+ from django.contrib.gis.gdal import (OGRGeometry, OGRGeomType,
+ OGRException, OGRIndexError, SpatialReference, CoordTransform,
+ GDAL_VERSION)
+
+
+@skipUnless(HAS_GDAL, "GDAL is required")
class OGRGeomTest(unittest.TestCase, TestDataMixin):
"This tests the OGR Geometry."
@@ -476,11 +483,3 @@ def test19_equivalence_regression(self):
"Testing equivalence methods with non-OGRGeometry instances."
self.assertNotEqual(None, OGRGeometry('POINT(0 0)'))
self.assertEqual(False, OGRGeometry('LINESTRING(0 0, 1 1)') == 3)
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(OGRGeomTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
16 django/contrib/gis/gdal/tests/test_srs.py
@@ -1,5 +1,9 @@
-from django.contrib.gis.gdal import SpatialReference, CoordTransform, OGRException, SRSException
+from django.contrib.gis.gdal import HAS_GDAL
from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+if HAS_GDAL:
+ from django.contrib.gis.gdal import SpatialReference, CoordTransform, OGRException, SRSException
class TestSRS:
@@ -46,6 +50,8 @@ def __init__(self, wkt, **kwargs):
bad_srlist = ('Foobar', 'OOJCS["NAD83 / Texas South Central",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["standard_parallel_1",30.28333333333333],PARAMETER["standard_parallel_2",28.38333333333333],PARAMETER["latitude_of_origin",27.83333333333333],PARAMETER["central_meridian",-99],PARAMETER["false_easting",600000],PARAMETER["false_northing",4000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32140"]]',)
+
+@skipUnless(HAS_GDAL, "GDAL is required")
class SpatialRefTest(unittest.TestCase):
def test01_wkt(self):
@@ -155,11 +161,3 @@ def test13_attr_value(self):
self.assertEqual('EPSG', s1['AUTHORITY'])
self.assertEqual(4326, int(s1['AUTHORITY', 1]))
self.assertEqual(None, s1['FOOBAR'])
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(SpatialRefTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
26 django/contrib/gis/geoip/tests.py
@@ -3,16 +3,28 @@
import os
from django.conf import settings
-from django.contrib.gis.geos import GEOSGeometry
-from django.contrib.gis.geoip import GeoIP, GeoIPException
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.geoip import HAS_GEOIP
from django.utils import unittest
+from django.utils.unittest import skipUnless
from django.utils import six
+if HAS_GEOIP:
+ from . import GeoIP, GeoIPException
+
+if HAS_GEOS:
+ from ..geos import GEOSGeometry
+
+
# Note: Requires use of both the GeoIP country and city datasets.
# The GEOIP_DATA path should be the only setting set (the directory
# should contain links or the actual database files 'GeoIP.dat' and
# 'GeoLiteCity.dat'.
+
+
+@skipUnless(HAS_GEOIP and getattr(settings, "GEOIP_PATH", None),
+ "GeoIP is required along with the GEOIP_DATA setting.")
class GeoIPTest(unittest.TestCase):
def test01_init(self):
@@ -70,6 +82,7 @@ def test03_country(self):
self.assertEqual({'country_code' : 'US', 'country_name' : 'United States'},
g.country(query))
+ @skipUnless(HAS_GEOS, "Geos is required")
def test04_city(self):
"Testing GeoIP city querying methods."
g = GeoIP(country='<foo>')
@@ -105,12 +118,3 @@ def test05_unicode_response(self):
g = GeoIP()
d = g.city("www.osnabrueck.de")
self.assertEqual('Osnabrück', d['city'])
-
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(GeoIPTest))
- return s
-
-def run(verbosity=1):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
24 django/contrib/gis/geos/__init__.py
@@ -3,12 +3,18 @@
for more details:
http://geodjango.org/docs/geos.html
"""
-from django.contrib.gis.geos.geometry import GEOSGeometry, wkt_regex, hex_regex
-from django.contrib.gis.geos.point import Point
-from django.contrib.gis.geos.linestring import LineString, LinearRing
-from django.contrib.gis.geos.polygon import Polygon
-from django.contrib.gis.geos.collections import GeometryCollection, MultiPoint, MultiLineString, MultiPolygon
-from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
-from django.contrib.gis.geos.io import WKTReader, WKTWriter, WKBReader, WKBWriter
-from django.contrib.gis.geos.factory import fromfile, fromstr
-from django.contrib.gis.geos.libgeos import geos_version, geos_version_info, GEOS_PREPARE
+try:
+ from .libgeos import geos_version, geos_version_info, GEOS_PREPARE
+ HAS_GEOS = True
+except ImportError:
+ HAS_GEOS = False
+
+if HAS_GEOS:
+ from .geometry import GEOSGeometry, wkt_regex, hex_regex
+ from .point import Point
+ from .linestring import LineString, LinearRing
+ from .polygon import Polygon
+ from .collections import GeometryCollection, MultiPoint, MultiLineString, MultiPolygon
+ from .error import GEOSException, GEOSIndexError
+ from .io import WKTReader, WKTWriter, WKBReader, WKBWriter
+ from .factory import fromfile, fromstr
View
28 django/contrib/gis/geos/tests/__init__.py
@@ -1,28 +0,0 @@
-"""
-GEOS Testing module.
-"""
-from __future__ import absolute_import
-
-from django.utils.unittest import TestSuite, TextTestRunner
-from . import test_geos, test_io, test_geos_mutation, test_mutable_list
-
-test_suites = [
- test_geos.suite(),
- test_io.suite(),
- test_geos_mutation.suite(),
- test_mutable_list.suite(),
- ]
-
-def suite():
- "Builds a test suite for the GEOS tests."
- s = TestSuite()
- for suite in test_suites:
- s.addTest(suite)
- return s
-
-def run(verbosity=1):
- "Runs the GEOS tests."
- TextTestRunner(verbosity=verbosity).run(suite())
-
-if __name__ == '__main__':
- run(2)
View
44 django/contrib/gis/geos/tests/test_geos.py
@@ -6,20 +6,28 @@
from binascii import a2b_hex, b2a_hex
from io import BytesIO
+from django.contrib.gis.gdal import HAS_GDAL
+
from django.contrib.gis import memoryview
-from django.contrib.gis.geos import (GEOSException, GEOSIndexError, GEOSGeometry,
- GeometryCollection, Point, MultiPoint, Polygon, MultiPolygon, LinearRing,
- LineString, MultiLineString, fromfile, fromstr, geos_version_info)
-from django.contrib.gis.geos.base import gdal, numpy, GEOSBase
-from django.contrib.gis.geos.libgeos import GEOS_PREPARE
from django.contrib.gis.geometry.test_data import TestDataMixin
from django.utils.encoding import force_bytes
from django.utils import six
from django.utils.six.moves import xrange
from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+from .. import HAS_GEOS
+
+if HAS_GEOS:
+ from .. import (GEOSException, GEOSIndexError, GEOSGeometry,
+ GeometryCollection, Point, MultiPoint, Polygon, MultiPolygon, LinearRing,
+ LineString, MultiLineString, fromfile, fromstr, geos_version_info,
+ GEOS_PREPARE)
+ from ..base import gdal, numpy, GEOSBase
+@skipUnless(HAS_GEOS, "Geos is required.")
class GEOSTest(unittest.TestCase, TestDataMixin):
@property
@@ -198,7 +206,7 @@ def test_ewkt(self):
self.assertEqual(srid, poly.shell.srid)
self.assertEqual(srid, fromstr(poly.ewkt).srid) # Checking export
- @unittest.skipUnless(gdal.HAS_GDAL, "gdal is required")
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test_json(self):
"Testing GeoJSON input/output (via GDAL)."
for g in self.geometries.json_geoms:
@@ -662,6 +670,7 @@ def test_srid(self):
p3 = fromstr(p1.hex, srid=-1) # -1 is intended.
self.assertEqual(-1, p3.srid)
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test_custom_srid(self):
""" Test with a srid unknown from GDAL """
pnt = Point(111200, 220900, srid=999999)
@@ -851,7 +860,7 @@ def test_collections_of_collections(self):
# And, they should be equal.
self.assertEqual(gc1, gc2)
- @unittest.skipUnless(gdal.HAS_GDAL, "gdal is required")
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test_gdal(self):
"Testing `ogr` and `srs` properties."
g1 = fromstr('POINT(5 23)')
@@ -878,7 +887,7 @@ def test_copy(self):
self.assertNotEqual(poly._ptr, cpy1._ptr)
self.assertNotEqual(poly._ptr, cpy2._ptr)
- @unittest.skipUnless(gdal.HAS_GDAL, "gdal is required to transform geometries")
+ @skipUnless(HAS_GDAL, "GDAL is required to transform geometries")
def test_transform(self):
"Testing `transform` method."
orig = GEOSGeometry('POINT (-104.609 38.255)', 4326)
@@ -903,7 +912,7 @@ def test_transform(self):
self.assertAlmostEqual(trans.x, p.x, prec)
self.assertAlmostEqual(trans.y, p.y, prec)
- @unittest.skipUnless(gdal.HAS_GDAL, "gdal is required to transform geometries")
+ @skipUnless(HAS_GDAL, "GDAL is required to transform geometries")
def test_transform_3d(self):
p3d = GEOSGeometry('POINT (5 23 100)', 4326)
p3d.transform(2774)
@@ -912,6 +921,7 @@ def test_transform_3d(self):
else:
self.assertIsNone(p3d.z)
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test_transform_noop(self):
""" Testing `transform` method (SRID match) """
# transform() should no-op if source & dest SRIDs match,
@@ -962,6 +972,7 @@ def test_transform_nosrid(self):
g = GEOSGeometry('POINT (-104.609 38.255)', srid=-1)
self.assertRaises(GEOSException, g.transform, 2774, clone=True)
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test_transform_nogdal(self):
""" Testing `transform` method (GDAL not available) """
old_has_gdal = gdal.HAS_GDAL
@@ -1016,7 +1027,7 @@ def get_geoms(lst, srid=None):
self.assertEqual(geom, tmpg)
if not no_srid: self.assertEqual(geom.srid, tmpg.srid)
- @unittest.skipUnless(GEOS_PREPARE, "geos >= 3.1.0 is required")
+ @skipUnless(HAS_GEOS and GEOS_PREPARE, "geos >= 3.1.0 is required")
def test_prepared(self):
"Testing PreparedGeometry support."
# Creating a simple multipolygon and getting a prepared version.
@@ -1043,7 +1054,7 @@ def test_line_merge(self):
for geom, merged in zip(ref_geoms, ref_merged):
self.assertEqual(merged, geom.merged)
- @unittest.skipUnless(GEOS_PREPARE, "geos >= 3.1.0 is required")
+ @skipUnless(HAS_GEOS and GEOS_PREPARE, "geos >= 3.1.0 is required")
def test_valid_reason(self):
"Testing IsValidReason support"
@@ -1058,7 +1069,7 @@ def test_valid_reason(self):
self.assertIsInstance(g.valid_reason, six.string_types)
self.assertTrue(g.valid_reason.startswith("Too few points in geometry component"))
- @unittest.skipUnless(geos_version_info()['version'] >= '3.2.0', "geos >= 3.2.0 is required")
+ @skipUnless(HAS_GEOS and geos_version_info()['version'] >= '3.2.0', "geos >= 3.2.0 is required")
def test_linearref(self):
"Testing linear referencing"
@@ -1091,12 +1102,3 @@ def test_geos_version(self):
self.assertTrue(m, msg="Unable to parse the version string '%s'" % v_init)
self.assertEqual(m.group('version'), v_geos)
self.assertEqual(m.group('capi_version'), v_capi)
-
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(GEOSTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
27 django/contrib/gis/geos/tests/test_geos_mutation.py
@@ -2,15 +2,23 @@
# Modified from original contribution by Aryeh Leib Taurog, which was
# released under the New BSD license.
-from django.contrib.gis.geos import *
-from django.contrib.gis.geos.error import GEOSIndexError
from django.utils import unittest
+from django.utils.unittest import skipUnless
+
+from .. import HAS_GEOS
+
+if HAS_GEOS:
+ from .. import *
+ from ..error import GEOSIndexError
+
def getItem(o,i): return o[i]
def delItem(o,i): del o[i]
def setItem(o,i,v): o[i] = v
-def api_get_distance(x): return x.distance(Point(-200,-200))
+if HAS_GEOS:
+ def api_get_distance(x): return x.distance(Point(-200,-200))
+
def api_get_buffer(x): return x.buffer(10)
def api_get_geom_typeid(x): return x.geom_typeid
def api_get_num_coords(x): return x.num_coords
@@ -29,6 +37,8 @@ def api_get_length(x): return x.length
if hasattr(val, '__call__')
and name.startswith('api_get_') ]
+
+@skipUnless(HAS_GEOS, "Geos is required.")
class GEOSMutationTest(unittest.TestCase):
"""
Tests Pythonic Mutability of Python GEOS geometry wrappers
@@ -122,14 +132,3 @@ def test06_Collection(self):
lsa = MultiPoint(*map(Point,((5,5),(3,-2),(8,1))))
for f in geos_function_tests:
self.assertEqual(f(lsa), f(mp), 'MultiPoint ' + f.__name__)
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(GEOSMutationTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
-
-if __name__ == '__main__':
- run()
View
16 django/contrib/gis/geos/tests/test_io.py
@@ -4,10 +4,16 @@
import unittest
from django.contrib.gis import memoryview
-from django.contrib.gis.geos import GEOSGeometry, WKTReader, WKTWriter, WKBReader, WKBWriter, geos_version_info
from django.utils import six
+from django.utils.unittest import skipUnless
+from ..import HAS_GEOS
+if HAS_GEOS:
+ from .. import GEOSGeometry, WKTReader, WKTWriter, WKBReader, WKBWriter, geos_version_info
+
+
+@skipUnless(HAS_GEOS, "Geos is required.")
class GEOSIOTest(unittest.TestCase):
def test01_wktreader(self):
@@ -109,11 +115,3 @@ def test04_wkbwriter(self):
wkb_w.srid = True
self.assertEqual(hex3d_srid, wkb_w.write_hex(g))
self.assertEqual(wkb3d_srid, wkb_w.write(g))
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(GEOSIOTest))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
View
12 django/contrib/gis/geos/tests/test_mutable_list.py
@@ -395,15 +395,3 @@ def test_12_arithmetic(self):
class ListMixinTestSingle(ListMixinTest):
listType = UserListB
-
-def suite():
- s = unittest.TestSuite()
- s.addTest(unittest.makeSuite(ListMixinTest))
- s.addTest(unittest.makeSuite(ListMixinTestSingle))
- return s
-
-def run(verbosity=2):
- unittest.TextTestRunner(verbosity=verbosity).run(suite())
-
-if __name__ == '__main__':
- run()
View
97 django/contrib/gis/tests/__init__.py
@@ -1,13 +1,4 @@
-from django.conf import settings
-from django.test.simple import build_suite, DjangoTestSuiteRunner
-from django.utils import unittest
-
-from .test_geoforms import GeometryFieldTest
-from .test_measure import DistanceTest, AreaTest
-from .test_spatialrefsys import SpatialRefSysTest
-
-
-def geo_apps(namespace=True, runtests=False):
+def geo_apps():
"""
Returns a list of GeoDjango test applications that reside in
`django.contrib.gis.tests` that can be used with the current
@@ -36,88 +27,4 @@ def geo_apps(namespace=True, runtests=False):
# 3D apps use LayerMapping, which uses GDAL and require GEOS 3.1+.
if connection.ops.postgis and GEOS_PREPARE:
apps.append('geo3d')
- if runtests:
- return [('django.contrib.gis.tests', app) for app in apps]
- elif namespace:
- return ['django.contrib.gis.tests.%s' % app
- for app in apps]
- else:
- return apps
-
-
-def geodjango_suite(apps=True):
- """
- Returns a TestSuite consisting only of GeoDjango tests that can be run.
- """
- import sys
- from django.db.models import get_app
-
- suite = unittest.TestSuite()
-
- # Adding the GEOS tests.
- from django.contrib.gis.geos import tests as geos_tests
- suite.addTest(geos_tests.suite())
-
- # Adding GDAL tests, and any test suite that depends on GDAL, to the
- # suite if GDAL is available.
- from django.contrib.gis.gdal import HAS_GDAL
- if HAS_GDAL:
- from django.contrib.gis.gdal import tests as gdal_tests
- suite.addTest(gdal_tests.suite())
- else:
- sys.stderr.write('GDAL not available - no tests requiring GDAL will be run.\n')
-
- # Add GeoIP tests to the suite, if the library and data is available.
- from django.contrib.gis.geoip import HAS_GEOIP
- if HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'):
- from django.contrib.gis.geoip import tests as geoip_tests
- suite.addTest(geoip_tests.suite())
-
- # Finally, adding the suites for each of the GeoDjango test apps.
- if apps:
- for app_name in geo_apps(namespace=False):
- suite.addTest(build_suite(get_app(app_name)))
-
- return suite
-
-
-class GeoDjangoTestSuiteRunner(DjangoTestSuiteRunner):
-
- def setup_test_environment(self, **kwargs):
- super(GeoDjangoTestSuiteRunner, self).setup_test_environment(**kwargs)
-
- # Saving original values of INSTALLED_APPS, ROOT_URLCONF, and SITE_ID.
- self.old_installed = getattr(settings, 'INSTALLED_APPS', None)
- self.old_root_urlconf = getattr(settings, 'ROOT_URLCONF', '')
- self.old_site_id = getattr(settings, 'SITE_ID', None)
-
- # Constructing the new INSTALLED_APPS, and including applications
- # within the GeoDjango test namespace.
- new_installed = [
- 'django.contrib.sites',
- 'django.contrib.sitemaps',
- 'django.contrib.gis',
- ]
-
- # Calling out to `geo_apps` to get GeoDjango applications supported
- # for testing.
- new_installed.extend(geo_apps())
- settings.INSTALLED_APPS = list(self.old_installed) + new_installed
-
- # SITE_ID needs to be set
- settings.SITE_ID = 1
-
- # ROOT_URLCONF needs to be set, else `AttributeErrors` are raised
- # when TestCases are torn down that have `urls` defined.
- settings.ROOT_URLCONF = ''
-
-
- def teardown_test_environment(self, **kwargs):
- super(GeoDjangoTestSuiteRunner, self).teardown_test_environment(**kwargs)
- settings.INSTALLED_APPS = self.old_installed
- settings.ROOT_URLCONF = self.old_root_urlconf
- settings.SITE_ID = self.old_site_id
-
-
- def build_suite(self, test_labels, extra_tests=None, **kwargs):
- return geodjango_suite()
+ return [('django.contrib.gis.tests', app) for app in apps]
View
31 django/contrib/gis/tests/distapp/tests.py
@@ -2,24 +2,33 @@
from django.db import connection
from django.db.models import Q
-from django.contrib.gis.geos import GEOSGeometry, LineString
+from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.measure import D # alias for Distance
-from django.contrib.gis.tests.utils import oracle, postgis, spatialite, no_oracle, no_spatialite
+from django.contrib.gis.tests.utils import (
+ HAS_SPATIAL_DB, oracle, postgis, spatialite, no_oracle, no_spatialite
+)
from django.test import TestCase
+from django.utils.unittest import skipUnless
-from .models import (AustraliaCity, Interstate, SouthTexasInterstate,
- SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode)
+if HAS_GEOS and HAS_SPATIAL_DB:
+ from django.contrib.gis.geos import GEOSGeometry, LineString
+ from .models import (AustraliaCity, Interstate, SouthTexasInterstate,
+ SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode)
+
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB,
+ "Geos and spatial db are required.")
class DistanceTest(TestCase):
- # A point we are testing distances with -- using a WGS84
- # coordinate that'll be implicitly transormed to that to
- # the coordinate system of the field, EPSG:32140 (Texas South Central
- # w/units in meters)
- stx_pnt = GEOSGeometry('POINT (-95.370401017314293 29.704867409475465)', 4326)
- # Another one for Australia
- au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326)
+ if HAS_GEOS and HAS_SPATIAL_DB:
+ # A point we are testing distances with -- using a WGS84
+ # coordinate that'll be implicitly transormed to that to
+ # the coordinate system of the field, EPSG:32140 (Texas South Central
+ # w/units in meters)
+ stx_pnt = GEOSGeometry('POINT (-95.370401017314293 29.704867409475465)', 4326)
+ # Another one for Australia
+ au_pnt = GEOSGeometry('POINT (150.791 -34.4919)', 4326)
def get_names(self, qs):
cities = [c.name for c in qs]
View
19 django/contrib/gis/tests/geo3d/tests.py
@@ -3,14 +3,22 @@
import os
import re
-from django.contrib.gis.db.models import Union, Extent3D
-from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon
-from django.contrib.gis.utils import LayerMapping, LayerMapError
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import TestCase
from django.utils._os import upath
+from django.utils.unittest import skipUnless
-from .models import (City3D, Interstate2D, Interstate3D, InterstateProj2D,
- InterstateProj3D, Point2D, Point3D, MultiPoint3D, Polygon2D, Polygon3D)
+if HAS_GEOS:
+ from django.contrib.gis.db.models import Union, Extent3D
+ from django.contrib.gis.geos import GEOSGeometry, LineString, Point, Polygon
+
+ from .models import (City3D, Interstate2D, Interstate3D, InterstateProj2D,
+ InterstateProj3D, Point2D, Point3D, MultiPoint3D, Polygon2D, Polygon3D)
+
+if HAS_GDAL:
+ from django.contrib.gis.utils import LayerMapping, LayerMapError
data_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), '..', 'data'))
@@ -54,6 +62,7 @@
)
+@skipUnless(HAS_GEOS and HAS_GDAL and HAS_SPATIAL_DB, "Geos, GDAL and spatial db are required.")
class Geo3DTest(TestCase):
"""
Only a subset of the PostGIS routines are 3D-enabled, and this TestCase
View
12 django/contrib/gis/tests/geoadmin/tests.py
@@ -1,12 +1,18 @@
from __future__ import absolute_import
from django.test import TestCase
-from django.contrib.gis import admin
-from django.contrib.gis.geos import GEOSGeometry, Point
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
+from django.utils.unittest import skipUnless
-from .models import City
+if HAS_GEOS and HAS_SPATIAL_DB:
+ from django.contrib.gis import admin
+ from django.contrib.gis.geos import Point
+ from .models import City
+
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoAdminTest(TestCase):
urls = 'django.contrib.gis.tests.geoadmin.urls'
View
7 django/contrib/gis/tests/geoapp/test_feeds.py
@@ -4,11 +4,16 @@
from django.conf import settings
from django.contrib.sites.models import Site
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import TestCase
+from django.utils.unittest import skipUnless
-from .models import City
+if HAS_GEOS:
+ from .models import City
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoFeedTest(TestCase):
urls = 'django.contrib.gis.tests.geoapp.urls'
View
7 django/contrib/gis/tests/geoapp/test_regress.py
@@ -3,14 +3,19 @@
from datetime import datetime
+from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import no_mysql, no_spatialite
from django.contrib.gis.shortcuts import render_to_kmz
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.db.models import Count, Min
from django.test import TestCase
+from django.utils.unittest import skipUnless
-from .models import City, PennsylvaniaCity, State, Truth
+if HAS_GEOS:
+ from .models import City, PennsylvaniaCity, State, Truth
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoRegressionTests(TestCase):
def test_update(self):
View
7 django/contrib/gis/tests/geoapp/test_sitemaps.py
@@ -5,12 +5,17 @@
import zipfile
from django.conf import settings
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.contrib.sites.models import Site
from django.test import TestCase
+from django.utils.unittest import skipUnless
-from .models import City, Country
+if HAS_GEOS:
+ from .models import City, Country
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoSitemapTest(TestCase):
urls = 'django.contrib.gis.tests.geoapp.urls'
View
29 django/contrib/gis/tests/geoapp/tests.py
@@ -3,26 +3,31 @@
import re
from django.db import connection
-from django.db.utils import DatabaseError
from django.contrib.gis import gdal
-from django.contrib.gis.geos import (fromstr, GEOSGeometry,
- Point, LineString, LinearRing, Polygon, GeometryCollection)
+from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.tests.utils import (
- no_mysql, no_oracle, no_spatialite,
+ HAS_SPATIAL_DB, no_mysql, no_oracle, no_spatialite,
mysql, oracle, postgis, spatialite)
from django.test import TestCase
from django.utils import six, unittest
+from django.utils.unittest import skipUnless
-from .models import Country, City, PennsylvaniaCity, State, Track
+if HAS_GEOS:
+ from django.contrib.gis.geos import (fromstr, GEOSGeometry,
+ Point, LineString, LinearRing, Polygon, GeometryCollection)
-from .test_feeds import GeoFeedTest
-from .test_regress import GeoRegressionTests
-from .test_sitemaps import GeoSitemapTest
+ from .models import Country, City, PennsylvaniaCity, State, Track
-
-if not spatialite:
+if HAS_GEOS and not spatialite:
from .models import Feature, MinusOneSRID
+
+def postgis_bug_version():
+ spatial_version = getattr(connection.ops, "spatial_version", (0,0,0))
+ return spatial_version and (2, 0, 0) <= spatial_version <= (2, 0, 1)
+
+
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoModelTest(TestCase):
def test_fixtures(self):
@@ -197,6 +202,7 @@ def test_raw_sql_query(self):
self.assertTrue(isinstance(cities2[0].point, Point))
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoLookupTest(TestCase):
@no_mysql
@@ -297,7 +303,7 @@ def test_left_right_lookups(self):
# The left/right lookup tests are known failures on PostGIS 2.0/2.0.1
# http://trac.osgeo.org/postgis/ticket/2035
- if connection.ops.postgis and (2, 0, 0) <= connection.ops.spatial_version <= (2, 0, 1):
+ if postgis_bug_version():
test_left_right_lookups = unittest.expectedFailure(test_left_right_lookups)
def test_equals_lookups(self):
@@ -382,6 +388,7 @@ def test_relate_lookup(self):
self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeoQuerySetTest(TestCase):
# Please keep the tests in GeoQuerySet method's alphabetic order
View
11 django/contrib/gis/tests/geogapp/tests.py
@@ -5,14 +5,19 @@
import os
-from django.contrib.gis import gdal
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.geos import HAS_GEOS
from django.contrib.gis.measure import D
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
from django.test import TestCase
from django.utils._os import upath
+from django.utils.unittest import skipUnless
-from .models import City, County, Zipcode
+if HAS_GEOS:
+ from .models import City, County, Zipcode
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class GeographyTest(TestCase):
def test01_fixture_load(self):
@@ -54,11 +59,11 @@ def test04_invalid_operators_functions(self):
htown = City.objects.get(name='Houston')
self.assertRaises(ValueError, City.objects.get, point__exact=htown.point)
+ @skipUnless(HAS_GDAL, "GDAL is required.")
def test05_geography_layermapping(self):
"Testing LayerMapping support on models with geography fields."
# There is a similar test in `layermap` that uses the same data set,
# but the County model here is a bit different.
- if not gdal.HAS_GDAL: return
from django.contrib.gis.utils import LayerMapping
# Getting the shapefile and mapping dictionary.
View
12 django/contrib/gis/tests/inspectapp/tests.py
@@ -4,13 +4,19 @@
from django.db import connections
from django.test import TestCase
-from django.contrib.gis.gdal import Driver
+from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geometry.test_data import TEST_DATA
-from django.contrib.gis.utils.ogrinspect import ogrinspect
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB
+from django.utils.unittest import skipUnless
-from .models import AllOGRFields
+if HAS_GDAL:
+ from django.contrib.gis.gdal import Driver
+ from django.contrib.gis.utils.ogrinspect import ogrinspect
+ from .models import AllOGRFields
+
+@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
class OGRInspectTest(TestCase):
maxDiff = 1024
View
20 django/contrib/gis/tests/layermap/tests.py
@@ -5,19 +5,23 @@
from copy import copy
from decimal import Decimal
-from django.contrib.gis.gdal import DataSource
-from django.contrib.gis.tests.utils import mysql
-from django.contrib.gis.utils.layermapping import (LayerMapping, LayerMapError,
- InvalidDecimal, MissingForeignKey)
+from django.contrib.gis.gdal import HAS_GDAL
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB, mysql
from django.db import router
from django.conf import settings
from django.test import TestCase
from django.utils import unittest
+from django.utils.unittest import skipUnless
from django.utils._os import upath
-from .models import (
- City, County, CountyFeat, Interstate, ICity1, ICity2, Invalid, State,
- city_mapping, co_mapping, cofeat_mapping, inter_mapping)
+if HAS_GDAL:
+ from django.contrib.gis.utils.layermapping import (LayerMapping,
+ LayerMapError, InvalidDecimal, MissingForeignKey)
+ from django.contrib.gis.gdal import DataSource
+
+ from .models import (
+ City, County, CountyFeat, Interstate, ICity1, ICity2, Invalid, State,
+ city_mapping, co_mapping, cofeat_mapping, inter_mapping)
shp_path = os.path.realpath(os.path.join(os.path.dirname(upath(__file__)), os.pardir, 'data'))
@@ -32,6 +36,7 @@
STATES = ['Texas', 'Texas', 'Texas', 'Hawaii', 'Colorado']
+@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
class LayerMapTest(TestCase):
def test_init(self):
@@ -310,6 +315,7 @@ def allow_syncdb(self, db, model):
return True
+@skipUnless(HAS_GDAL and HAS_SPATIAL_DB, "GDAL and spatial db are required.")
class LayerMapRouterTest(TestCase):
def setUp(self):
View
15 django/contrib/gis/tests/relatedapp/tests.py
@@ -2,15 +2,20 @@
from datetime import date
-from django.contrib.gis.geos import GEOSGeometry, Point, MultiPoint
-from django.contrib.gis.db.models import Collect, Count, Extent, F, Union
-from django.contrib.gis.geometry.backend import Geometry
-from django.contrib.gis.tests.utils import mysql, oracle, no_mysql, no_oracle, no_spatialite
+from django.contrib.gis.geos import HAS_GEOS
+from django.contrib.gis.tests.utils import HAS_SPATIAL_DB, mysql, oracle, no_mysql, no_oracle, no_spatialite
from django.test import TestCase
+from django.utils.unittest import skipUnless
-from .models import City, Location, DirectoryEntry, Parcel, Book, Author, Article
+if HAS_GEOS:
+ from django.contrib.gis.db.models import Collect, Count, Extent, F, Union
+ from django.contrib.gis.geometry.backend import Geometry
+ from django.contrib.gis.geos import GEOSGeometry, Point, MultiPoint
+ from .models import City, Location, DirectoryEntry, Parcel, Book, Author, Article
+
+@skipUnless(HAS_GEOS and HAS_SPATIAL_DB, "Geos and spatial db are required.")
class RelatedGeoModelTest(TestCase):
def test02_select_related(self):
View
1  django/contrib/gis/tests/test_spatialrefsys.py
@@ -1,4 +1,3 @@
-from django.db import connection
from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.tests.utils import (no_mysql, oracle, postgis,
spatialite, HAS_SPATIALREFSYS, SpatialRefSys)
View
9 django/contrib/gis/tests/utils.py
@@ -35,3 +35,12 @@ def no_spatialite(func): return no_backend(func, 'spatialite')
else:
HAS_SPATIALREFSYS = False
SpatialRefSys = None
+
+
+def has_spatial_db():
+ # 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)
+
+HAS_SPATIAL_DB = has_spatial_db()
View
5 django/contrib/messages/tests/__init__.py
@@ -1,5 +0,0 @@
-from django.contrib.messages.tests.test_cookie import CookieTest
-from django.contrib.messages.tests.test_fallback import FallbackTest
-from django.contrib.messages.tests.test_middleware import MiddlewareTest
-from django.contrib.messages.tests.test_session import SessionTest
-from django.contrib.messages.tests.test_mixins import SuccessMessageMixinTests
View
4 django/contrib/sitemaps/tests/__init__.py
@@ -1,4 +0,0 @@
-from .test_flatpages import FlatpagesSitemapTests
-from .test_generic import GenericViewsSitemapTests
-from .test_http import HTTPSitemapTests
-from .test_https import HTTPSSitemapTests, HTTPSDetectionSitemapTests
View
7 django/test/_doctest.py
@@ -49,6 +49,13 @@ def _test():
of doctest's default behaviors. See the Library Reference Manual for
details.
"""
+import warnings
+
+warnings.warn(
+ "The django.test._doctest module is deprecated; "
+ "use the doctest module from the Python standard library instead.",
+ PendingDeprecationWarning)
+
__docformat__ = 'reStructuredText en'
View
289 django/test/runner.py
@@ -0,0 +1,289 @@
+import os
+from optparse import make_option
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.test import TestCase
+from django.test.utils import setup_test_environment, teardown_test_environment
+from django.utils import unittest
+from django.utils.unittest import TestSuite, defaultTestLoader
+
+
+class DiscoverRunner(object):
+ """
+ A Django test runner that uses unittest2 test discovery.
+ """
+
+ test_loader = defaultTestLoader
+ reorder_by = (TestCase, )
+ option_list = (
+ make_option('-t', '--top-level-directory',
+ action='store', dest='top_level', default=None,
+ help='Top level of project for unittest discovery.'),
+ make_option('-p', '--pattern', action='store', dest='pattern',
+ default="test*.py",
+ help='The test matching pattern. Defaults to test*.py.'),
+ )
+
+ def __init__(self, pattern=None, top_level=None,
+ verbosity=1, interactive=True, failfast=False,
+ **kwargs):
+
+ self.pattern = pattern
+ self.top_level = top_level
+
+ self.verbosity = verbosity
+ self.interactive = interactive
+ self.failfast = failfast
+
+ def setup_test_environment(self, **kwargs):
+ setup_test_environment()
+ settings.DEBUG = False
+ unittest.installHandler()
+
+ def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
+ suite = TestSuite()
+ test_labels = test_labels or ['.']
+ extra_tests = extra_tests or []
+
+ discover_kwargs = {}
+ if self.pattern is not None:
+ discover_kwargs['pattern'] = self.pattern
+ if self.top_level is not None:
+ discover_kwargs['top_level_dir'] = self.top_level
+
+ for label in test_labels:
+ kwargs = discover_kwargs.copy()
+ tests = None
+
+ label_as_path = os.path.abspath(label)
+
+ # if a module, or "module.ClassName[.method_name]", just run those
+ if not os.path.exists(label_as_path):
+ tests = self.test_loader.loadTestsFromName(label)
+ elif os.path.isdir(label_as_path) and not self.top_level:
+ # Try to be a bit smarter than unittest about finding the
@orymate
orymate added a note

This smartness should really be documented. If you have an __init__.py in the directory containing manage.py, tests won't run.

@carljm Owner
carljm added a note

Yes, you're right. We provide the necessary work-around for this situation (the -t option, which prevents this autodetection logic from running at all), but the documentation could be more explicit about the autodetection behavior. Perhaps you'd be willing to submit a pull request and/or Trac ticket? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ # default top-level for a given directory path, to avoid
+ # breaking relative imports. (Unittest's default is to set
+ # top-level equal to the path, which means relative imports
+ # will result in "Attempted relative import in non-package.").
+
+ # We'd be happy to skip this and require dotted module paths
+ # (which don't cause this problem) instead of file paths (which
+ # do), but in the case of a directory in the cwd, which would
+ # be equally valid if considered as a top-level module or as a
+ # directory path, unittest unfortunately prefers the latter.
+
+ top_level = label_as_path
+ while True:
+ init_py = os.path.join(top_level, '__init__.py')
+ if os.path.exists(init_py):
+ try_next = os.path.dirname(top_level)
+ if try_next == top_level:
+ # __init__.py all the way down? give up.
+ break
+ top_level = try_next
+ continue
+ break
+ kwargs['top_level_dir'] = top_level
+
+
+ if not (tests and tests.countTestCases()):
+ # if no tests found, it's probably a package; try discovery
+ tests = self.test_loader.discover(start_dir=label, **kwargs)
+
+ # make unittest forget the top-level dir it calculated from this
+ # run, to support running tests from two different top-levels.
+ self.test_loader._top_level_dir = None
+
+ suite.addTests(tests)
+
+ for test in extra_tests:
+ suite.addTest(test)
+
+ return reorder_suite(suite, self.reorder_by)
+
+ def setup_databases(self, **kwargs):
+ return setup_databases(self.verbosity, self.interactive, **kwargs)
+
+ def run_suite(self, suite, **kwargs):
+ return unittest.TextTestRunner(
+ verbosity=self.verbosity,
+ failfast=self.failfast,
+ ).run(suite)
+
+ def teardown_databases(self, old_config, **kwargs):
+ """
+ Destroys all the non-mirror databases.
+ """
+ old_names, mirrors = old_config
+ for connection, old_name, destroy in old_names:
+ if destroy:
+ connection.creation.destroy_test_db(old_name, self.verbosity)
+
+ def teardown_test_environment(self, **kwargs):
+ unittest.removeHandler()
+ teardown_test_environment()
+
+ def suite_result(self, suite, result, **kwargs):
+ return len(result.failures) + len(result.errors)
+
+ def run_tests(self, test_labels, extra_tests=None, **kwargs):
+ """
+ Run the unit tests for all the test labels in the provided list.
+
+ Test labels should be dotted Python paths to test modules, test
+ classes, or test methods.
+
+ A list of 'extra' tests may also be provided; these tests
+ will be added to the test suite.
+
+ Returns the number of tests that failed.
+ """
+ self.setup_test_environment()
+ suite = self.build_suite(test_labels, extra_tests)
+ old_config = self.setup_databases()
+ result = self.run_suite(suite)
+ self.teardown_databases(old_config)
+ self.teardown_test_environment()
+ return self.suite_result(suite, result)
+
+
+def dependency_ordered(test_databases, dependencies):
+ """
+ Reorder test_databases into an order that honors the dependencies
+ described in TEST_DEPENDENCIES.
+ """
+ ordered_test_databases = []
+ resolved_databases = set()
+
+ # Maps db signature to dependencies of all it's aliases
+ dependencies_map = {}
+
+ # sanity check - no DB can depend on it's own alias
+ for sig, (_, aliases) in test_databases:
+ all_deps = set()
+ for alias in aliases:
+ all_deps.update(dependencies.get(alias, []))
+ if not all_deps.isdisjoint(aliases):
+ raise ImproperlyConfigured(
+ "Circular dependency: databases %r depend on each other, "
+ "but are aliases." % aliases)
+ dependencies_map[sig] = all_deps
+
+ while test_databases:
+ changed = False
+ deferred = []
+
+ # Try to find a DB that has all it's dependencies met
+ for signature, (db_name, aliases) in test_databases:
+ if dependencies_map[signature].issubset(resolved_databases):
+ resolved_databases.update(aliases)
+ ordered_test_databases.append((signature, (db_name, aliases)))
+ changed = True
+ else:
+ deferred.append((signature, (db_name, aliases)))
+
+ if not changed:
+ raise ImproperlyConfigured(
+ "Circular dependency in TEST_DEPENDENCIES")
+ test_databases = deferred
+ return ordered_test_databases
+
+
+def reorder_suite(suite, classes):
+ """
+ Reorders a test suite by test type.
+
+ `classes` is a sequence of types
+
+ All tests of type classes[0] are placed first, then tests of type
+ classes[1], etc. Tests with no match in classes are placed last.
+ """
+ class_count = len(classes)
+ bins = [unittest.TestSuite() for i in range(class_count+1)]
+ partition_suite(suite, classes, bins)
+ for i in range(class_count):
+ bins[0].addTests(bins[i+1])
+ return bins[0]
+
+
+def partition_suite(suite, classes, bins):
+ """
+ Partitions a test suite by test type.
+
+ classes is a sequence of types
+ bins is a sequence of TestSuites, one more than classes
+
+ Tests of type classes[i] are added to bins[i],
+ tests with no match found in classes are place in bins[-1]
+ """
+ for test in suite:
+ if isinstance(test, unittest.TestSuite):
+ partition_suite(test, classes, bins)
+ else:
+ for i in range(len(classes)):
+ if isinstance(test, classes[i]):
+ bins[i].addTest(test)
+ break
+ else:
+ bins[-1].addTest(test)
+
+
+def setup_databases(verbosity, interactive, **kwargs):
+ from django.db import connections, DEFAULT_DB_ALIAS
+
+ # First pass -- work out which databases actually need to be created,
+ # and which ones are test mirrors or duplicate entries in DATABASES
+ mirrored_aliases = {}
+ test_databases = {}
+ dependencies = {}
+ for alias in connections:
+ connection = connections[alias]
+ if connection.settings_dict['TEST_MIRROR']:
+ # If the database is marked as a test mirror, save
+ # the alias.
+ mirrored_aliases[alias] = (
+ connection.settings_dict['TEST_MIRROR'])
+ else:
+ # Store a tuple with DB parameters that uniquely identify it.
+ # If we have two aliases with the same values for that tuple,
+ # we only need to create the test database once.
+ item = test_databases.setdefault(
+ connection.creation.test_db_signature(),
+ (connection.settings_dict['NAME'], set())
+ )
+ item[1].add(alias)
+
+ if 'TEST_DEPENDENCIES' in connection.settings_dict:
+ dependencies[alias] = (
+ connection.settings_dict['TEST_DEPENDENCIES'])
+ else:
+ if alias != DEFAULT_DB_ALIAS:
+ dependencies[alias] = connection.settings_dict.get(
+ 'TEST_DEPENDENCIES', [DEFAULT_DB_ALIAS])
+
+ # Second pass -- actually create the databases.
+ old_names = []
+ mirrors = []
+
+ for signature, (db_name, aliases) in dependency_ordered(
+ test_databases.items(), dependencies):
+ test_db_name = None
+ # Actually create the database for the first connection
+
+ for alias in aliases:
+ connection = connections[alias]
+ old_names.append((connection, db_name, True))
+ if test_db_name is None:
+ test_db_name = connection.creation.create_test_db(
+ verbosity, autoclobber=not interactive)
+ else:
+ connection.settings_dict['NAME'] = test_db_name
+
+ for alias, mirror_alias in mirrored_aliases.items():
+ mirrors.append((alias, connections[alias].settings_dict['NAME']))
+ connections[alias].settings_dict['NAME'] = (
+ connections[mirror_alias].settings_dict['NAME'])
+
+ return old_names, mirrors
View
215 django/test/simple.py
@@ -1,10 +1,15 @@
+"""
+This module is pending deprecation as of Django 1.6 and will be removed in
+version 1.8.
+
+"""
+
import unittest as real_unittest
+import warnings
-from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
from django.db.models import get_app, get_apps
from django.test import _doctest as doctest
-from django.test.utils import setup_test_environment, teardown_test_environment
+from django.test import runner
from django.test.testcases import OutputChecker, DocTestRunner
from django.utils import unittest
from django.utils.importlib import import_module
@@ -12,6 +17,11 @@
__all__ = ('DjangoTestSuiteRunner',)
+warnings.warn(
+ "The django.test.simple module and DjangoTestSuiteRunner are deprecated; "
+ "use django.test.runner.DiscoverRunner instead.",
+ PendingDeprecationWarning)
+
# The module name for tests outside models.py
TEST_MODULE = 'tests'
@@ -154,97 +164,7 @@ def build_test(label):
return unittest.TestSuite(tests)
-def partition_suite(suite, classes, bins):
- """
- Partitions a test suite by test type.
-
- classes is a sequence of types
- bins is a sequence of TestSuites, one more than classes
-
- Tests of type classes[i] are added to bins[i],
- tests with no match found in classes are place in bins[-1]
- """
- for test in suite:
- if isinstance(test, unittest.TestSuite):
- partition_suite(test, classes, bins)
- else:
- for i in range(len(classes)):
- if isinstance(test, classes[i]):
- bins[i].addTest(test)
- break
- else:
- bins[-1].addTest(test)
-
-
-def reorder_suite(suite, classes):
- """
- Reorders a test suite by test type.
-
- `classes` is a sequence of types
-
- All tests of type classes[0] are placed first, then tests of type
- classes[1], etc. Tests with no match in classes are placed last.
- """
- class_count = len(classes)
- bins = [unittest.TestSuite() for i in range(class_count+1)]
- partition_suite(suite, classes, bins)
- for i in range(class_count):
- bins[0].addTests(bins[i+1])
- return bins[0]
-
-
-def dependency_ordered(test_databases, dependencies):
- """
- Reorder test_databases into an order that honors the dependencies
- described in TEST_DEPENDENCIES.
- """
- ordered_test_databases = []
- resolved_databases = set()
-
- # Maps db signature to dependencies of all it's aliases
- dependencies_map = {}
-
- # sanity check - no DB can depend on it's own alias
- for sig, (_, aliases) in test_databases:
- all_deps = set()
- for alias in aliases:
- all_deps.update(dependencies.get(alias, []))
- if not all_deps.isdisjoint(aliases):
- raise ImproperlyConfigured(
- "Circular dependency: databases %r depend on each other, "
- "but are aliases." % aliases)
- dependencies_map[sig] = all_deps
-
- while test_databases:
- changed = False
- deferred = []
-
- # Try to find a DB that has all it's dependencies met
- for signature, (db_name, aliases) in test_databases:
- if dependencies_map[signature].issubset(resolved_databases):
- resolved_databases.update(aliases)
- ordered_test_databases.append((signature, (db_name, aliases)))
- changed = True
- else:
- deferred.append((signature, (db_name, aliases)))
-
- if not changed:
- raise ImproperlyConfigured(
- "Circular dependency in TEST_DEPENDENCIES")
- test_databases = deferred
- return ordered_test_databases
-
-
-class DjangoTestSuiteRunner(object):
- def __init__(self, verbosity=1, interactive=True, failfast=True, **kwargs):
- self.verbosity = verbosity
- self.interactive = interactive
- self.failfast = failfast
-
- def setup_test_environment(self, **kwargs):
- setup_test_environment()
- settings.DEBUG = False
- unittest.installHandler()
+class DjangoTestSuiteRunner(runner.DiscoverRunner):
def build_suite(self, test_labels, extra_tests=None, **kwargs):
suite = unittest.TestSuite()
@@ -264,109 +184,4 @@ def build_suite(self, test_labels, extra_tests=None, **kwargs):
for test in extra_tests:
suite.addTest(test)
- return reorder_suite(suite, (unittest.TestCase,))
-
- def setup_databases(self, **kwargs):
- from django.db import connections, DEFAULT_DB_ALIAS
-
- # First pass -- work out which databases actually need to be created,
- # and which ones are test mirrors or duplicate entries in DATABASES
- mirrored_aliases = {}
- test_databases = {}
- dependencies = {}
- for alias in connections:
- connection = connections[alias]
- if connection.settings_dict['TEST_MIRROR']:
- # If the database is marked as a test mirror, save
- # the alias.
- mirrored_aliases[alias] = (
- connection.settings_dict['TEST_MIRROR'])
- else:
- # Store a tuple with DB parameters that uniquely identify it.
- # If we have two aliases with the same values for that tuple,
- # we only need to create the test database once.
- item = test_databases.setdefault(
- connection.creation.test_db_signature(),
- (connection.settings_dict['NAME'], set())
- )
- item[1].add(alias)
-
- if 'TEST_DEPENDENCIES' in connection.settings_dict:
- dependencies[alias] = (
- connection.settings_dict['TEST_DEPENDENCIES'])
- else:
- if alias != DEFAULT_DB_ALIAS:
- dependencies[alias] = connection.settings_dict.get(
- 'TEST_DEPENDENCIES', [DEFAULT_DB_ALIAS])
-
- # Second pass -- actually create the databases.
- old_names = []
- mirrors = []
-
- for signature, (db_name, aliases) in dependency_ordered(
- test_databases.items(), dependencies):
- test_db_name = None
- # Actually create the database for the first connection
-
- for alias in aliases:
- connection = connections[alias]
- old_names.append((connection, db_name, True))
- if test_db_name is None:
- test_db_name = connection.creation.create_test_db(
- self.verbosity, autoclobber=not self.interactive)
- else:
- connection.settings_dict['NAME'] = test_db_name
-
- for alias, mirror_alias in mirrored_aliases.items():
- mirrors.append((alias, connections[alias].settings_dict['NAME']))
- connections[alias].settings_dict['NAME'] = (
- connections[mirror_alias].settings_dict['NAME'])
-
- return old_names, mirrors
-
- def run_suite(self, suite, **kwargs):
- return unittest.TextTestRunner(
- verbosity=self.verbosity, failfast=self.failfast).run(suite)
-
- def teardown_databases(self, old_config, **kwargs):
- """
- Destroys all the non-mirror databases.
- """
- old_names, mirrors = old_config
- for connection, old_name, destroy in old_names:
- if destroy:
- connection.creation.destroy_test_db(old_name, self.verbosity)
-
- def teardown_test_environment(self, **kwargs):
- unittest.removeHandler()
- teardown_test_environment()
-
- def suite_result(self, suite, result, **kwargs):
- return len(result.failures) + len(result.errors)
-
- def run_tests(self, test_labels, extra_tests=None, **kwargs):
- """
- Run the unit tests for all the test labels in the provided list.
- Labels must be of the form:
- - app.TestClass.test_method
- Run a single specific test method
- - app.TestClass
- Run all the test methods in a given class
- - app
- Search for doctests and unittests in the named application.
-
- When looking for tests, the test runner will look in the models and
- tests modules for the application.
-
- A list of 'extra' tests may also be provided; these tests
- will be added to the test suite.
-
- Returns the number of tests that failed.
- """
- self.setup_test_environment()
- suite = self.build_suite(test_labels, extra_tests)
- old_config = self.setup_databases()
- result = self.run_suite(suite)
- self.teardown_databases(old_config)
- self.teardown_test_environment()
- return self.suite_result(suite, result)
+ return runner.reorder_suite(suite, (unittest.TestCase,))
View
10 django/test/testcases.py
@@ -97,6 +97,12 @@ def assert_and_parse_html(self, html, user_msg, msg):
class OutputChecker(doctest.OutputChecker):
+ def __init__(self):
+ warnings.warn(
+ "The django.test.testcases.OutputChecker class is deprecated; "
+ "use the doctest module from the Python standard library instead.",
+ PendingDeprecationWarning)
+
def check_output(self, want, got, optionflags):
"""
The entry method for doctest output checking. Defers to a sequence of
@@ -151,6 +157,10 @@ def check_output_json(self, want, got, optionsflags):
class DocTestRunner(doctest.DocTestRunner):
def __init__(self, *args, **kwargs):
+ warnings.warn(
+ "The django.test.testcases.DocTestRunner class is deprecated; "
+ "use the doctest module from the Python standard library instead.",
+ PendingDeprecationWarning)
doctest.DocTestRunner.__init__(self, *args, **kwargs)
self.optionflags = doctest.ELLIPSIS
View
2  django/utils/unittest/loader.py
@@ -125,7 +125,7 @@ def loadTestsFromName(self, name, module=None):
return self.loadTestsFromTestCase(obj)
elif (isinstance(obj, types.UnboundMethodType) and
isinstance(parent, type) and
- issubclass(parent, case.TestCase)):
+ issubclass(parent, unittest.TestCase)):
return self.suiteClass([parent(obj.__name__)])
elif isinstance(obj, unittest.TestSuite):
return obj
View
1  docs/index.txt
@@ -186,7 +186,6 @@ testing of Django applications:
:doc:`Introduction <topics/testing/index>` |
:doc:`Writing and running tests <topics/testing/overview>` |
:doc:`Advanced topics <topics/testing/advanced>` |
- :doc:`Doctests <topics/testing/doctests>`
* **Deployment:**
:doc:`Overview <howto/deployment/index>` |
View
11 docs/internals/deprecation.txt
@@ -73,7 +73,7 @@ these changes.
``django.utils.formats.get_format()`` to get the appropriate
formats.
-* The ability to use a function-based test runners will be removed,
+* The ability to use a function-based test runner will be removed,
along with the ``django.test.simple.run_tests()`` test runner.
* The ``views.feed()`` view and ``feeds.Feed`` class in
@@ -375,6 +375,15 @@ these changes.
* ``django.forms.widgets.RadioInput`` will be removed in favor of
``django.forms.widgets.RadioChoiceInput``.
+* The module ``django.test.simple`` and the class
+ ``django.test.simple.DjangoTestSuiteRunner`` will be removed. Instead use
+ ``django.test.runner.DiscoverRunner``.
+
+* The module ``django.test._doctest`` and the classes
+ ``django.test.testcases.DocTestRunner`` and
+ ``django.test.testcases.OutputChecker`` will be removed. Instead use the
+ doctest module from the Python standard library.
+
2.0
---
View
5 docs/intro/tutorial05.txt
@@ -156,8 +156,9 @@ Create a test to expose the bug
What we've just done in the shell to test for the problem is exactly what we
can do in an automated test, so let's turn that into an automated test.
-The best place for an application's tests is in the application's ``tests.py``
-file - the testing system will look there for tests automatically.
+A conventional place for an application's tests is in the application's
+``tests.py`` file; the testing system will automatically find tests in any file
+whose name begins with ``test``.
Put the following in the ``tests.py`` file in the ``polls`` application::
View
57 docs/ref/contrib/gis/testing.txt
@@ -134,57 +134,14 @@ your settings::
GeoDjango tests
===============
-GeoDjango's test suite may be run in one of two ways, either by itself or
-with the rest of :ref:`Django's unit tests <running-unit-tests>`.
+To have the GeoDjango tests executed when :ref:`running the Django test suite
+<running-unit-tests>` with ``runtests.py`` all of the databases in the settings
+file must be using one of the :ref:`spatial database backends
+<spatial-backends>`.
-Run only GeoDjango tests
-------------------------
-
-.. class:: django.contrib.gis.tests.GeoDjangoTestSuiteRunner
-
-To run *only* the tests for GeoDjango, the :setting:`TEST_RUNNER`
-setting must be changed to use the
-:class:`~django.contrib.gis.tests.GeoDjangoTestSuiteRunner`::
-
- TEST_RUNNER = 'django.contrib.gis.tests.GeoDjangoTestSuiteRunner'
Example
-^^^^^^^
-
-First, you'll need a bare-bones settings file, like below, that is
-customized with your spatial database name and user::
-
- TEST_RUNNER = 'django.contrib.gis.tests.GeoDjangoTestSuiteRunner'
-
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.contrib.gis.db.backends.postgis',
- 'NAME': 'a_spatial_database',
- 'USER': 'db_user'
- }
- }
-
-Assuming the above is in a file called ``postgis.py`` that is in the
-the same directory as ``manage.py`` of your Django project, then
-you may run the tests with the following command::
-
- $ python manage.py test --settings=postgis
-
-Run with ``runtests.py``
-------------------------
-
-To have the GeoDjango tests executed when
-:ref:`running the Django test suite <running-unit-tests>` with ``runtests.py``
-all of the databases in the settings file must be using one of the
-:ref:`spatial database backends <spatial-backends>`.
-
-.. warning::
-
- Do not change the :setting:`TEST_RUNNER` setting
- when running the GeoDjango tests with ``runtests.py``.
-
-Example
-^^^^^^^
+-------
The following is an example bare-bones settings file with spatial backends
that can be used to run the entire Django test suite, including those
@@ -208,3 +165,7 @@ directory as ``runtests.py``, then all Django and GeoDjango tests would
be performed when executing the command::
$ ./runtests.py --settings=postgis
+
+To run only the GeoDjango test suite, specify ``django.contrib.gis``::
+
+ $ ./runtests.py --settings=postgis django.contrib.gis
View
7 docs/ref/settings.txt
@@ -1725,11 +1725,16 @@ misspelled) variables. See :ref:`invalid-template-variables`..
TEST_RUNNER
-----------
-Default: ``'django.test.simple.DjangoTestSuiteRunner'``
+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
View
2  docs/releases/1.2.4.txt
@@ -78,7 +78,7 @@ GeoDjango
The function-based :setting:`TEST_RUNNER` previously used to execute
the GeoDjango test suite, ``django.contrib.gis.tests.run_gis_tests``,
was finally deprecated in favor of a class-based test runner,
-:class:`django.contrib.gis.tests.GeoDjangoTestSuiteRunner`, added in this
+``django.contrib.gis.tests.GeoDjangoTestSuiteRunner``, added in this
release.
In addition, the GeoDjango test suite is now included when
</