GeoDjango test suite housekeeping. Moved data into fixtures for `relatedapp` and `distapp` tests, and made both use Django's `TestCase`; moved functionality out of `GeoDjangoTestSuiteRunner` to allow future re-use in `runtests.py` (refs #10420); compressed test app fixtures and cleaned up imports.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14776 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2010-12-02 05:58:21 +00:00
parent fb391b8b98
commit 0f879195a6
14 changed files with 160 additions and 346 deletions

View File

@ -1,15 +1,12 @@
import sys
from django.conf import settings from django.conf import settings
from django.db.models import get_app
from django.test.simple import build_suite, DjangoTestSuiteRunner from django.test.simple import build_suite, DjangoTestSuiteRunner
from django.utils import unittest from django.utils import unittest
def run_tests(*args, **kwargs): def run_tests(*args, **kwargs):
from django.test.simple import run_tests as base_run_tests from django.test.simple import run_tests as base_run_tests
return base_run_tests(*args, **kwargs) return base_run_tests(*args, **kwargs)
def run_gis_tests(test_labels, verbosity=1, interactive=True, failfast=False, extra_tests=None): def run_gis_tests(test_labels, verbosity=1, interactive=True, failfast=False, extra_tests=None):
import warnings import warnings
warnings.warn( warnings.warn(
@ -19,94 +16,121 @@ def run_gis_tests(test_labels, verbosity=1, interactive=True, failfast=False, ex
test_runner = GeoDjangoTestSuiteRunner(verbosity=verbosity, interactive=interactive, failfast=failfast) test_runner = GeoDjangoTestSuiteRunner(verbosity=verbosity, interactive=interactive, failfast=failfast)
return test_runner.run_tests(test_labels, extra_tests=extra_tests) return test_runner.run_tests(test_labels, extra_tests=extra_tests)
def geo_apps(namespace=True):
"""
Returns a list of GeoDjango test applications that reside in
`django.contrib.gis.tests` that can be used with the current
database and the spatial libraries that are installed.
"""
from django.db import connection
from django.contrib.gis.geos import GEOS_PREPARE
from django.contrib.gis.gdal import HAS_GDAL
apps = ['geoapp', 'relatedapp']
# No distance queries on MySQL.
if not connection.ops.mysql:
apps.append('distapp')
# Test geography support with PostGIS 1.5+.
if connection.ops.postgis and connection.ops.geography:
apps.append('geogapp')
# The following GeoDjango test apps depend on GDAL support.
if HAS_GDAL:
# 3D apps use LayerMapping, which uses GDAL.
if connection.ops.postgis and GEOS_PREPARE:
apps.append('geo3d')
apps.append('layermap')
if namespace:
return ['django.contrib.gis.tests.%s' % app
for app in apps]
else:
return apps
def geodjango_suite():
"""
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 the measurment tests.
from django.contrib.gis.tests import test_measure
suite.addTest(test_measure.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())
from django.contrib.gis.tests import test_spatialrefsys, test_geoforms
suite.addTest(test_spatialrefsys.suite())
suite.addTest(test_geoforms.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.utils import HAS_GEOIP
if HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'):
from django.contrib.gis.tests import test_geoip
suite.addTest(test_geoip.suite())
# Finally, adding the suites for each of the GeoDjango test apps.
for app_name in geo_apps(namespace=False):
suite.addTest(build_suite(get_app(app_name)))
return suite
class GeoDjangoTestSuiteRunner(DjangoTestSuiteRunner): class GeoDjangoTestSuiteRunner(DjangoTestSuiteRunner):
def setup_test_environment(self, **kwargs): def setup_test_environment(self, **kwargs):
super(GeoDjangoTestSuiteRunner, self).setup_test_environment(**kwargs) super(GeoDjangoTestSuiteRunner, self).setup_test_environment(**kwargs)
from django.db import connection # Saving original values of INSTALLED_APPS, ROOT_URLCONF, and SITE_ID.
from django.contrib.gis.geos import GEOS_PREPARE
from django.contrib.gis.gdal import HAS_GDAL
# Getting and storing the original values of INSTALLED_APPS and
# the ROOT_URLCONF.
self.old_installed = getattr(settings, 'INSTALLED_APPS', None) self.old_installed = getattr(settings, 'INSTALLED_APPS', None)
self.old_root_urlconf = getattr(settings, 'ROOT_URLCONF', None) self.old_root_urlconf = getattr(settings, 'ROOT_URLCONF', '')
self.old_site_id = getattr(settings, 'SITE_ID', None) self.old_site_id = getattr(settings, 'SITE_ID', None)
# Tests that require use of a spatial database (e.g., creation of models)
self.geo_apps = ['geoapp', 'relatedapp']
if connection.ops.postgis and connection.ops.geography:
# Test geography support with PostGIS 1.5+.
self.geo_apps.append('geogapp')
if HAS_GDAL:
# The following GeoDjango test apps depend on GDAL support.
if not connection.ops.mysql:
self.geo_apps.append('distapp')
# 3D apps use LayerMapping, which uses GDAL.
if connection.ops.postgis and GEOS_PREPARE:
self.geo_apps.append('geo3d')
self.geo_apps.append('layermap')
# Constructing the new INSTALLED_APPS, and including applications # Constructing the new INSTALLED_APPS, and including applications
# within the GeoDjango test namespace (`self.geo_apps`). # within the GeoDjango test namespace.
new_installed = ['django.contrib.sites', new_installed = ['django.contrib.sites',
'django.contrib.sitemaps', 'django.contrib.sitemaps',
'django.contrib.gis', 'django.contrib.gis',
] ]
new_installed.extend(['django.contrib.gis.tests.%s' % app
for app in self.geo_apps]) # Calling out to `geo_apps` to get GeoDjango applications supported
# for testing.
new_installed.extend(geo_apps())
settings.INSTALLED_APPS = new_installed settings.INSTALLED_APPS = new_installed
# Setting the URLs. # SITE_ID needs to be set
settings.ROOT_URLCONF = 'django.contrib.gis.tests.urls'
settings.SITE_ID = 1 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): def teardown_test_environment(self, **kwargs):
super(GeoDjangoTestSuiteRunner, self).teardown_test_environment(**kwargs) super(GeoDjangoTestSuiteRunner, self).teardown_test_environment(**kwargs)
settings.INSTALLED_APPS = self.old_installed settings.INSTALLED_APPS = self.old_installed
settings.ROOT_URLCONF = self.old_root_urlconf settings.ROOT_URLCONF = self.old_root_urlconf
settings.SITE_ID = self.old_site_id settings.SITE_ID = self.old_site_id
def build_suite(self, test_labels, extra_tests=None, **kwargs): def build_suite(self, test_labels, extra_tests=None, **kwargs):
""" return geodjango_suite()
This method is overridden to construct a suite consisting only of tests
for GeoDjango.
"""
suite = unittest.TestSuite()
# Adding the GEOS tests.
from django.contrib.gis.geos import tests as geos_tests
suite.addTest(geos_tests.suite())
# Adding the measurment tests.
from django.contrib.gis.tests import test_measure
suite.addTest(test_measure.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())
from django.contrib.gis.tests import test_spatialrefsys, test_geoforms
suite.addTest(test_spatialrefsys.suite())
suite.addTest(test_geoforms.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.utils import HAS_GEOIP
if HAS_GEOIP and hasattr(settings, 'GEOIP_PATH'):
from django.contrib.gis.tests import test_geoip
suite.addTest(test_geoip.suite())
# Finally, adding the suites for each of the GeoDjango test apps.
for app_name in self.geo_apps:
suite.addTest(build_suite(get_app(app_name)))
return suite

View File

@ -1,36 +0,0 @@
au_cities = (('Wollongong', 150.902, -34.4245),
('Shellharbour', 150.87, -34.5789),
('Thirroul', 150.924, -34.3147),
('Mittagong', 150.449, -34.4509),
('Batemans Bay', 150.175, -35.7082),
('Canberra', 144.963, -37.8143),
('Melbourne', 145.963, -37.8143),
('Sydney', 151.26071, -33.887034),
('Hobart', 147.33, -42.8827),
('Adelaide', 138.6, -34.9258),
('Hillsdale', 151.231341, -33.952685),
)
stx_cities = (('Downtown Houston', -95.363151, 29.763374),
('West University Place', -95.448601, 29.713803),
('Southside Place', -95.436920, 29.705777),
('Bellaire', -95.458732, 29.705614),
('Pearland', -95.287303, 29.563568),
('Galveston', -94.797489, 29.301336),
('Sealy', -96.156952, 29.780918),
('San Antonio', -98.493183, 29.424170),
('Saint Hedwig', -98.199820, 29.414197),
)
# Data from U.S. Census ZCTA cartographic boundary file for Texas (`zt48_d00.shp`).
stx_zips = (('77002', 'POLYGON ((-95.365015 29.772327, -95.362415 29.772327, -95.360915 29.771827, -95.354615 29.771827, -95.351515 29.772527, -95.350915 29.765327, -95.351015 29.762436, -95.350115 29.760328, -95.347515 29.758528, -95.352315 29.753928, -95.356415 29.756328, -95.358215 29.754028, -95.360215 29.756328, -95.363415 29.757128, -95.364014 29.75638, -95.363415 29.753928, -95.360015 29.751828, -95.361815 29.749528, -95.362715 29.750028, -95.367516 29.744128, -95.369316 29.745128, -95.373916 29.744128, -95.380116 29.738028, -95.387916 29.727929, -95.388516 29.729629, -95.387916 29.732129, -95.382916 29.737428, -95.376616 29.742228, -95.372616 29.747228, -95.378601 29.750846, -95.378616 29.752028, -95.378616 29.754428, -95.376016 29.754528, -95.374616 29.759828, -95.373616 29.761128, -95.371916 29.763928, -95.372316 29.768727, -95.365884 29.76791, -95.366015 29.767127, -95.358715 29.765327, -95.358615 29.766327, -95.359115 29.767227, -95.360215 29.767027, -95.362783 29.768267, -95.365315 29.770527, -95.365015 29.772327))'),
('77005', 'POLYGON ((-95.447918 29.727275, -95.428017 29.728729, -95.421117 29.729029, -95.418617 29.727629, -95.418517 29.726429, -95.402117 29.726629, -95.402117 29.725729, -95.395316 29.725729, -95.391916 29.726229, -95.389716 29.725829, -95.396517 29.715429, -95.397517 29.715929, -95.400917 29.711429, -95.411417 29.715029, -95.418417 29.714729, -95.418317 29.70623, -95.440818 29.70593, -95.445018 29.70683, -95.446618 29.70763, -95.447418 29.71003, -95.447918 29.727275))'),
('77025', 'POLYGON ((-95.418317 29.70623, -95.414717 29.706129, -95.414617 29.70533, -95.418217 29.70533, -95.419817 29.69533, -95.419484 29.694196, -95.417166 29.690901, -95.414517 29.69433, -95.413317 29.69263, -95.412617 29.68973, -95.412817 29.68753, -95.414087 29.685055, -95.419165 29.685428, -95.421617 29.68513, -95.425717 29.67983, -95.425017 29.67923, -95.424517 29.67763, -95.427418 29.67763, -95.438018 29.664631, -95.436713 29.664411, -95.440118 29.662231, -95.439218 29.661031, -95.437718 29.660131, -95.435718 29.659731, -95.431818 29.660331, -95.441418 29.656631, -95.441318 29.656331, -95.441818 29.656131, -95.441718 29.659031, -95.441118 29.661031, -95.446718 29.656431, -95.446518 29.673431, -95.446918 29.69013, -95.447418 29.71003, -95.446618 29.70763, -95.445018 29.70683, -95.440818 29.70593, -95.418317 29.70623))'),
('77401', 'POLYGON ((-95.447918 29.727275, -95.447418 29.71003, -95.446918 29.69013, -95.454318 29.68893, -95.475819 29.68903, -95.475819 29.69113, -95.484419 29.69103, -95.484519 29.69903, -95.480419 29.70133, -95.480419 29.69833, -95.474119 29.69833, -95.474119 29.70453, -95.472719 29.71283, -95.468019 29.71293, -95.468219 29.720229, -95.464018 29.720229, -95.464118 29.724529, -95.463018 29.725929, -95.459818 29.726129, -95.459918 29.720329, -95.451418 29.720429, -95.451775 29.726303, -95.451318 29.727029, -95.447918 29.727275))'),
)
interstates = (('I-25', 'LINESTRING(-104.4780170766108 36.66698791870694, -104.4468522338495 36.79925409393386, -104.46212692626 36.9372149776075, -104.5126119783768 37.08163268820887, -104.5247764602161 37.29300499892048, -104.7084397427668 37.49150259925398, -104.8126599016282 37.69514285621863, -104.8452887035466 37.87613395659479, -104.7160169341003 38.05951763337799, -104.6165437927668 38.30432045855106, -104.6437227858174 38.53979986564737, -104.7596170387259 38.7322907594295, -104.8380078676822 38.89998460604341, -104.8501253693506 39.09980189213358, -104.8791648316464 39.24368776457503, -104.8635041274215 39.3785278162751, -104.8894471170052 39.5929228239605, -104.9721242843344 39.69528482419685, -105.0112104500356 39.7273080432394, -105.0010368577104 39.76677607811571, -104.981835619 39.81466504121967, -104.9858891550477 39.88806911250832, -104.9873548059578 39.98117234571016, -104.9766220487419 40.09796423450692, -104.9818565932953 40.36056530662884, -104.9912746373997 40.74904484447656)'),
)
stx_interstates = (('I-10', 'LINESTRING(924952.5 4220931.6,925065.3 4220931.6,929568.4 4221057.8)'),
)

View File

@ -1,18 +1,17 @@
import os, unittest import os
from decimal import Decimal from decimal import Decimal
from django.db import connection from django.db import connection
from django.db.models import Q from django.db.models import Q
from django.contrib.gis.gdal import DataSource
from django.contrib.gis.geos import GEOSGeometry, Point, LineString from django.contrib.gis.geos import GEOSGeometry, Point, LineString
from django.contrib.gis.measure import D # alias for Distance 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 oracle, postgis, spatialite, no_oracle, no_spatialite
from django.test import TestCase
from models import AustraliaCity, Interstate, SouthTexasInterstate, \ from models import AustraliaCity, Interstate, SouthTexasInterstate, \
SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode SouthTexasCity, SouthTexasCityFt, CensusZipcode, SouthTexasZipcode
from data import au_cities, interstates, stx_interstates, stx_cities, stx_zips
class DistanceTest(unittest.TestCase): class DistanceTest(TestCase):
# A point we are testing distances with -- using a WGS84 # A point we are testing distances with -- using a WGS84
# coordinate that'll be implicitly transormed to that to # coordinate that'll be implicitly transormed to that to
@ -28,37 +27,12 @@ class DistanceTest(unittest.TestCase):
return cities return cities
def test01_init(self): def test01_init(self):
"Initialization of distance models." "Test initialization of distance models."
# Loading up the cities.
def load_cities(city_model, data_tup):
for name, x, y in data_tup:
city_model(name=name, point=Point(x, y, srid=4326)).save()
def load_interstates(imodel, data_tup):
for name, wkt in data_tup:
imodel(name=name, path=wkt).save()
load_cities(SouthTexasCity, stx_cities)
load_cities(SouthTexasCityFt, stx_cities)
load_cities(AustraliaCity, au_cities)
self.assertEqual(9, SouthTexasCity.objects.count()) self.assertEqual(9, SouthTexasCity.objects.count())
self.assertEqual(9, SouthTexasCityFt.objects.count()) self.assertEqual(9, SouthTexasCityFt.objects.count())
self.assertEqual(11, AustraliaCity.objects.count()) self.assertEqual(11, AustraliaCity.objects.count())
# Loading up the South Texas Zip Codes.
for name, wkt in stx_zips:
poly = GEOSGeometry(wkt, srid=4269)
SouthTexasZipcode(name=name, poly=poly).save()
CensusZipcode(name=name, poly=poly).save()
self.assertEqual(4, SouthTexasZipcode.objects.count()) self.assertEqual(4, SouthTexasZipcode.objects.count())
self.assertEqual(4, CensusZipcode.objects.count()) self.assertEqual(4, CensusZipcode.objects.count())
# Loading up the Interstates.
load_interstates(Interstate, interstates)
load_interstates(SouthTexasInterstate, stx_interstates)
self.assertEqual(1, Interstate.objects.count()) self.assertEqual(1, Interstate.objects.count())
self.assertEqual(1, SouthTexasInterstate.objects.count()) self.assertEqual(1, SouthTexasInterstate.objects.count())
@ -382,8 +356,3 @@ class DistanceTest(unittest.TestCase):
z = SouthTexasZipcode.objects.distance(htown.point).area().get(name='78212') z = SouthTexasZipcode.objects.distance(htown.point).area().get(name='78212')
self.assertEqual(None, z.distance) self.assertEqual(None, z.distance)
self.assertEqual(None, z.area) self.assertEqual(None, z.area)
def suite():
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(DistanceTest))
return s

View File

@ -1,4 +1,6 @@
import os, re, unittest import os
import re
from django.utils.unittest import TestCase
from django.contrib.gis.db.models import Union, Extent3D from django.contrib.gis.db.models import Union, Extent3D
from django.contrib.gis.geos import GEOSGeometry, Point, Polygon from django.contrib.gis.geos import GEOSGeometry, Point, Polygon
from django.contrib.gis.utils import LayerMapping, LayerMapError from django.contrib.gis.utils import LayerMapping, LayerMapError
@ -49,7 +51,7 @@ def gen_bbox():
bbox_3d = Polygon(tuple((x, y, z) for (x, y), z in zip(bbox_2d[0].coords, bbox_z)), srid=32140) bbox_3d = Polygon(tuple((x, y, z) for (x, y), z in zip(bbox_2d[0].coords, bbox_z)), srid=32140)
return bbox_2d, bbox_3d return bbox_2d, bbox_3d
class Geo3DTest(unittest.TestCase): class Geo3DTest(TestCase):
""" """
Only a subset of the PostGIS routines are 3D-enabled, and this TestCase Only a subset of the PostGIS routines are 3D-enabled, and this TestCase
tries to test the features that can handle 3D and that are also tries to test the features that can handle 3D and that are also
@ -227,8 +229,3 @@ class Geo3DTest(unittest.TestCase):
for ztrans in ztranslations: for ztrans in ztranslations:
for city in City3D.objects.translate(0, 0, ztrans): for city in City3D.objects.translate(0, 0, ztrans):
self.assertEqual(city_dict[city.name][2] + ztrans, city.translate.z) self.assertEqual(city_dict[city.name][2] + ztrans, city.translate.z)
def suite():
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(Geo3DTest))
return s

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,12 @@
from xml.dom import minidom from xml.dom import minidom
from django.test import TestCase
from django.test import Client
from django.utils import unittest
from models import City from models import City
class GeoFeedTest(unittest.TestCase): class GeoFeedTest(TestCase):
client = Client()
urls = 'django.contrib.gis.tests.geoapp.urls'
def assertChildNodes(self, elem, expected): def assertChildNodes(self, elem, expected):
"Taken from regressiontests/syndication/tests.py." "Taken from regressiontests/syndication/tests.py."
@ -18,9 +17,9 @@ class GeoFeedTest(unittest.TestCase):
def test_geofeed_rss(self): def test_geofeed_rss(self):
"Tests geographic feeds using GeoRSS over RSSv2." "Tests geographic feeds using GeoRSS over RSSv2."
# Uses `GEOSGeometry` in `item_geometry` # Uses `GEOSGeometry` in `item_geometry`
doc1 = minidom.parseString(self.client.get('/geoapp/feeds/rss1/').content) doc1 = minidom.parseString(self.client.get('/feeds/rss1/').content)
# Uses a 2-tuple in `item_geometry` # Uses a 2-tuple in `item_geometry`
doc2 = minidom.parseString(self.client.get('/geoapp/feeds/rss2/').content) doc2 = minidom.parseString(self.client.get('/feeds/rss2/').content)
feed1, feed2 = doc1.firstChild, doc2.firstChild feed1, feed2 = doc1.firstChild, doc2.firstChild
# Making sure the box got added to the second GeoRSS feed. # Making sure the box got added to the second GeoRSS feed.
@ -43,8 +42,8 @@ class GeoFeedTest(unittest.TestCase):
def test_geofeed_atom(self): def test_geofeed_atom(self):
"Testing geographic feeds using GeoRSS over Atom." "Testing geographic feeds using GeoRSS over Atom."
doc1 = minidom.parseString(self.client.get('/geoapp/feeds/atom1/').content) doc1 = minidom.parseString(self.client.get('/feeds/atom1/').content)
doc2 = minidom.parseString(self.client.get('/geoapp/feeds/atom2/').content) doc2 = minidom.parseString(self.client.get('/feeds/atom2/').content)
feed1, feed2 = doc1.firstChild, doc2.firstChild feed1, feed2 = doc1.firstChild, doc2.firstChild
# Making sure the box got added to the second GeoRSS feed. # Making sure the box got added to the second GeoRSS feed.
@ -62,7 +61,7 @@ class GeoFeedTest(unittest.TestCase):
def test_geofeed_w3c(self): def test_geofeed_w3c(self):
"Testing geographic feeds using W3C Geo." "Testing geographic feeds using W3C Geo."
doc = minidom.parseString(self.client.get('/geoapp/feeds/w3cgeo1/').content) doc = minidom.parseString(self.client.get('/feeds/w3cgeo1/').content)
feed = doc.firstChild feed = doc.firstChild
# Ensuring the geo namespace was added to the <feed> element. # Ensuring the geo namespace was added to the <feed> element.
self.assertEqual(feed.getAttribute(u'xmlns:geo'), u'http://www.w3.org/2003/01/geo/wgs84_pos#') self.assertEqual(feed.getAttribute(u'xmlns:geo'), u'http://www.w3.org/2003/01/geo/wgs84_pos#')
@ -75,5 +74,5 @@ class GeoFeedTest(unittest.TestCase):
self.assertChildNodes(item, ['title', 'link', 'description', 'guid', 'geo:lat', 'geo:lon']) self.assertChildNodes(item, ['title', 'link', 'description', 'guid', 'geo:lat', 'geo:lon'])
# Boxes and Polygons aren't allowed in W3C Geo feeds. # Boxes and Polygons aren't allowed in W3C Geo feeds.
self.assertRaises(ValueError, self.client.get, '/geoapp/feeds/w3cgeo2/') # Box in <channel> self.assertRaises(ValueError, self.client.get, '/feeds/w3cgeo2/') # Box in <channel>
self.assertRaises(ValueError, self.client.get, '/geoapp/feeds/w3cgeo3/') # Polygons in <entry> self.assertRaises(ValueError, self.client.get, '/feeds/w3cgeo3/') # Polygons in <entry>

View File

@ -1,15 +1,14 @@
import cStringIO import cStringIO
from xml.dom import minidom from xml.dom import minidom
import zipfile import zipfile
from django.test import TestCase
from django.test import Client
from django.utils import unittest
from models import City, Country from models import City, Country
class GeoSitemapTest(unittest.TestCase): class GeoSitemapTest(TestCase):
client = Client()
urls = 'django.contrib.gis.tests.geoapp.urls'
def assertChildNodes(self, elem, expected): def assertChildNodes(self, elem, expected):
"Taken from regressiontests/syndication/tests.py." "Taken from regressiontests/syndication/tests.py."
@ -20,7 +19,7 @@ class GeoSitemapTest(unittest.TestCase):
def test_geositemap_index(self): def test_geositemap_index(self):
"Tests geographic sitemap index." "Tests geographic sitemap index."
# Getting the geo index. # Getting the geo index.
doc = minidom.parseString(self.client.get('/geoapp/sitemap.xml').content) doc = minidom.parseString(self.client.get('/sitemap.xml').content)
index = doc.firstChild index = doc.firstChild
self.assertEqual(index.getAttribute(u'xmlns'), u'http://www.sitemaps.org/schemas/sitemap/0.9') self.assertEqual(index.getAttribute(u'xmlns'), u'http://www.sitemaps.org/schemas/sitemap/0.9')
self.assertEqual(3, len(index.getElementsByTagName('sitemap'))) self.assertEqual(3, len(index.getElementsByTagName('sitemap')))
@ -28,7 +27,7 @@ class GeoSitemapTest(unittest.TestCase):
def test_geositemap_kml(self): def test_geositemap_kml(self):
"Tests KML/KMZ geographic sitemaps." "Tests KML/KMZ geographic sitemaps."
for kml_type in ('kml', 'kmz'): for kml_type in ('kml', 'kmz'):
doc = minidom.parseString(self.client.get('/geoapp/sitemaps/%s.xml' % kml_type).content) doc = minidom.parseString(self.client.get('/sitemaps/%s.xml' % kml_type).content)
# Ensuring the right sitemaps namespaces are present. # Ensuring the right sitemaps namespaces are present.
urlset = doc.firstChild urlset = doc.firstChild
@ -68,7 +67,7 @@ class GeoSitemapTest(unittest.TestCase):
"Tests GeoRSS geographic sitemaps." "Tests GeoRSS geographic sitemaps."
from feeds import feed_dict from feeds import feed_dict
doc = minidom.parseString(self.client.get('/geoapp/sitemaps/georss.xml').content) doc = minidom.parseString(self.client.get('/sitemaps/georss.xml').content)
# Ensuring the right sitemaps namespaces are present. # Ensuring the right sitemaps namespaces are present.
urlset = doc.firstChild urlset = doc.firstChild

View File

@ -1,10 +1,11 @@
import re, os, unittest import re
from django.db import connection from django.db import connection
from django.contrib.gis import gdal from django.contrib.gis import gdal
from django.contrib.gis.geos import * from django.contrib.gis.geos import fromstr, GEOSGeometry, \
Point, LineString, LinearRing, Polygon, GeometryCollection
from django.contrib.gis.measure import Distance from django.contrib.gis.measure import Distance
from django.contrib.gis.tests.utils import \ from django.contrib.gis.tests.utils import \
no_mysql, no_oracle, no_postgis, no_spatialite, \ no_mysql, no_oracle, no_spatialite, \
mysql, oracle, postgis, spatialite mysql, oracle, postgis, spatialite
from django.test import TestCase from django.test import TestCase
@ -732,11 +733,3 @@ class GeoModelTest(TestCase):
from test_feeds import GeoFeedTest from test_feeds import GeoFeedTest
from test_regress import GeoRegressionTests from test_regress import GeoRegressionTests
from test_sitemaps import GeoSitemapTest from test_sitemaps import GeoSitemapTest
def suite():
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(GeoModelTest))
s.addTest(unittest.makeSuite(GeoFeedTest))
s.addTest(unittest.makeSuite(GeoSitemapTest))
s.addTest(unittest.makeSuite(GeoRegressionTests))
return s

View File

@ -1,8 +1,8 @@
import os import os
from decimal import Decimal from decimal import Decimal
from django.utils import unittest
from django.utils.copycompat import copy from django.utils.copycompat import copy
from django.utils.unittest import TestCase
from django.contrib.gis.gdal import DataSource from django.contrib.gis.gdal import DataSource
from django.contrib.gis.tests.utils import mysql from django.contrib.gis.tests.utils import mysql
@ -10,7 +10,7 @@ from django.contrib.gis.utils.layermapping import LayerMapping, LayerMapError, I
from models import City, County, CountyFeat, Interstate, ICity1, ICity2, State, city_mapping, co_mapping, cofeat_mapping, inter_mapping from models import City, County, CountyFeat, Interstate, ICity1, ICity2, State, city_mapping, co_mapping, cofeat_mapping, inter_mapping
shp_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', 'data')) shp_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'data'))
city_shp = os.path.join(shp_path, 'cities', 'cities.shp') city_shp = os.path.join(shp_path, 'cities', 'cities.shp')
co_shp = os.path.join(shp_path, 'counties', 'counties.shp') co_shp = os.path.join(shp_path, 'counties', 'counties.shp')
inter_shp = os.path.join(shp_path, 'interstates', 'interstates.shp') inter_shp = os.path.join(shp_path, 'interstates', 'interstates.shp')
@ -20,7 +20,7 @@ NAMES = ['Bexar', 'Galveston', 'Harris', 'Honolulu', 'Pueblo']
NUMS = [1, 2, 1, 19, 1] # Number of polygons for each. NUMS = [1, 2, 1, 19, 1] # Number of polygons for each.
STATES = ['Texas', 'Texas', 'Texas', 'Hawaii', 'Colorado'] STATES = ['Texas', 'Texas', 'Texas', 'Hawaii', 'Colorado']
class LayerMapTest(unittest.TestCase): class LayerMapTest(TestCase):
def test01_init(self): def test01_init(self):
"Testing LayerMapping initialization." "Testing LayerMapping initialization."
@ -265,8 +265,3 @@ class LayerMapTest(unittest.TestCase):
self.assertEqual(6, ICity1.objects.count()) self.assertEqual(6, ICity1.objects.count())
self.assertEqual(3, ICity2.objects.count()) self.assertEqual(3, ICity2.objects.count())
def suite():
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(LayerMapTest))
return s

View File

@ -1,23 +1,13 @@
import os, unittest from django.test import TestCase
from django.contrib.gis.geos import *
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.db.models import Collect, Count, Extent, F, Union
from django.contrib.gis.geometry.backend import Geometry from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.tests.utils import mysql, oracle, postgis, spatialite, no_mysql, no_oracle, no_spatialite from django.contrib.gis.tests.utils import mysql, oracle, no_mysql, no_oracle, no_spatialite
from django.conf import settings
from models import City, Location, DirectoryEntry, Parcel, Book, Author, Article from models import City, Location, DirectoryEntry, Parcel, Book, Author, Article
cities = (('Aurora', 'TX', -97.516111, 33.058333), class RelatedGeoModelTest(TestCase):
('Roswell', 'NM', -104.528056, 33.387222),
('Kecksburg', 'PA', -79.460734, 40.18476),
)
class RelatedGeoModelTest(unittest.TestCase):
def test01_setup(self):
"Setting up for related model tests."
for name, state, lon, lat in cities:
loc = Location.objects.create(point=Point(lon, lat))
c = City.objects.create(name=name, state=state, location=loc)
def test02_select_related(self): def test02_select_related(self):
"Testing `select_related` on geographic models (see #7126)." "Testing `select_related` on geographic models (see #7126)."
@ -25,6 +15,13 @@ class RelatedGeoModelTest(unittest.TestCase):
qs2 = City.objects.select_related() qs2 = City.objects.select_related()
qs3 = City.objects.select_related('location') qs3 = City.objects.select_related('location')
# Reference data for what's in the fixtures.
cities = (
('Aurora', 'TX', -97.516111, 33.058333),
('Roswell', 'NM', -104.528056, 33.387222),
('Kecksburg', 'PA', -79.460734, 40.18476),
)
for qs in (qs1, qs2, qs3): for qs in (qs1, qs2, qs3):
for ref, c in zip(cities, qs): for ref, c in zip(cities, qs):
nm, st, lon, lat = ref nm, st, lon, lat = ref
@ -63,11 +60,11 @@ class RelatedGeoModelTest(unittest.TestCase):
# This combines the Extent and Union aggregates into one query # This combines the Extent and Union aggregates into one query
aggs = City.objects.aggregate(Extent('location__point')) aggs = City.objects.aggregate(Extent('location__point'))
# One for all locations, one that excludes Roswell. # One for all locations, one that excludes New Mexico (Roswell).
all_extent = (-104.528060913086, 33.0583305358887,-79.4607315063477, 40.1847610473633) all_extent = (-104.528056, 29.763374, -79.460734, 40.18476)
txpa_extent = (-97.51611328125, 33.0583305358887,-79.4607315063477, 40.1847610473633) txpa_extent = (-97.516111, 29.763374, -79.460734, 40.18476)
e1 = City.objects.extent(field_name='location__point') e1 = City.objects.extent(field_name='location__point')
e2 = City.objects.exclude(name='Roswell').extent(field_name='location__point') e2 = City.objects.exclude(state='NM').extent(field_name='location__point')
e3 = aggs['location__point__extent'] e3 = aggs['location__point__extent']
# The tolerance value is to four decimal places because of differences # The tolerance value is to four decimal places because of differences
@ -83,10 +80,12 @@ class RelatedGeoModelTest(unittest.TestCase):
aggs = City.objects.aggregate(Union('location__point')) aggs = City.objects.aggregate(Union('location__point'))
# These are the points that are components of the aggregate geographic # These are the points that are components of the aggregate geographic
# union that is returned. # union that is returned. Each point # corresponds to City PK.
p1 = Point(-104.528056, 33.387222) p1 = Point(-104.528056, 33.387222)
p2 = Point(-97.516111, 33.058333) p2 = Point(-97.516111, 33.058333)
p3 = Point(-79.460734, 40.18476) p3 = Point(-79.460734, 40.18476)
p4 = Point(-96.801611, 32.782057)
p5 = Point(-95.363151, 29.763374)
# Creating the reference union geometry depending on the spatial backend, # Creating the reference union geometry depending on the spatial backend,
# as Oracle will have a different internal ordering of the component # as Oracle will have a different internal ordering of the component
@ -94,14 +93,15 @@ class RelatedGeoModelTest(unittest.TestCase):
# query that includes limiting information in the WHERE clause (in other # query that includes limiting information in the WHERE clause (in other
# words a `.filter()` precedes the call to `.unionagg()`). # words a `.filter()` precedes the call to `.unionagg()`).
if oracle: if oracle:
ref_u1 = MultiPoint(p3, p1, p2, srid=4326) ref_u1 = MultiPoint(p4, p5, p3, p1, p2, srid=4326)
ref_u2 = MultiPoint(p3, p2, srid=4326) ref_u2 = MultiPoint(p3, p2, srid=4326)
else: else:
ref_u1 = MultiPoint(p1, p2, p3, srid=4326) # Looks like PostGIS points by longitude value.
ref_u1 = MultiPoint(p1, p2, p4, p5, p3, srid=4326)
ref_u2 = MultiPoint(p2, p3, srid=4326) ref_u2 = MultiPoint(p2, p3, srid=4326)
u1 = City.objects.unionagg(field_name='location__point') u1 = City.objects.unionagg(field_name='location__point')
u2 = City.objects.exclude(name='Roswell').unionagg(field_name='location__point') u2 = City.objects.exclude(name__in=('Roswell', 'Houston', 'Dallas', 'Fort Worth')).unionagg(field_name='location__point')
u3 = aggs['location__point__union'] u3 = aggs['location__point__union']
self.assertEqual(ref_u1, u1) self.assertEqual(ref_u1, u1)
@ -187,17 +187,10 @@ class RelatedGeoModelTest(unittest.TestCase):
def test09_pk_relations(self): def test09_pk_relations(self):
"Ensuring correct primary key column is selected across relations. See #10757." "Ensuring correct primary key column is selected across relations. See #10757."
# Adding two more cities, but this time making sure that their location
# ID values do not match their City ID values.
loc1 = Location.objects.create(point='POINT (-95.363151 29.763374)')
loc2 = Location.objects.create(point='POINT (-96.801611 32.782057)')
dallas = City.objects.create(name='Dallas', state='TX', location=loc2)
houston = City.objects.create(name='Houston', state='TX', location=loc1)
# The expected ID values -- notice the last two location IDs # The expected ID values -- notice the last two location IDs
# are out of order. We want to make sure that the related # are out of order. Dallas and Houston have location IDs that differ
# location ID column is selected instead of ID column for # from their PKs -- this is done to ensure that the related location
# the city. # ID column is selected instead of ID column for the city.
city_ids = (1, 2, 3, 4, 5) city_ids = (1, 2, 3, 4, 5)
loc_ids = (1, 2, 3, 5, 4) loc_ids = (1, 2, 3, 5, 4)
ids_qs = City.objects.order_by('id').values('id', 'location__id') ids_qs = City.objects.order_by('id').values('id', 'location__id')
@ -232,10 +225,8 @@ class RelatedGeoModelTest(unittest.TestCase):
@no_oracle @no_oracle
def test12a_count(self): def test12a_count(self):
"Testing `Count` aggregate use with the `GeoManager` on geo-fields." "Testing `Count` aggregate use with the `GeoManager` on geo-fields."
# Creating a new City, 'Fort Worth', that uses the same location # The City, 'Fort Worth' uses the same location as Dallas.
# as Dallas.
dallas = City.objects.get(name='Dallas') dallas = City.objects.get(name='Dallas')
ftworth = City.objects.create(name='Fort Worth', state='TX', location=dallas.location)
# Count annotation should be 2 for the Dallas location now. # Count annotation should be 2 for the Dallas location now.
loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id) loc = Location.objects.annotate(num_cities=Count('city')).get(id=dallas.location.id)
@ -243,18 +234,9 @@ class RelatedGeoModelTest(unittest.TestCase):
def test12b_count(self): def test12b_count(self):
"Testing `Count` aggregate use with the `GeoManager` on non geo-fields. See #11087." "Testing `Count` aggregate use with the `GeoManager` on non geo-fields. See #11087."
# Creating some data for the Book/Author non-geo models that
# use GeoManager. See #11087.
tp = Author.objects.create(name='Trevor Paglen')
Book.objects.create(title='Torture Taxi', author=tp)
Book.objects.create(title='I Could Tell You But Then You Would Have to be Destroyed by Me', author=tp)
Book.objects.create(title='Blank Spots on the Map', author=tp)
wp = Author.objects.create(name='William Patry')
Book.objects.create(title='Patry on Copyright', author=wp)
# Should only be one author (Trevor Paglen) returned by this query, and # Should only be one author (Trevor Paglen) returned by this query, and
# the annotation should have 3 for the number of books. Also testing # the annotation should have 3 for the number of books, see #11087.
# with a `GeoValuesQuerySet` (see #11489). # Also testing with a `GeoValuesQuerySet`, see #11489.
qs = Author.objects.annotate(num_books=Count('books')).filter(num_books__gt=1) qs = Author.objects.annotate(num_books=Count('books')).filter(num_books__gt=1)
vqs = Author.objects.values('name').annotate(num_books=Count('books')).filter(num_books__gt=1) vqs = Author.objects.values('name').annotate(num_books=Count('books')).filter(num_books__gt=1)
self.assertEqual(1, len(qs)) self.assertEqual(1, len(qs))
@ -280,7 +262,7 @@ class RelatedGeoModelTest(unittest.TestCase):
# SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN # SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN
# "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id") # "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id")
# WHERE "relatedapp_city"."state" = 'TX'; # WHERE "relatedapp_city"."state" = 'TX';
ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)') ref_geom = GEOSGeometry('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)')
c1 = City.objects.filter(state='TX').collect(field_name='location__point') c1 = City.objects.filter(state='TX').collect(field_name='location__point')
c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect'] c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect']
@ -298,10 +280,5 @@ class RelatedGeoModelTest(unittest.TestCase):
# keyword. The TypeError is swallowed if QuerySet is actually # keyword. The TypeError is swallowed if QuerySet is actually
# evaluated as list generation swallows TypeError in CPython. # evaluated as list generation swallows TypeError in CPython.
sql = str(qs.query) sql = str(qs.query)
# TODO: Related tests for KML, GML, and distance lookups.
def suite(): # TODO: Related tests for KML, GML, and distance lookups.
s = unittest.TestSuite()
s.addTest(unittest.makeSuite(RelatedGeoModelTest))
return s

View File

@ -1,6 +0,0 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^geoapp/', include('django.contrib.gis.tests.geoapp.urls')),
)