Fixed #12991 -- Added unittest2 support. Thanks to PaulM for the draft patch, and to Luke, Karen, Justin, Alex, Łukasz Rekucki, and Chuck Harmston for their help testing and reviewing the final patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@14139 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
1070c57b83
commit
121d2e3678
|
@ -1,7 +1,8 @@
|
|||
import unittest
|
||||
import fields
|
||||
from django.contrib.admindocs import views
|
||||
from django.db.models import fields as builtin_fields
|
||||
from django.utils import unittest
|
||||
|
||||
import fields
|
||||
|
||||
|
||||
class TestFieldType(unittest.TestCase):
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import unittest
|
||||
from django import forms
|
||||
from django.contrib.formtools import preview, wizard, utils
|
||||
from django import http
|
||||
from django.contrib.formtools import preview, wizard, utils
|
||||
from django.test import TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
success_string = "Done was called!"
|
||||
|
||||
|
@ -115,7 +115,7 @@ class SecurityHashTests(unittest.TestCase):
|
|||
hash1 = utils.security_hash(None, f1)
|
||||
hash2 = utils.security_hash(None, f2)
|
||||
self.assertEqual(hash1, hash2)
|
||||
|
||||
|
||||
def test_empty_permitted(self):
|
||||
"""
|
||||
Regression test for #10643: the security hash should allow forms with
|
||||
|
|
|
@ -22,8 +22,8 @@ class SpatiaLiteCreation(DatabaseCreation):
|
|||
self.connection.close()
|
||||
|
||||
self.connection.settings_dict["NAME"] = test_database_name
|
||||
can_rollback = self._rollback_works()
|
||||
self.connection.settings_dict["SUPPORTS_TRANSACTIONS"] = can_rollback
|
||||
# Confirm the feature set of the test database
|
||||
self.connection.features.confirm()
|
||||
# Need to load the SpatiaLite initialization SQL before running `syncdb`.
|
||||
self.load_spatialite_sql()
|
||||
call_command('syncdb', verbosity=verbosity, interactive=False, database=self.connection.alias)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Module for executing all of the GDAL tests. None
|
||||
of these tests require the use of the database.
|
||||
"""
|
||||
from unittest import TestSuite, TextTestRunner
|
||||
from django.utils.unittest import TestSuite, TextTestRunner
|
||||
|
||||
# Importing the GDAL test modules.
|
||||
import test_driver, test_ds, test_envelope, test_geom, test_srs
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import unittest
|
||||
from django.contrib.gis.gdal import Envelope, OGRException
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class TestPoint(object):
|
||||
def __init__(self, x, y):
|
||||
|
@ -8,8 +9,8 @@ class TestPoint(object):
|
|||
|
||||
class EnvelopeTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.e = Envelope(0, 0, 5, 5)
|
||||
def setUp(self):
|
||||
self.e = Envelope(0, 0, 5, 5)
|
||||
|
||||
def test01_init(self):
|
||||
"Testing Envelope initilization."
|
||||
|
@ -23,10 +24,10 @@ class EnvelopeTest(unittest.TestCase):
|
|||
self.assertRaises(OGRException, Envelope, ())
|
||||
self.assertRaises(ValueError, Envelope, 0, 'a', 5, 5)
|
||||
self.assertRaises(TypeError, Envelope, u'foo')
|
||||
self.assertRaises(OGRException, Envelope, (1, 1, 0, 0))
|
||||
try:
|
||||
Envelope(0, 0, 0, 0)
|
||||
except OGRException:
|
||||
self.assertRaises(OGRException, Envelope, (1, 1, 0, 0))
|
||||
try:
|
||||
Envelope(0, 0, 0, 0)
|
||||
except OGRException:
|
||||
self.fail("shouldn't raise an exception for min_x == max_x or min_y == max_y")
|
||||
|
||||
def test02_properties(self):
|
||||
|
@ -49,41 +50,41 @@ class EnvelopeTest(unittest.TestCase):
|
|||
self.assertEqual(e1, e2)
|
||||
self.assertEqual((0.523, 0.217, 253.23, 523.69), e1)
|
||||
|
||||
def test04_expand_to_include_pt_2_params(self):
|
||||
"Testing Envelope expand_to_include -- point as two parameters."
|
||||
self.e.expand_to_include(2, 6)
|
||||
self.assertEqual((0, 0, 5, 6), self.e)
|
||||
self.e.expand_to_include(-1, -1)
|
||||
self.assertEqual((-1, -1, 5, 6), self.e)
|
||||
|
||||
def test05_expand_to_include_pt_2_tuple(self):
|
||||
"Testing Envelope expand_to_include -- point as a single 2-tuple parameter."
|
||||
self.e.expand_to_include((10, 10))
|
||||
self.assertEqual((0, 0, 10, 10), self.e)
|
||||
self.e.expand_to_include((-10, -10))
|
||||
self.assertEqual((-10, -10, 10, 10), self.e)
|
||||
def test04_expand_to_include_pt_2_params(self):
|
||||
"Testing Envelope expand_to_include -- point as two parameters."
|
||||
self.e.expand_to_include(2, 6)
|
||||
self.assertEqual((0, 0, 5, 6), self.e)
|
||||
self.e.expand_to_include(-1, -1)
|
||||
self.assertEqual((-1, -1, 5, 6), self.e)
|
||||
|
||||
def test06_expand_to_include_extent_4_params(self):
|
||||
"Testing Envelope expand_to_include -- extent as 4 parameters."
|
||||
self.e.expand_to_include(-1, 1, 3, 7)
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test06_expand_to_include_extent_4_tuple(self):
|
||||
"Testing Envelope expand_to_include -- extent as a single 4-tuple parameter."
|
||||
self.e.expand_to_include((-1, 1, 3, 7))
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test07_expand_to_include_envelope(self):
|
||||
"Testing Envelope expand_to_include with Envelope as parameter."
|
||||
self.e.expand_to_include(Envelope(-1, 1, 3, 7))
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test08_expand_to_include_point(self):
|
||||
"Testing Envelope expand_to_include with Point as parameter."
|
||||
self.e.expand_to_include(TestPoint(-1, 1))
|
||||
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 test05_expand_to_include_pt_2_tuple(self):
|
||||
"Testing Envelope expand_to_include -- point as a single 2-tuple parameter."
|
||||
self.e.expand_to_include((10, 10))
|
||||
self.assertEqual((0, 0, 10, 10), self.e)
|
||||
self.e.expand_to_include((-10, -10))
|
||||
self.assertEqual((-10, -10, 10, 10), self.e)
|
||||
|
||||
def test06_expand_to_include_extent_4_params(self):
|
||||
"Testing Envelope expand_to_include -- extent as 4 parameters."
|
||||
self.e.expand_to_include(-1, 1, 3, 7)
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test06_expand_to_include_extent_4_tuple(self):
|
||||
"Testing Envelope expand_to_include -- extent as a single 4-tuple parameter."
|
||||
self.e.expand_to_include((-1, 1, 3, 7))
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test07_expand_to_include_envelope(self):
|
||||
"Testing Envelope expand_to_include with Envelope as parameter."
|
||||
self.e.expand_to_include(Envelope(-1, 1, 3, 7))
|
||||
self.assertEqual((-1, 0, 5, 7), self.e)
|
||||
|
||||
def test08_expand_to_include_point(self):
|
||||
"Testing Envelope expand_to_include with Point as parameter."
|
||||
self.e.expand_to_include(TestPoint(-1, 1))
|
||||
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()
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import unittest
|
||||
from django.contrib.gis.gdal import OGRGeometry, OGRGeomType, \
|
||||
OGRException, OGRIndexError, SpatialReference, CoordTransform, \
|
||||
gdal_version
|
||||
from django.contrib.gis.tests.geometries import *
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class OGRGeomTest(unittest.TestCase):
|
||||
"This tests the OGR Geometry."
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import unittest
|
||||
from django.contrib.gis.gdal import SpatialReference, CoordTransform, OGRException, SRSException
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class TestSRS:
|
||||
def __init__(self, wkt, **kwargs):
|
||||
|
@ -79,7 +80,7 @@ class SpatialRefTest(unittest.TestCase):
|
|||
srs1 = SpatialReference(s.wkt)
|
||||
srs2 = SpatialReference(s.proj)
|
||||
self.assertEqual(srs1.proj, srs2.proj)
|
||||
|
||||
|
||||
def test05_epsg(self):
|
||||
"Test EPSG import."
|
||||
for s in srlist:
|
||||
|
@ -159,7 +160,7 @@ class SpatialRefTest(unittest.TestCase):
|
|||
self.assertEqual(4326, int(s1['AUTHORITY', 1]))
|
||||
#for i in range(7): self.assertEqual(0, int(s1['TOWGS84', i]))
|
||||
self.assertEqual(None, s1['FOOBAR'])
|
||||
|
||||
|
||||
def suite():
|
||||
s = unittest.TestSuite()
|
||||
s.addTest(unittest.makeSuite(SpatialRefTest))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
GEOS Testing module.
|
||||
"""
|
||||
from unittest import TestSuite, TextTestRunner
|
||||
from django.utils.unittest import TestSuite, TextTestRunner
|
||||
import test_geos, test_io, test_geos_mutation, test_mutable_list
|
||||
|
||||
test_suites = [
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# Copyright (c) 2008-2009 Aryeh Leib Taurog, all rights reserved.
|
||||
# Modified from original contribution by Aryeh Leib Taurog, which was
|
||||
# released under the New BSD license.
|
||||
import unittest
|
||||
|
||||
import django.utils.copycompat as copy
|
||||
|
||||
from django.contrib.gis.geos import *
|
||||
from django.contrib.gis.geos.error import GEOSIndexError
|
||||
from django.utils import unittest
|
||||
|
||||
def getItem(o,i): return o[i]
|
||||
def delItem(o,i): del o[i]
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
#
|
||||
# Modified from original contribution by Aryeh Leib Taurog, which was
|
||||
# released under the New BSD license.
|
||||
import unittest
|
||||
from django.contrib.gis.geos.mutable_list import ListMixin
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class UserListA(ListMixin):
|
||||
_mytype = tuple
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import sys
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from django.db.models import get_app
|
||||
from django.test.simple import build_suite, DjangoTestSuiteRunner
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
def run_tests(*args, **kwargs):
|
||||
from django.test.simple import run_tests as base_run_tests
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import unittest
|
||||
from xml.dom import minidom
|
||||
|
||||
from django.test import Client
|
||||
from django.utils import unittest
|
||||
|
||||
from models import City
|
||||
|
||||
|
||||
class GeoFeedTest(unittest.TestCase):
|
||||
client = Client()
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import unittest, zipfile, cStringIO
|
||||
import cStringIO
|
||||
from xml.dom import minidom
|
||||
import zipfile
|
||||
|
||||
from django.test import Client
|
||||
from django.utils import unittest
|
||||
|
||||
from models import City, Country
|
||||
|
||||
|
||||
class GeoSitemapTest(unittest.TestCase):
|
||||
client = Client()
|
||||
|
||||
|
@ -30,7 +34,7 @@ class GeoSitemapTest(unittest.TestCase):
|
|||
urlset = doc.firstChild
|
||||
self.assertEqual(urlset.getAttribute(u'xmlns'), u'http://www.sitemaps.org/schemas/sitemap/0.9')
|
||||
self.assertEqual(urlset.getAttribute(u'xmlns:geo'), u'http://www.google.com/geo/schemas/sitemap/1.0')
|
||||
|
||||
|
||||
urls = urlset.getElementsByTagName('url')
|
||||
self.assertEqual(2, len(urls)) # Should only be 2 sitemaps.
|
||||
for url in urls:
|
||||
|
@ -42,7 +46,7 @@ class GeoSitemapTest(unittest.TestCase):
|
|||
|
||||
# Getting the relative URL since we don't have a real site.
|
||||
kml_url = url.getElementsByTagName('loc')[0].childNodes[0].data.split('http://example.com')[1]
|
||||
|
||||
|
||||
if kml_type == 'kml':
|
||||
kml_doc = minidom.parseString(self.client.get(kml_url).content)
|
||||
elif kml_type == 'kmz':
|
||||
|
@ -52,7 +56,7 @@ class GeoSitemapTest(unittest.TestCase):
|
|||
self.assertEqual(1, len(zf.filelist))
|
||||
self.assertEqual('doc.kml', zf.filelist[0].filename)
|
||||
kml_doc = minidom.parseString(zf.read('doc.kml'))
|
||||
|
||||
|
||||
# Ensuring the correct number of placemarks are in the KML doc.
|
||||
if 'city' in kml_url:
|
||||
model = City
|
||||
|
@ -65,7 +69,7 @@ class GeoSitemapTest(unittest.TestCase):
|
|||
from feeds import feed_dict
|
||||
|
||||
doc = minidom.parseString(self.client.get('/geoapp/sitemaps/georss.xml').content)
|
||||
|
||||
|
||||
# Ensuring the right sitemaps namespaces are present.
|
||||
urlset = doc.firstChild
|
||||
self.assertEqual(urlset.getAttribute(u'xmlns'), u'http://www.sitemaps.org/schemas/sitemap/0.9')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import unittest
|
||||
from decimal import Decimal
|
||||
|
||||
from django.utils import unittest
|
||||
from django.utils.copycompat import copy
|
||||
|
||||
from django.contrib.gis.gdal import DataSource
|
||||
|
@ -15,9 +15,9 @@ city_shp = os.path.join(shp_path, 'cities', 'cities.shp')
|
|||
co_shp = os.path.join(shp_path, 'counties', 'counties.shp')
|
||||
inter_shp = os.path.join(shp_path, 'interstates', 'interstates.shp')
|
||||
|
||||
# Dictionaries to hold what's expected in the county shapefile.
|
||||
# Dictionaries to hold what's expected in the county shapefile.
|
||||
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']
|
||||
|
||||
class LayerMapTest(unittest.TestCase):
|
||||
|
@ -98,7 +98,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
|
||||
# Two interstate should have imported correctly.
|
||||
self.assertEqual(2, Interstate.objects.count())
|
||||
|
||||
|
||||
# Verifying the values in the layer w/the model.
|
||||
ds = DataSource(inter_shp)
|
||||
|
||||
|
@ -106,7 +106,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
valid_feats = ds[0][:2]
|
||||
for feat in valid_feats:
|
||||
istate = Interstate.objects.get(name=feat['Name'].value)
|
||||
|
||||
|
||||
if feat.fid == 0:
|
||||
self.assertEqual(Decimal(str(feat['Length'])), istate.length)
|
||||
elif feat.fid == 1:
|
||||
|
@ -125,7 +125,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
c = County.objects.get(name=name)
|
||||
self.assertEqual(n, len(c.mpoly))
|
||||
self.assertEqual(st, c.state.name) # Checking ForeignKey mapping.
|
||||
|
||||
|
||||
# Multiple records because `unique` was not set.
|
||||
if county_feat:
|
||||
qs = CountyFeat.objects.filter(name=name)
|
||||
|
@ -137,7 +137,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
try:
|
||||
# Telling LayerMapping that we want no transformations performed on the data.
|
||||
lm = LayerMapping(County, co_shp, co_mapping, transform=False)
|
||||
|
||||
|
||||
# Specifying the source spatial reference system via the `source_srs` keyword.
|
||||
lm = LayerMapping(County, co_shp, co_mapping, source_srs=4269)
|
||||
lm = LayerMapping(County, co_shp, co_mapping, source_srs='NAD83')
|
||||
|
@ -147,7 +147,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
lm = LayerMapping(County, co_shp, co_mapping, transform=False, unique=arg)
|
||||
except:
|
||||
self.fail('No exception should be raised for proper use of keywords.')
|
||||
|
||||
|
||||
# Testing invalid params for the `unique` keyword.
|
||||
for e, arg in ((TypeError, 5.0), (ValueError, 'foobar'), (ValueError, ('name', 'mpolygon'))):
|
||||
self.assertRaises(e, LayerMapping, County, co_shp, co_mapping, transform=False, unique=arg)
|
||||
|
@ -177,11 +177,11 @@ class LayerMapTest(unittest.TestCase):
|
|||
# are not collections will be converted into them. For example,
|
||||
# a Point column would be converted to MultiPoint. Other things being done
|
||||
# w/the keyword args:
|
||||
# `transform=False`: Specifies that no transform is to be done; this
|
||||
# `transform=False`: Specifies that no transform is to be done; this
|
||||
# has the effect of ignoring the spatial reference check (because the
|
||||
# county shapefile does not have implicit spatial reference info).
|
||||
#
|
||||
# `unique='name'`: Creates models on the condition that they have
|
||||
#
|
||||
# `unique='name'`: Creates models on the condition that they have
|
||||
# unique county names; geometries from each feature however will be
|
||||
# appended to the geometry collection of the unique model. Thus,
|
||||
# all of the various islands in Honolulu county will be in in one
|
||||
|
@ -201,7 +201,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
"Tests the `fid_range` keyword and the `step` keyword of .save()."
|
||||
# Function for clearing out all the counties before testing.
|
||||
def clear_counties(): County.objects.all().delete()
|
||||
|
||||
|
||||
# Initializing the LayerMapping object to use in these tests.
|
||||
lm = LayerMapping(County, co_shp, co_mapping, transform=False, unique='name')
|
||||
|
||||
|
@ -213,9 +213,9 @@ class LayerMapTest(unittest.TestCase):
|
|||
|
||||
# Step keyword should not be allowed w/`fid_range`.
|
||||
fr = (3, 5) # layer[3:5]
|
||||
self.assertRaises(LayerMapError, lm.save, fid_range=fr, step=10)
|
||||
self.assertRaises(LayerMapError, lm.save, fid_range=fr, step=10)
|
||||
lm.save(fid_range=fr)
|
||||
|
||||
|
||||
# Features IDs 3 & 4 are for Galveston County, Texas -- only
|
||||
# one model is returned because the `unique` keyword was set.
|
||||
qs = County.objects.all()
|
||||
|
@ -229,9 +229,9 @@ class LayerMapTest(unittest.TestCase):
|
|||
lm.save(fid_range=slice(None, 1), silent=True, strict=True) # layer[:1]
|
||||
|
||||
# Only Pueblo & Honolulu counties should be present because of
|
||||
# the `unique` keyword. Have to set `order_by` on this QuerySet
|
||||
# the `unique` keyword. Have to set `order_by` on this QuerySet
|
||||
# or else MySQL will return a different ordering than the other dbs.
|
||||
qs = County.objects.order_by('name')
|
||||
qs = County.objects.order_by('name')
|
||||
self.assertEqual(2, qs.count())
|
||||
hi, co = tuple(qs)
|
||||
hi_idx, co_idx = tuple(map(NAMES.index, ('Honolulu', 'Pueblo')))
|
||||
|
@ -265,7 +265,7 @@ class LayerMapTest(unittest.TestCase):
|
|||
|
||||
self.assertEqual(6, ICity1.objects.count())
|
||||
self.assertEqual(3, ICity2.objects.count())
|
||||
|
||||
|
||||
def suite():
|
||||
s = unittest.TestSuite()
|
||||
s.addTest(unittest.makeSuite(LayerMapTest))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import unittest
|
||||
|
||||
from django.forms import ValidationError
|
||||
from django.contrib.gis import forms
|
||||
from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class GeometryFieldTest(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
"""
|
||||
Distance and Area objects to allow for sensible and convienient calculation
|
||||
Distance and Area objects to allow for sensible and convienient calculation
|
||||
and conversions. Here are some tests.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from django.contrib.gis.measure import Distance, Area, D, A
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class DistanceTest(unittest.TestCase):
|
||||
"Testing the Distance object"
|
||||
|
@ -30,7 +31,7 @@ class DistanceTest(unittest.TestCase):
|
|||
self.assertEqual(d.m, 1.0)
|
||||
self.assertEqual(d.mm, 1000.0)
|
||||
|
||||
|
||||
|
||||
def testInitInvalid(self):
|
||||
"Testing initialisation from invalid units"
|
||||
self.assertRaises(AttributeError, D, banana=100)
|
||||
|
@ -40,7 +41,7 @@ class DistanceTest(unittest.TestCase):
|
|||
d = D(m=100)
|
||||
self.assertEqual(d.km, 0.1)
|
||||
self.assertAlmostEqual(d.ft, 328.084, 3)
|
||||
|
||||
|
||||
def testAccessInvalid(self):
|
||||
"Testing access in invalid units"
|
||||
d = D(m=100)
|
||||
|
@ -55,12 +56,12 @@ class DistanceTest(unittest.TestCase):
|
|||
self.assertEqual(d3.m, 300)
|
||||
d3 += d1
|
||||
self.assertEqual(d3.m, 400)
|
||||
|
||||
|
||||
d4 = d1 - d2
|
||||
self.assertEqual(d4.m, -100)
|
||||
d4 -= d1
|
||||
self.assertEqual(d4.m, -200)
|
||||
|
||||
|
||||
try:
|
||||
d5 = d1 + 1
|
||||
except TypeError, e:
|
||||
|
@ -88,7 +89,7 @@ class DistanceTest(unittest.TestCase):
|
|||
pass
|
||||
else:
|
||||
self.fail('Distance -= number should raise TypeError')
|
||||
|
||||
|
||||
def testMultiplication(self):
|
||||
"Test multiplication & division"
|
||||
d1 = D(m=100)
|
||||
|
@ -99,12 +100,12 @@ class DistanceTest(unittest.TestCase):
|
|||
self.assertEqual(d3.m, 200)
|
||||
d3 *= 5
|
||||
self.assertEqual(d3.m, 1000)
|
||||
|
||||
|
||||
d4 = d1 / 2
|
||||
self.assertEqual(d4.m, 50)
|
||||
d4 /= 5
|
||||
self.assertEqual(d4.m, 10)
|
||||
|
||||
|
||||
a5 = d1 * D(m=10)
|
||||
self.assert_(isinstance(a5, Area))
|
||||
self.assertEqual(a5.sq_m, 100*10)
|
||||
|
@ -115,7 +116,7 @@ class DistanceTest(unittest.TestCase):
|
|||
pass
|
||||
else:
|
||||
self.fail('Distance *= Distance should raise TypeError')
|
||||
|
||||
|
||||
try:
|
||||
d5 = d1 / D(m=1)
|
||||
except TypeError, e:
|
||||
|
@ -143,23 +144,23 @@ class DistanceTest(unittest.TestCase):
|
|||
self.assertEqual(d5._default_unit, 'm')
|
||||
d6 = d1 / 2
|
||||
self.assertEqual(d6._default_unit, 'm')
|
||||
|
||||
|
||||
def testComparisons(self):
|
||||
"Testing comparisons"
|
||||
d1 = D(m=100)
|
||||
d2 = D(km=1)
|
||||
d3 = D(km=0)
|
||||
|
||||
|
||||
self.assert_(d2 > d1)
|
||||
self.assert_(d1 == d1)
|
||||
self.assert_(d1 < d2)
|
||||
self.failIf(d3)
|
||||
|
||||
|
||||
def testUnitsStr(self):
|
||||
"Testing conversion to strings"
|
||||
d1 = D(m=100)
|
||||
d2 = D(km=3.5)
|
||||
|
||||
|
||||
self.assertEqual(str(d1), '100.0 m')
|
||||
self.assertEqual(str(d2), '3.5 km')
|
||||
self.assertEqual(repr(d1), 'Distance(m=100.0)')
|
||||
|
@ -185,7 +186,7 @@ class AreaTest(unittest.TestCase):
|
|||
|
||||
a = A(sq_mi=100)
|
||||
self.assertEqual(a.sq_m, 258998811.0336)
|
||||
|
||||
|
||||
def testInitInvaliA(self):
|
||||
"Testing initialisation from invalid units"
|
||||
self.assertRaises(AttributeError, A, banana=100)
|
||||
|
@ -195,7 +196,7 @@ class AreaTest(unittest.TestCase):
|
|||
a = A(sq_m=100)
|
||||
self.assertEqual(a.sq_km, 0.0001)
|
||||
self.assertAlmostEqual(a.sq_ft, 1076.391, 3)
|
||||
|
||||
|
||||
def testAccessInvaliA(self):
|
||||
"Testing access in invalid units"
|
||||
a = A(sq_m=100)
|
||||
|
@ -210,12 +211,12 @@ class AreaTest(unittest.TestCase):
|
|||
self.assertEqual(a3.sq_m, 300)
|
||||
a3 += a1
|
||||
self.assertEqual(a3.sq_m, 400)
|
||||
|
||||
|
||||
a4 = a1 - a2
|
||||
self.assertEqual(a4.sq_m, -100)
|
||||
a4 -= a1
|
||||
self.assertEqual(a4.sq_m, -200)
|
||||
|
||||
|
||||
try:
|
||||
a5 = a1 + 1
|
||||
except TypeError, e:
|
||||
|
@ -243,7 +244,7 @@ class AreaTest(unittest.TestCase):
|
|||
pass
|
||||
else:
|
||||
self.fail('Area -= number should raise TypeError')
|
||||
|
||||
|
||||
def testMultiplication(self):
|
||||
"Test multiplication & division"
|
||||
a1 = A(sq_m=100)
|
||||
|
@ -254,12 +255,12 @@ class AreaTest(unittest.TestCase):
|
|||
self.assertEqual(a3.sq_m, 200)
|
||||
a3 *= 5
|
||||
self.assertEqual(a3.sq_m, 1000)
|
||||
|
||||
|
||||
a4 = a1 / 2
|
||||
self.assertEqual(a4.sq_m, 50)
|
||||
a4 /= 5
|
||||
self.assertEqual(a4.sq_m, 10)
|
||||
|
||||
|
||||
try:
|
||||
a5 = a1 * A(sq_m=1)
|
||||
except TypeError, e:
|
||||
|
@ -273,7 +274,7 @@ class AreaTest(unittest.TestCase):
|
|||
pass
|
||||
else:
|
||||
self.fail('Area *= Area should raise TypeError')
|
||||
|
||||
|
||||
try:
|
||||
a5 = a1 / A(sq_m=1)
|
||||
except TypeError, e:
|
||||
|
@ -301,23 +302,23 @@ class AreaTest(unittest.TestCase):
|
|||
self.assertEqual(a5._default_unit, 'sq_m')
|
||||
a6 = a1 / 2
|
||||
self.assertEqual(a6._default_unit, 'sq_m')
|
||||
|
||||
|
||||
def testComparisons(self):
|
||||
"Testing comparisons"
|
||||
a1 = A(sq_m=100)
|
||||
a2 = A(sq_km=1)
|
||||
a3 = A(sq_km=0)
|
||||
|
||||
|
||||
self.assert_(a2 > a1)
|
||||
self.assert_(a1 == a1)
|
||||
self.assert_(a1 < a2)
|
||||
self.failIf(a3)
|
||||
|
||||
|
||||
def testUnitsStr(self):
|
||||
"Testing conversion to strings"
|
||||
a1 = A(sq_m=100)
|
||||
a2 = A(sq_km=3.5)
|
||||
|
||||
|
||||
self.assertEqual(str(a1), '100.0 sq_m')
|
||||
self.assertEqual(str(a2), '3.5 sq_km')
|
||||
self.assertEqual(repr(a1), 'Area(sq_m=100.0)')
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import unittest
|
||||
|
||||
from django.db import connection
|
||||
from django.contrib.gis.tests.utils import mysql, no_mysql, oracle, postgis, spatialite
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
test_srs = ({'srid' : 4326,
|
||||
'auth_name' : ('EPSG', True),
|
||||
|
@ -9,7 +9,7 @@ test_srs = ({'srid' : 4326,
|
|||
'srtext' : 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]',
|
||||
'srtext14' : 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]',
|
||||
'proj4' : '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ',
|
||||
'spheroid' : 'WGS 84', 'name' : 'WGS 84',
|
||||
'spheroid' : 'WGS 84', 'name' : 'WGS 84',
|
||||
'geographic' : True, 'projected' : False, 'spatialite' : True,
|
||||
'ellipsoid' : (6378137.0, 6356752.3, 298.257223563), # From proj's "cs2cs -le" and Wikipedia (semi-minor only)
|
||||
'eprec' : (1, 1, 9),
|
||||
|
@ -49,7 +49,7 @@ class SpatialRefSysTest(unittest.TestCase):
|
|||
auth_name, oracle_flag = sd['auth_name']
|
||||
if postgis or (oracle and oracle_flag):
|
||||
self.assertEqual(True, srs.auth_name.startswith(auth_name))
|
||||
|
||||
|
||||
self.assertEqual(sd['auth_srid'], srs.auth_srid)
|
||||
|
||||
# No proj.4 and different srtext on oracle backends :(
|
||||
|
|
|
@ -1,77 +1,90 @@
|
|||
# Quick tests for the markup templatetags (django.contrib.markup)
|
||||
|
||||
import re
|
||||
import unittest
|
||||
|
||||
from django.template import Template, Context, add_to_builtins
|
||||
from django.utils import unittest
|
||||
from django.utils.html import escape
|
||||
|
||||
add_to_builtins('django.contrib.markup.templatetags.markup')
|
||||
|
||||
class Templates(unittest.TestCase):
|
||||
def test_textile(self):
|
||||
try:
|
||||
import textile
|
||||
except ImportError:
|
||||
textile = None
|
||||
try:
|
||||
import textile
|
||||
except ImportError:
|
||||
textile = None
|
||||
|
||||
textile_content = """Paragraph 1
|
||||
try:
|
||||
import markdown
|
||||
except ImportError:
|
||||
markdown = None
|
||||
|
||||
try:
|
||||
import docutils
|
||||
except ImportError:
|
||||
docutils = None
|
||||
|
||||
class Templates(unittest.TestCase):
|
||||
|
||||
textile_content = """Paragraph 1
|
||||
|
||||
Paragraph 2 with "quotes" and @code@"""
|
||||
|
||||
t = Template("{{ textile_content|textile }}")
|
||||
rendered = t.render(Context(locals())).strip()
|
||||
if textile:
|
||||
self.assertEqual(rendered.replace('\t', ''), """<p>Paragraph 1</p>
|
||||
|
||||
<p>Paragraph 2 with “quotes” and <code>code</code></p>""")
|
||||
else:
|
||||
self.assertEqual(rendered, escape(textile_content))
|
||||
|
||||
def test_markdown(self):
|
||||
try:
|
||||
import markdown
|
||||
except ImportError:
|
||||
markdown = None
|
||||
|
||||
markdown_content = """Paragraph 1
|
||||
markdown_content = """Paragraph 1
|
||||
|
||||
## An h2"""
|
||||
|
||||
t = Template("{{ markdown_content|markdown }}")
|
||||
rendered = t.render(Context(locals())).strip()
|
||||
if markdown:
|
||||
pattern = re.compile("""<p>Paragraph 1\s*</p>\s*<h2>\s*An h2</h2>""")
|
||||
self.assert_(pattern.match(rendered))
|
||||
else:
|
||||
self.assertEqual(rendered, markdown_content)
|
||||
|
||||
def test_docutils(self):
|
||||
try:
|
||||
import docutils
|
||||
except ImportError:
|
||||
docutils = None
|
||||
|
||||
rest_content = """Paragraph 1
|
||||
rest_content = """Paragraph 1
|
||||
|
||||
Paragraph 2 with a link_
|
||||
|
||||
.. _link: http://www.example.com/"""
|
||||
|
||||
|
||||
@unittest.skipUnless(textile, 'texttile not installed')
|
||||
def test_textile(self):
|
||||
t = Template("{{ textile_content|textile }}")
|
||||
rendered = t.render(Context({'textile_content':self.textile_content})).strip()
|
||||
self.assertEqual(rendered.replace('\t', ''), """<p>Paragraph 1</p>
|
||||
|
||||
<p>Paragraph 2 with “quotes” and <code>code</code></p>""")
|
||||
|
||||
@unittest.skipIf(textile, 'texttile is installed')
|
||||
def test_no_textile(self):
|
||||
t = Template("{{ textile_content|textile }}")
|
||||
rendered = t.render(Context({'textile_content':self.textile_content})).strip()
|
||||
self.assertEqual(rendered, escape(self.textile_content))
|
||||
|
||||
@unittest.skipUnless(markdown, 'markdown not installed')
|
||||
def test_markdown(self):
|
||||
t = Template("{{ markdown_content|markdown }}")
|
||||
rendered = t.render(Context({'markdown_content':self.markdown_content})).strip()
|
||||
pattern = re.compile("""<p>Paragraph 1\s*</p>\s*<h2>\s*An h2</h2>""")
|
||||
self.assertTrue(pattern.match(rendered))
|
||||
|
||||
@unittest.skipIf(markdown, 'markdown is installed')
|
||||
def test_no_markdown(self):
|
||||
t = Template("{{ markdown_content|markdown }}")
|
||||
rendered = t.render(Context({'markdown_content':self.markdown_content})).strip()
|
||||
self.assertEqual(rendered, self.markdown_content)
|
||||
|
||||
@unittest.skipUnless(docutils, 'docutils not installed')
|
||||
def test_docutils(self):
|
||||
t = Template("{{ rest_content|restructuredtext }}")
|
||||
rendered = t.render(Context(locals())).strip()
|
||||
if docutils:
|
||||
# Different versions of docutils return slightly different HTML
|
||||
try:
|
||||
# Docutils v0.4 and earlier
|
||||
self.assertEqual(rendered, """<p>Paragraph 1</p>
|
||||
rendered = t.render(Context({'rest_content':self.rest_content})).strip()
|
||||
# Different versions of docutils return slightly different HTML
|
||||
try:
|
||||
# Docutils v0.4 and earlier
|
||||
self.assertEqual(rendered, """<p>Paragraph 1</p>
|
||||
<p>Paragraph 2 with a <a class="reference" href="http://www.example.com/">link</a></p>""")
|
||||
except AssertionError, e:
|
||||
# Docutils from SVN (which will become 0.5)
|
||||
self.assertEqual(rendered, """<p>Paragraph 1</p>
|
||||
except AssertionError, e:
|
||||
# Docutils from SVN (which will become 0.5)
|
||||
self.assertEqual(rendered, """<p>Paragraph 1</p>
|
||||
<p>Paragraph 2 with a <a class="reference external" href="http://www.example.com/">link</a></p>""")
|
||||
else:
|
||||
self.assertEqual(rendered, rest_content)
|
||||
|
||||
@unittest.skipIf(docutils, 'docutils is installed')
|
||||
def test_no_docutils(self):
|
||||
t = Template("{{ rest_content|restructuredtext }}")
|
||||
rendered = t.render(Context({'rest_content':self.rest_content})).strip()
|
||||
self.assertEqual(rendered, self.rest_content)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import unittest
|
||||
from django import http
|
||||
from django.contrib.messages.middleware import MessageMiddleware
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class MiddlewareTest(unittest.TestCase):
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from datetime import datetime, timedelta
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.backends.db import SessionStore as DatabaseSession
|
||||
from django.contrib.sessions.backends.cache import SessionStore as CacheSession
|
||||
|
@ -8,9 +11,7 @@ from django.contrib.sessions.backends.base import SessionBase
|
|||
from django.contrib.sessions.models import Session
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.test import TestCase
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
class SessionTestsMixin(object):
|
||||
|
|
|
@ -20,6 +20,7 @@ class BaseDatabaseWrapper(local):
|
|||
self.queries = []
|
||||
self.settings_dict = settings_dict
|
||||
self.alias = alias
|
||||
self.vendor = 'unknown'
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.settings_dict == other.settings_dict
|
||||
|
@ -87,16 +88,105 @@ class BaseDatabaseFeatures(object):
|
|||
needs_datetime_string_cast = True
|
||||
empty_fetchmany_value = []
|
||||
update_can_self_select = True
|
||||
|
||||
# Does the backend distinguish between '' and None?
|
||||
interprets_empty_strings_as_nulls = False
|
||||
|
||||
can_use_chunked_reads = True
|
||||
can_return_id_from_insert = False
|
||||
uses_autocommit = False
|
||||
uses_savepoints = False
|
||||
|
||||
# If True, don't use integer foreign keys referring to, e.g., positive
|
||||
# integer primary keys.
|
||||
related_fields_match_type = False
|
||||
allow_sliced_subqueries = True
|
||||
|
||||
# Does the default test database allow multiple connections?
|
||||
# Usually an indication that the test database is in-memory
|
||||
test_db_allows_multiple_connections = True
|
||||
|
||||
# Can an object be saved without an explicit primary key?
|
||||
supports_unspecified_pk = False
|
||||
|
||||
# Can a fixture contain forward references? i.e., are
|
||||
# FK constraints checked at the end of transaction, or
|
||||
# at the end of each save operation?
|
||||
supports_forward_references = True
|
||||
|
||||
# Does a dirty transaction need to be rolled back
|
||||
# before the cursor can be used again?
|
||||
requires_rollback_on_dirty_transaction = False
|
||||
|
||||
# Does the backend allow very long model names without error?
|
||||
supports_long_model_names = True
|
||||
|
||||
# Is there a REAL datatype in addition to floats/doubles?
|
||||
has_real_datatype = False
|
||||
supports_subqueries_in_group_by = True
|
||||
supports_bitwise_or = True
|
||||
|
||||
# Do time/datetime fields have microsecond precision?
|
||||
supports_microsecond_precision = True
|
||||
|
||||
# Does the __regex lookup support backreferencing and grouping?
|
||||
supports_regex_backreferencing = True
|
||||
|
||||
# Can date/datetime lookups be performed using a string?
|
||||
supports_date_lookup_using_string = True
|
||||
|
||||
# Can datetimes with timezones be used?
|
||||
supports_timezones = True
|
||||
|
||||
# When performing a GROUP BY, is an ORDER BY NULL required
|
||||
# to remove any ordering?
|
||||
requires_explicit_null_ordering_when_grouping = False
|
||||
|
||||
# Is there a 1000 item limit on query parameters?
|
||||
supports_1000_query_paramters = True
|
||||
|
||||
# Can an object have a primary key of 0? MySQL says No.
|
||||
allows_primary_key_0 = True
|
||||
|
||||
# Features that need to be confirmed at runtime
|
||||
# Cache whether the confirmation has been performed.
|
||||
_confirmed = False
|
||||
supports_transactions = None
|
||||
supports_stddev = None
|
||||
|
||||
def __init__(self, connection):
|
||||
self.connection = connection
|
||||
|
||||
def confirm(self):
|
||||
"Perform manual checks of any database features that might vary between installs"
|
||||
self._confirmed = True
|
||||
self.supports_transactions = self._supports_transactions()
|
||||
self.supports_stddev = self._supports_stddev()
|
||||
|
||||
def _supports_transactions(self):
|
||||
"Confirm support for transactions"
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute('CREATE TABLE ROLLBACK_TEST (X INT)')
|
||||
self.connection._commit()
|
||||
cursor.execute('INSERT INTO ROLLBACK_TEST (X) VALUES (8)')
|
||||
self.connection._rollback()
|
||||
cursor.execute('SELECT COUNT(X) FROM ROLLBACK_TEST')
|
||||
count, = cursor.fetchone()
|
||||
cursor.execute('DROP TABLE ROLLBACK_TEST')
|
||||
self.connection._commit()
|
||||
return count == 0
|
||||
|
||||
def _supports_stddev(self):
|
||||
"Confirm support for STDDEV and related stats functions"
|
||||
class StdDevPop(object):
|
||||
sql_function = 'STDDEV_POP'
|
||||
|
||||
try:
|
||||
self.connection.ops.check_aggregate_support(StdDevPop())
|
||||
except DatabaseError:
|
||||
self.supports_stddev = False
|
||||
|
||||
|
||||
class BaseDatabaseOperations(object):
|
||||
"""
|
||||
This class encapsulates all backend-specific differences, such as the way
|
||||
|
|
|
@ -347,8 +347,9 @@ class BaseDatabaseCreation(object):
|
|||
|
||||
self.connection.close()
|
||||
self.connection.settings_dict["NAME"] = test_database_name
|
||||
can_rollback = self._rollback_works()
|
||||
self.connection.settings_dict["SUPPORTS_TRANSACTIONS"] = can_rollback
|
||||
|
||||
# Confirm the feature set of the test database
|
||||
self.connection.features.confirm()
|
||||
|
||||
# Report syncdb messages at one level lower than that requested.
|
||||
# This ensures we don't get flooded with messages during testing
|
||||
|
@ -405,18 +406,6 @@ class BaseDatabaseCreation(object):
|
|||
|
||||
return test_database_name
|
||||
|
||||
def _rollback_works(self):
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute('CREATE TABLE ROLLBACK_TEST (X INT)')
|
||||
self.connection._commit()
|
||||
cursor.execute('INSERT INTO ROLLBACK_TEST (X) VALUES (8)')
|
||||
self.connection._rollback()
|
||||
cursor.execute('SELECT COUNT(X) FROM ROLLBACK_TEST')
|
||||
count, = cursor.fetchone()
|
||||
cursor.execute('DROP TABLE ROLLBACK_TEST')
|
||||
self.connection._commit()
|
||||
return count == 0
|
||||
|
||||
def destroy_test_db(self, old_database_name, verbosity=1):
|
||||
"""
|
||||
Destroy a test database, prompting the user for confirmation if the
|
||||
|
|
|
@ -42,7 +42,7 @@ class DatabaseWrapper(object):
|
|||
_rollback = ignore
|
||||
|
||||
def __init__(self, settings_dict, alias, *args, **kwargs):
|
||||
self.features = BaseDatabaseFeatures()
|
||||
self.features = BaseDatabaseFeatures(self)
|
||||
self.ops = DatabaseOperations()
|
||||
self.client = DatabaseClient(self)
|
||||
self.creation = BaseDatabaseCreation(self)
|
||||
|
|
|
@ -124,6 +124,14 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
allows_group_by_pk = True
|
||||
related_fields_match_type = True
|
||||
allow_sliced_subqueries = False
|
||||
supports_forward_references = False
|
||||
supports_long_model_names = False
|
||||
supports_microsecond_precision = False
|
||||
supports_regex_backreferencing = False
|
||||
supports_date_lookup_using_string = False
|
||||
supports_timezones = False
|
||||
requires_explicit_null_ordering_when_grouping = True
|
||||
allows_primary_key_0 = False
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
compiler_module = "django.db.backends.mysql.compiler"
|
||||
|
@ -231,7 +239,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return 64
|
||||
|
||||
class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
|
||||
vendor = 'mysql'
|
||||
operators = {
|
||||
'exact': '= %s',
|
||||
'iexact': 'LIKE %s',
|
||||
|
@ -253,7 +261,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
super(DatabaseWrapper, self).__init__(*args, **kwargs)
|
||||
|
||||
self.server_version = None
|
||||
self.features = DatabaseFeatures()
|
||||
self.features = DatabaseFeatures(self)
|
||||
self.ops = DatabaseOperations()
|
||||
self.client = DatabaseClient(self)
|
||||
self.creation = DatabaseCreation(self)
|
||||
|
|
|
@ -50,7 +50,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
uses_savepoints = True
|
||||
can_return_id_from_insert = True
|
||||
allow_sliced_subqueries = False
|
||||
|
||||
supports_subqueries_in_group_by = True
|
||||
supports_timezones = False
|
||||
supports_bitwise_or = False
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
compiler_module = "django.db.backends.oracle.compiler"
|
||||
|
@ -314,7 +316,7 @@ WHEN (new.%(col_name)s IS NULL)
|
|||
|
||||
|
||||
class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
|
||||
vendor = 'oracle'
|
||||
operators = {
|
||||
'exact': '= %s',
|
||||
'iexact': '= UPPER(%s)',
|
||||
|
@ -334,7 +336,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseWrapper, self).__init__(*args, **kwargs)
|
||||
|
||||
self.features = DatabaseFeatures()
|
||||
self.features = DatabaseFeatures(self)
|
||||
self.ops = DatabaseOperations()
|
||||
self.client = DatabaseClient(self)
|
||||
self.creation = DatabaseCreation(self)
|
||||
|
|
|
@ -80,8 +80,11 @@ class UnicodeCursorWrapper(object):
|
|||
|
||||
class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
uses_savepoints = True
|
||||
requires_rollback_on_dirty_transaction = True
|
||||
has_real_datatype = True
|
||||
|
||||
class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
vendor = 'postgresql'
|
||||
operators = {
|
||||
'exact': '= %s',
|
||||
'iexact': '= UPPER(%s)',
|
||||
|
@ -108,7 +111,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
DeprecationWarning
|
||||
)
|
||||
|
||||
self.features = DatabaseFeatures()
|
||||
self.features = DatabaseFeatures(self)
|
||||
self.ops = DatabaseOperations(self)
|
||||
self.client = DatabaseClient(self)
|
||||
self.creation = DatabaseCreation(self)
|
||||
|
|
|
@ -67,6 +67,8 @@ class CursorWrapper(object):
|
|||
class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
needs_datetime_string_cast = False
|
||||
can_return_id_from_insert = False
|
||||
requires_rollback_on_dirty_transaction = True
|
||||
has_real_datatype = True
|
||||
|
||||
class DatabaseOperations(PostgresqlDatabaseOperations):
|
||||
def last_executed_query(self, cursor, sql, params):
|
||||
|
@ -79,6 +81,7 @@ class DatabaseOperations(PostgresqlDatabaseOperations):
|
|||
return "RETURNING %s", ()
|
||||
|
||||
class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
vendor = 'postgresql'
|
||||
operators = {
|
||||
'exact': '= %s',
|
||||
'iexact': '= UPPER(%s)',
|
||||
|
@ -99,7 +102,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseWrapper, self).__init__(*args, **kwargs)
|
||||
|
||||
self.features = DatabaseFeatures()
|
||||
self.features = DatabaseFeatures(self)
|
||||
autocommit = self.settings_dict["OPTIONS"].get('autocommit', False)
|
||||
self.features.uses_autocommit = autocommit
|
||||
self._set_isolation_level(int(not autocommit))
|
||||
|
|
|
@ -60,6 +60,27 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
# setting ensures we always read result sets fully into memory all in one
|
||||
# go.
|
||||
can_use_chunked_reads = False
|
||||
test_db_allows_multiple_connections = False
|
||||
supports_unspecified_pk = True
|
||||
supports_1000_query_paramters = False
|
||||
|
||||
def _supports_stddev(self):
|
||||
"""Confirm support for STDDEV and related stats functions
|
||||
|
||||
SQLite supports STDDEV as an extension package; so
|
||||
connection.ops.check_aggregate_support() can't unilaterally
|
||||
rule out support for STDDEV. We need to manually check
|
||||
whether the call works.
|
||||
"""
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute('CREATE TABLE STDDEV_TEST (X INT)')
|
||||
try:
|
||||
cursor.execute('SELECT STDDEV(*) FROM STDDEV_TEST')
|
||||
has_support = True
|
||||
except utils.DatabaseError:
|
||||
has_support = False
|
||||
cursor.execute('DROP TABLE STDDEV_TEST')
|
||||
return has_support
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
def date_extract_sql(self, lookup_type, field_name):
|
||||
|
@ -129,7 +150,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
return value
|
||||
|
||||
class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
|
||||
vendor = 'sqlite'
|
||||
# SQLite requires LIKE statements to include an ESCAPE clause if the value
|
||||
# being escaped has a percent or underscore in it.
|
||||
# See http://www.sqlite.org/lang_expr.html for an explanation.
|
||||
|
@ -153,7 +174,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseWrapper, self).__init__(*args, **kwargs)
|
||||
|
||||
self.features = DatabaseFeatures()
|
||||
self.features = DatabaseFeatures(self)
|
||||
self.ops = DatabaseOperations()
|
||||
self.client = DatabaseClient(self)
|
||||
self.creation = DatabaseCreation(self)
|
||||
|
|
|
@ -3,5 +3,5 @@ Django Unit Test and Doctest framework.
|
|||
"""
|
||||
|
||||
from django.test.client import Client
|
||||
from django.test.testcases import TestCase, TransactionTestCase
|
||||
from django.test.testcases import TestCase, TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature
|
||||
from django.test.utils import Approximate
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import sys
|
||||
import signal
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
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.testcases import OutputChecker, DocTestRunner, TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
# The module name for tests outside models.py
|
||||
TEST_MODULE = 'tests'
|
||||
|
@ -14,52 +14,13 @@ TEST_MODULE = 'tests'
|
|||
doctestOutputChecker = OutputChecker()
|
||||
|
||||
class DjangoTestRunner(unittest.TextTestRunner):
|
||||
|
||||
def __init__(self, verbosity=0, failfast=False, **kwargs):
|
||||
super(DjangoTestRunner, self).__init__(verbosity=verbosity, **kwargs)
|
||||
self.failfast = failfast
|
||||
self._keyboard_interrupt_intercepted = False
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
"""
|
||||
Runs the test suite after registering a custom signal handler
|
||||
that triggers a graceful exit when Ctrl-C is pressed.
|
||||
"""
|
||||
self._default_keyboard_interrupt_handler = signal.signal(signal.SIGINT,
|
||||
self._keyboard_interrupt_handler)
|
||||
try:
|
||||
result = super(DjangoTestRunner, self).run(*args, **kwargs)
|
||||
finally:
|
||||
signal.signal(signal.SIGINT, self._default_keyboard_interrupt_handler)
|
||||
return result
|
||||
|
||||
def _keyboard_interrupt_handler(self, signal_number, stack_frame):
|
||||
"""
|
||||
Handles Ctrl-C by setting a flag that will stop the test run when
|
||||
the currently running test completes.
|
||||
"""
|
||||
self._keyboard_interrupt_intercepted = True
|
||||
sys.stderr.write(" <Test run halted by Ctrl-C> ")
|
||||
# Set the interrupt handler back to the default handler, so that
|
||||
# another Ctrl-C press will trigger immediate exit.
|
||||
signal.signal(signal.SIGINT, self._default_keyboard_interrupt_handler)
|
||||
|
||||
def _makeResult(self):
|
||||
result = super(DjangoTestRunner, self)._makeResult()
|
||||
failfast = self.failfast
|
||||
|
||||
def stoptest_override(func):
|
||||
def stoptest(test):
|
||||
# If we were set to failfast and the unit test failed,
|
||||
# or if the user has typed Ctrl-C, report and quit
|
||||
if (failfast and not result.wasSuccessful()) or \
|
||||
self._keyboard_interrupt_intercepted:
|
||||
result.stop()
|
||||
func(test)
|
||||
return stoptest
|
||||
|
||||
result.stopTest = stoptest_override(result.stopTest)
|
||||
return result
|
||||
def __init__(self, *args, **kwargs):
|
||||
import warnings
|
||||
warnings.warn(
|
||||
"DjangoTestRunner is deprecated; it's functionality is indistinguishable from TextTestRunner",
|
||||
PendingDeprecationWarning
|
||||
)
|
||||
super(DjangoTestRunner, self).__init__(*args, **kwargs)
|
||||
|
||||
def get_tests(app_module):
|
||||
try:
|
||||
|
@ -232,6 +193,7 @@ class DjangoTestSuiteRunner(object):
|
|||
def setup_test_environment(self, **kwargs):
|
||||
setup_test_environment()
|
||||
settings.DEBUG = False
|
||||
unittest.installHandler()
|
||||
|
||||
def build_suite(self, test_labels, extra_tests=None, **kwargs):
|
||||
suite = unittest.TestSuite()
|
||||
|
@ -271,7 +233,7 @@ class DjangoTestSuiteRunner(object):
|
|||
return old_names, mirrors
|
||||
|
||||
def run_suite(self, suite, **kwargs):
|
||||
return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)
|
||||
return unittest.TextTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)
|
||||
|
||||
def teardown_databases(self, old_config, **kwargs):
|
||||
from django.db import connections
|
||||
|
@ -284,6 +246,7 @@ class DjangoTestSuiteRunner(object):
|
|||
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):
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import re
|
||||
import unittest
|
||||
from urlparse import urlsplit, urlunsplit
|
||||
from xml.dom.minidom import parseString, Node
|
||||
|
||||
|
@ -7,12 +6,14 @@ from django.conf import settings
|
|||
from django.core import mail
|
||||
from django.core.management import call_command
|
||||
from django.core.urlresolvers import clear_url_caches
|
||||
from django.db import transaction, connections, DEFAULT_DB_ALIAS
|
||||
from django.db import transaction, connection, connections, DEFAULT_DB_ALIAS
|
||||
from django.http import QueryDict
|
||||
from django.test import _doctest as doctest
|
||||
from django.test.client import Client
|
||||
from django.utils import simplejson
|
||||
from django.utils import simplejson, unittest
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.functional import wraps
|
||||
|
||||
|
||||
try:
|
||||
all
|
||||
|
@ -22,6 +23,7 @@ except NameError:
|
|||
normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)
|
||||
normalize_decimals = lambda s: re.sub(r"Decimal\('(\d+(\.\d*)?)'\)", lambda m: "Decimal(\"%s\")" % m.groups()[0], s)
|
||||
|
||||
|
||||
def to_list(value):
|
||||
"""
|
||||
Puts value into a list if it's not already one.
|
||||
|
@ -472,7 +474,7 @@ def connections_support_transactions():
|
|||
Returns True if all connections support transactions. This is messy
|
||||
because 2.4 doesn't support any or all.
|
||||
"""
|
||||
return all(conn.settings_dict['SUPPORTS_TRANSACTIONS']
|
||||
return all(conn.features.supports_transactions
|
||||
for conn in connections.all())
|
||||
|
||||
class TestCase(TransactionTestCase):
|
||||
|
@ -528,3 +530,25 @@ class TestCase(TransactionTestCase):
|
|||
|
||||
for connection in connections.all():
|
||||
connection.close()
|
||||
|
||||
def _deferredSkip(condition, reason):
|
||||
def decorator(test_item):
|
||||
if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
|
||||
@wraps(test_item)
|
||||
def skip_wrapper(*args, **kwargs):
|
||||
if condition():
|
||||
raise unittest.SkipTest(reason)
|
||||
test_item = skip_wrapper
|
||||
test_item.__unittest_skip_why__ = reason
|
||||
return test_item
|
||||
return decorator
|
||||
|
||||
def skipIfDBFeature(feature):
|
||||
"Skip a test if a database has the named feature"
|
||||
return _deferredSkip(lambda: getattr(connection.features, feature),
|
||||
"Database has feature %s" % feature)
|
||||
|
||||
def skipUnlessDBFeature(feature):
|
||||
"Skip a test unless a database has the named feature"
|
||||
return _deferredSkip(lambda: not getattr(connection.features, feature),
|
||||
"Database doesn't support feature %s" % feature)
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
"""
|
||||
unittest2
|
||||
|
||||
unittest2 is a backport of the new features added to the unittest testing
|
||||
framework in Python 2.7. It is tested to run on Python 2.4 - 2.6.
|
||||
|
||||
To use unittest2 instead of unittest simply replace ``import unittest`` with
|
||||
``import unittest2``.
|
||||
|
||||
|
||||
Copyright (c) 1999-2003 Steve Purcell
|
||||
Copyright (c) 2003-2010 Python Software Foundation
|
||||
This module is free software, and you may redistribute it and/or modify
|
||||
it under the same terms as Python itself, so long as this copyright message
|
||||
and disclaimer are retained in their original form.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
|
||||
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
|
||||
THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
|
||||
THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
|
||||
AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
|
||||
SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
# Django hackery to load the appropriate version of unittest
|
||||
|
||||
if sys.version_info >= (2,7):
|
||||
# unittest2 features are native in Python 2.7
|
||||
from unittest import *
|
||||
else:
|
||||
try:
|
||||
# check the system path first
|
||||
from unittest2 import *
|
||||
except ImportError:
|
||||
# otherwise use our bundled version
|
||||
__all__ = ['TestResult', 'TestCase', 'TestSuite',
|
||||
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
||||
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
||||
'expectedFailure', 'TextTestResult', '__version__', 'collector']
|
||||
|
||||
__version__ = '0.5.1'
|
||||
|
||||
# Expose obsolete functions for backwards compatibility
|
||||
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
|
||||
|
||||
|
||||
from django.utils.unittest.collector import collector
|
||||
from django.utils.unittest.result import TestResult
|
||||
from django.utils.unittest.case import \
|
||||
TestCase, FunctionTestCase, SkipTest, skip, skipIf,\
|
||||
skipUnless, expectedFailure
|
||||
|
||||
from django.utils.unittest.suite import BaseTestSuite, TestSuite
|
||||
from django.utils.unittest.loader import \
|
||||
TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,\
|
||||
findTestCases
|
||||
|
||||
from django.utils.unittest.main import TestProgram, main, main_
|
||||
from django.utils.unittest.runner import TextTestRunner, TextTestResult
|
||||
|
||||
try:
|
||||
from django.utils.unittest.signals import\
|
||||
installHandler, registerResult, removeResult, removeHandler
|
||||
except ImportError:
|
||||
# Compatibility with platforms that don't have the signal module
|
||||
pass
|
||||
else:
|
||||
__all__.extend(['installHandler', 'registerResult', 'removeResult',
|
||||
'removeHandler'])
|
||||
|
||||
# deprecated
|
||||
_TextTestResult = TextTestResult
|
||||
|
||||
__unittest = True
|
|
@ -0,0 +1,10 @@
|
|||
"""Main entry point"""
|
||||
|
||||
import sys
|
||||
if sys.argv[0].endswith("__main__.py"):
|
||||
sys.argv[0] = "unittest2"
|
||||
|
||||
__unittest = True
|
||||
|
||||
from django.utils.unittest.main import main_
|
||||
main_()
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
from django.utils.unittest.loader import defaultTestLoader
|
||||
|
||||
def collector():
|
||||
# import __main__ triggers code re-execution
|
||||
__main__ = sys.modules['__main__']
|
||||
setupDir = os.path.abspath(os.path.dirname(__main__.__file__))
|
||||
return defaultTestLoader.discover(setupDir)
|
|
@ -0,0 +1,64 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
try:
|
||||
from functools import wraps
|
||||
except ImportError:
|
||||
# only needed for Python 2.4
|
||||
def wraps(_):
|
||||
def _wraps(func):
|
||||
return func
|
||||
return _wraps
|
||||
|
||||
__unittest = True
|
||||
|
||||
def _relpath_nt(path, start=os.path.curdir):
|
||||
"""Return a relative version of a path"""
|
||||
|
||||
if not path:
|
||||
raise ValueError("no path specified")
|
||||
start_list = os.path.abspath(start).split(os.path.sep)
|
||||
path_list = os.path.abspath(path).split(os.path.sep)
|
||||
if start_list[0].lower() != path_list[0].lower():
|
||||
unc_path, rest = os.path.splitunc(path)
|
||||
unc_start, rest = os.path.splitunc(start)
|
||||
if bool(unc_path) ^ bool(unc_start):
|
||||
raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
|
||||
% (path, start))
|
||||
else:
|
||||
raise ValueError("path is on drive %s, start on drive %s"
|
||||
% (path_list[0], start_list[0]))
|
||||
# Work out how much of the filepath is shared by start and path.
|
||||
for i in range(min(len(start_list), len(path_list))):
|
||||
if start_list[i].lower() != path_list[i].lower():
|
||||
break
|
||||
else:
|
||||
i += 1
|
||||
|
||||
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
||||
if not rel_list:
|
||||
return os.path.curdir
|
||||
return os.path.join(*rel_list)
|
||||
|
||||
# default to posixpath definition
|
||||
def _relpath_posix(path, start=os.path.curdir):
|
||||
"""Return a relative version of a path"""
|
||||
|
||||
if not path:
|
||||
raise ValueError("no path specified")
|
||||
|
||||
start_list = os.path.abspath(start).split(os.path.sep)
|
||||
path_list = os.path.abspath(path).split(os.path.sep)
|
||||
|
||||
# Work out how much of the filepath is shared by start and path.
|
||||
i = len(os.path.commonprefix([start_list, path_list]))
|
||||
|
||||
rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
|
||||
if not rel_list:
|
||||
return os.path.curdir
|
||||
return os.path.join(*rel_list)
|
||||
|
||||
if os.path is sys.modules.get('ntpath'):
|
||||
relpath = _relpath_nt
|
||||
else:
|
||||
relpath = _relpath_posix
|
|
@ -0,0 +1,322 @@
|
|||
"""Loading unittests."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
import types
|
||||
import unittest
|
||||
|
||||
from fnmatch import fnmatch
|
||||
|
||||
from django.utils.unittest import case, suite
|
||||
|
||||
try:
|
||||
from os.path import relpath
|
||||
except ImportError:
|
||||
from django.utils.unittest.compatibility import relpath
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
def _CmpToKey(mycmp):
|
||||
'Convert a cmp= function into a key= function'
|
||||
class K(object):
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
def __lt__(self, other):
|
||||
return mycmp(self.obj, other.obj) == -1
|
||||
return K
|
||||
|
||||
|
||||
# what about .pyc or .pyo (etc)
|
||||
# we would need to avoid loading the same tests multiple times
|
||||
# from '.py', '.pyc' *and* '.pyo'
|
||||
VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
|
||||
|
||||
|
||||
def _make_failed_import_test(name, suiteClass):
|
||||
message = 'Failed to import test module: %s' % name
|
||||
if hasattr(traceback, 'format_exc'):
|
||||
# Python 2.3 compatibility
|
||||
# format_exc returns two frames of discover.py as well
|
||||
message += '\n%s' % traceback.format_exc()
|
||||
return _make_failed_test('ModuleImportFailure', name, ImportError(message),
|
||||
suiteClass)
|
||||
|
||||
def _make_failed_load_tests(name, exception, suiteClass):
|
||||
return _make_failed_test('LoadTestsFailure', name, exception, suiteClass)
|
||||
|
||||
def _make_failed_test(classname, methodname, exception, suiteClass):
|
||||
def testFailure(self):
|
||||
raise exception
|
||||
attrs = {methodname: testFailure}
|
||||
TestClass = type(classname, (case.TestCase,), attrs)
|
||||
return suiteClass((TestClass(methodname),))
|
||||
|
||||
|
||||
class TestLoader(unittest.TestLoader):
|
||||
"""
|
||||
This class is responsible for loading tests according to various criteria
|
||||
and returning them wrapped in a TestSuite
|
||||
"""
|
||||
testMethodPrefix = 'test'
|
||||
sortTestMethodsUsing = cmp
|
||||
suiteClass = suite.TestSuite
|
||||
_top_level_dir = None
|
||||
|
||||
def loadTestsFromTestCase(self, testCaseClass):
|
||||
"""Return a suite of all tests cases contained in testCaseClass"""
|
||||
if issubclass(testCaseClass, suite.TestSuite):
|
||||
raise TypeError("Test cases should not be derived from TestSuite."
|
||||
" Maybe you meant to derive from TestCase?")
|
||||
testCaseNames = self.getTestCaseNames(testCaseClass)
|
||||
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
||||
testCaseNames = ['runTest']
|
||||
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
|
||||
return loaded_suite
|
||||
|
||||
def loadTestsFromModule(self, module, use_load_tests=True):
|
||||
"""Return a suite of all tests cases contained in the given module"""
|
||||
tests = []
|
||||
for name in dir(module):
|
||||
obj = getattr(module, name)
|
||||
if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
|
||||
tests.append(self.loadTestsFromTestCase(obj))
|
||||
|
||||
load_tests = getattr(module, 'load_tests', None)
|
||||
tests = self.suiteClass(tests)
|
||||
if use_load_tests and load_tests is not None:
|
||||
try:
|
||||
return load_tests(self, tests, None)
|
||||
except Exception, e:
|
||||
return _make_failed_load_tests(module.__name__, e,
|
||||
self.suiteClass)
|
||||
return tests
|
||||
|
||||
def loadTestsFromName(self, name, module=None):
|
||||
"""Return a suite of all tests cases given a string specifier.
|
||||
|
||||
The name may resolve either to a module, a test case class, a
|
||||
test method within a test case class, or a callable object which
|
||||
returns a TestCase or TestSuite instance.
|
||||
|
||||
The method optionally resolves the names relative to a given module.
|
||||
"""
|
||||
parts = name.split('.')
|
||||
if module is None:
|
||||
parts_copy = parts[:]
|
||||
while parts_copy:
|
||||
try:
|
||||
module = __import__('.'.join(parts_copy))
|
||||
break
|
||||
except ImportError:
|
||||
del parts_copy[-1]
|
||||
if not parts_copy:
|
||||
raise
|
||||
parts = parts[1:]
|
||||
obj = module
|
||||
for part in parts:
|
||||
parent, obj = obj, getattr(obj, part)
|
||||
|
||||
if isinstance(obj, types.ModuleType):
|
||||
return self.loadTestsFromModule(obj)
|
||||
elif isinstance(obj, type) and issubclass(obj, unittest.TestCase):
|
||||
return self.loadTestsFromTestCase(obj)
|
||||
elif (isinstance(obj, types.UnboundMethodType) and
|
||||
isinstance(parent, type) and
|
||||
issubclass(parent, case.TestCase)):
|
||||
return self.suiteClass([parent(obj.__name__)])
|
||||
elif isinstance(obj, unittest.TestSuite):
|
||||
return obj
|
||||
elif hasattr(obj, '__call__'):
|
||||
test = obj()
|
||||
if isinstance(test, unittest.TestSuite):
|
||||
return test
|
||||
elif isinstance(test, unittest.TestCase):
|
||||
return self.suiteClass([test])
|
||||
else:
|
||||
raise TypeError("calling %s returned %s, not a test" %
|
||||
(obj, test))
|
||||
else:
|
||||
raise TypeError("don't know how to make test from: %s" % obj)
|
||||
|
||||
def loadTestsFromNames(self, names, module=None):
|
||||
"""Return a suite of all tests cases found using the given sequence
|
||||
of string specifiers. See 'loadTestsFromName()'.
|
||||
"""
|
||||
suites = [self.loadTestsFromName(name, module) for name in names]
|
||||
return self.suiteClass(suites)
|
||||
|
||||
def getTestCaseNames(self, testCaseClass):
|
||||
"""Return a sorted sequence of method names found within testCaseClass
|
||||
"""
|
||||
def isTestMethod(attrname, testCaseClass=testCaseClass,
|
||||
prefix=self.testMethodPrefix):
|
||||
return attrname.startswith(prefix) and \
|
||||
hasattr(getattr(testCaseClass, attrname), '__call__')
|
||||
testFnNames = filter(isTestMethod, dir(testCaseClass))
|
||||
if self.sortTestMethodsUsing:
|
||||
testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
|
||||
return testFnNames
|
||||
|
||||
def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
|
||||
"""Find and return all test modules from the specified start
|
||||
directory, recursing into subdirectories to find them. Only test files
|
||||
that match the pattern will be loaded. (Using shell style pattern
|
||||
matching.)
|
||||
|
||||
All test modules must be importable from the top level of the project.
|
||||
If the start directory is not the top level directory then the top
|
||||
level directory must be specified separately.
|
||||
|
||||
If a test package name (directory with '__init__.py') matches the
|
||||
pattern then the package will be checked for a 'load_tests' function. If
|
||||
this exists then it will be called with loader, tests, pattern.
|
||||
|
||||
If load_tests exists then discovery does *not* recurse into the package,
|
||||
load_tests is responsible for loading all tests in the package.
|
||||
|
||||
The pattern is deliberately not stored as a loader attribute so that
|
||||
packages can continue discovery themselves. top_level_dir is stored so
|
||||
load_tests does not need to pass this argument in to loader.discover().
|
||||
"""
|
||||
set_implicit_top = False
|
||||
if top_level_dir is None and self._top_level_dir is not None:
|
||||
# make top_level_dir optional if called from load_tests in a package
|
||||
top_level_dir = self._top_level_dir
|
||||
elif top_level_dir is None:
|
||||
set_implicit_top = True
|
||||
top_level_dir = start_dir
|
||||
|
||||
top_level_dir = os.path.abspath(top_level_dir)
|
||||
|
||||
if not top_level_dir in sys.path:
|
||||
# all test modules must be importable from the top level directory
|
||||
# should we *unconditionally* put the start directory in first
|
||||
# in sys.path to minimise likelihood of conflicts between installed
|
||||
# modules and development versions?
|
||||
sys.path.insert(0, top_level_dir)
|
||||
self._top_level_dir = top_level_dir
|
||||
|
||||
is_not_importable = False
|
||||
if os.path.isdir(os.path.abspath(start_dir)):
|
||||
start_dir = os.path.abspath(start_dir)
|
||||
if start_dir != top_level_dir:
|
||||
is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
|
||||
else:
|
||||
# support for discovery from dotted module names
|
||||
try:
|
||||
__import__(start_dir)
|
||||
except ImportError:
|
||||
is_not_importable = True
|
||||
else:
|
||||
the_module = sys.modules[start_dir]
|
||||
top_part = start_dir.split('.')[0]
|
||||
start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
|
||||
if set_implicit_top:
|
||||
self._top_level_dir = os.path.abspath(os.path.dirname(os.path.dirname(sys.modules[top_part].__file__)))
|
||||
sys.path.remove(top_level_dir)
|
||||
|
||||
if is_not_importable:
|
||||
raise ImportError('Start directory is not importable: %r' % start_dir)
|
||||
|
||||
tests = list(self._find_tests(start_dir, pattern))
|
||||
return self.suiteClass(tests)
|
||||
|
||||
def _get_name_from_path(self, path):
|
||||
path = os.path.splitext(os.path.normpath(path))[0]
|
||||
|
||||
_relpath = relpath(path, self._top_level_dir)
|
||||
assert not os.path.isabs(_relpath), "Path must be within the project"
|
||||
assert not _relpath.startswith('..'), "Path must be within the project"
|
||||
|
||||
name = _relpath.replace(os.path.sep, '.')
|
||||
return name
|
||||
|
||||
def _get_module_from_name(self, name):
|
||||
__import__(name)
|
||||
return sys.modules[name]
|
||||
|
||||
def _match_path(self, path, full_path, pattern):
|
||||
# override this method to use alternative matching strategy
|
||||
return fnmatch(path, pattern)
|
||||
|
||||
def _find_tests(self, start_dir, pattern):
|
||||
"""Used by discovery. Yields test suites it loads."""
|
||||
paths = os.listdir(start_dir)
|
||||
|
||||
for path in paths:
|
||||
full_path = os.path.join(start_dir, path)
|
||||
if os.path.isfile(full_path):
|
||||
if not VALID_MODULE_NAME.match(path):
|
||||
# valid Python identifiers only
|
||||
continue
|
||||
if not self._match_path(path, full_path, pattern):
|
||||
continue
|
||||
# if the test file matches, load it
|
||||
name = self._get_name_from_path(full_path)
|
||||
try:
|
||||
module = self._get_module_from_name(name)
|
||||
except:
|
||||
yield _make_failed_import_test(name, self.suiteClass)
|
||||
else:
|
||||
mod_file = os.path.abspath(getattr(module, '__file__', full_path))
|
||||
realpath = os.path.splitext(mod_file)[0]
|
||||
fullpath_noext = os.path.splitext(full_path)[0]
|
||||
if realpath.lower() != fullpath_noext.lower():
|
||||
module_dir = os.path.dirname(realpath)
|
||||
mod_name = os.path.splitext(os.path.basename(full_path))[0]
|
||||
expected_dir = os.path.dirname(full_path)
|
||||
msg = ("%r module incorrectly imported from %r. Expected %r. "
|
||||
"Is this module globally installed?")
|
||||
raise ImportError(msg % (mod_name, module_dir, expected_dir))
|
||||
yield self.loadTestsFromModule(module)
|
||||
elif os.path.isdir(full_path):
|
||||
if not os.path.isfile(os.path.join(full_path, '__init__.py')):
|
||||
continue
|
||||
|
||||
load_tests = None
|
||||
tests = None
|
||||
if fnmatch(path, pattern):
|
||||
# only check load_tests if the package directory itself matches the filter
|
||||
name = self._get_name_from_path(full_path)
|
||||
package = self._get_module_from_name(name)
|
||||
load_tests = getattr(package, 'load_tests', None)
|
||||
tests = self.loadTestsFromModule(package, use_load_tests=False)
|
||||
|
||||
if load_tests is None:
|
||||
if tests is not None:
|
||||
# tests loaded from package file
|
||||
yield tests
|
||||
# recurse into the package
|
||||
for test in self._find_tests(full_path, pattern):
|
||||
yield test
|
||||
else:
|
||||
try:
|
||||
yield load_tests(self, tests, pattern)
|
||||
except Exception, e:
|
||||
yield _make_failed_load_tests(package.__name__, e,
|
||||
self.suiteClass)
|
||||
|
||||
defaultTestLoader = TestLoader()
|
||||
|
||||
|
||||
def _makeLoader(prefix, sortUsing, suiteClass=None):
|
||||
loader = TestLoader()
|
||||
loader.sortTestMethodsUsing = sortUsing
|
||||
loader.testMethodPrefix = prefix
|
||||
if suiteClass:
|
||||
loader.suiteClass = suiteClass
|
||||
return loader
|
||||
|
||||
def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
|
||||
return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
|
||||
|
||||
def makeSuite(testCaseClass, prefix='test', sortUsing=cmp,
|
||||
suiteClass=suite.TestSuite):
|
||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
|
||||
|
||||
def findTestCases(module, prefix='test', sortUsing=cmp,
|
||||
suiteClass=suite.TestSuite):
|
||||
return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
|
|
@ -0,0 +1,241 @@
|
|||
"""Unittest main program"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import types
|
||||
|
||||
from django.utils.unittest import loader, runner
|
||||
try:
|
||||
from django.utils.unittest.signals import installHandler
|
||||
except ImportError:
|
||||
installHandler = None
|
||||
|
||||
__unittest = True
|
||||
|
||||
FAILFAST = " -f, --failfast Stop on first failure\n"
|
||||
CATCHBREAK = " -c, --catch Catch control-C and display results\n"
|
||||
BUFFEROUTPUT = " -b, --buffer Buffer stdout and stderr during test runs\n"
|
||||
|
||||
USAGE_AS_MAIN = """\
|
||||
Usage: %(progName)s [options] [tests]
|
||||
|
||||
Options:
|
||||
-h, --help Show this message
|
||||
-v, --verbose Verbose output
|
||||
-q, --quiet Minimal output
|
||||
%(failfast)s%(catchbreak)s%(buffer)s
|
||||
Examples:
|
||||
%(progName)s test_module - run tests from test_module
|
||||
%(progName)s test_module.TestClass - run tests from
|
||||
test_module.TestClass
|
||||
%(progName)s test_module.TestClass.test_method - run specified test method
|
||||
|
||||
[tests] can be a list of any number of test modules, classes and test
|
||||
methods.
|
||||
|
||||
Alternative Usage: %(progName)s discover [options]
|
||||
|
||||
Options:
|
||||
-v, --verbose Verbose output
|
||||
%(failfast)s%(catchbreak)s%(buffer)s -s directory Directory to start discovery ('.' default)
|
||||
-p pattern Pattern to match test files ('test*.py' default)
|
||||
-t directory Top level directory of project (default to
|
||||
start directory)
|
||||
|
||||
For test discovery all test modules must be importable from the top
|
||||
level directory of the project.
|
||||
"""
|
||||
|
||||
USAGE_FROM_MODULE = """\
|
||||
Usage: %(progName)s [options] [test] [...]
|
||||
|
||||
Options:
|
||||
-h, --help Show this message
|
||||
-v, --verbose Verbose output
|
||||
-q, --quiet Minimal output
|
||||
%(failfast)s%(catchbreak)s%(buffer)s
|
||||
Examples:
|
||||
%(progName)s - run default set of tests
|
||||
%(progName)s MyTestSuite - run suite 'MyTestSuite'
|
||||
%(progName)s MyTestCase.testSomething - run MyTestCase.testSomething
|
||||
%(progName)s MyTestCase - run all 'test*' test methods
|
||||
in MyTestCase
|
||||
"""
|
||||
|
||||
|
||||
class TestProgram(object):
|
||||
"""A command-line program that runs a set of tests; this is primarily
|
||||
for making test modules conveniently executable.
|
||||
"""
|
||||
USAGE = USAGE_FROM_MODULE
|
||||
|
||||
# defaults for testing
|
||||
failfast = catchbreak = buffer = progName = None
|
||||
|
||||
def __init__(self, module='__main__', defaultTest=None,
|
||||
argv=None, testRunner=None,
|
||||
testLoader=loader.defaultTestLoader, exit=True,
|
||||
verbosity=1, failfast=None, catchbreak=None, buffer=None):
|
||||
if isinstance(module, basestring):
|
||||
self.module = __import__(module)
|
||||
for part in module.split('.')[1:]:
|
||||
self.module = getattr(self.module, part)
|
||||
else:
|
||||
self.module = module
|
||||
if argv is None:
|
||||
argv = sys.argv
|
||||
|
||||
self.exit = exit
|
||||
self.verbosity = verbosity
|
||||
self.failfast = failfast
|
||||
self.catchbreak = catchbreak
|
||||
self.buffer = buffer
|
||||
self.defaultTest = defaultTest
|
||||
self.testRunner = testRunner
|
||||
self.testLoader = testLoader
|
||||
self.progName = os.path.basename(argv[0])
|
||||
self.parseArgs(argv)
|
||||
self.runTests()
|
||||
|
||||
def usageExit(self, msg=None):
|
||||
if msg:
|
||||
print msg
|
||||
usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
|
||||
'buffer': ''}
|
||||
if self.failfast != False:
|
||||
usage['failfast'] = FAILFAST
|
||||
if self.catchbreak != False and installHandler is not None:
|
||||
usage['catchbreak'] = CATCHBREAK
|
||||
if self.buffer != False:
|
||||
usage['buffer'] = BUFFEROUTPUT
|
||||
print self.USAGE % usage
|
||||
sys.exit(2)
|
||||
|
||||
def parseArgs(self, argv):
|
||||
if len(argv) > 1 and argv[1].lower() == 'discover':
|
||||
self._do_discovery(argv[2:])
|
||||
return
|
||||
|
||||
import getopt
|
||||
long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
|
||||
try:
|
||||
options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
|
||||
for opt, value in options:
|
||||
if opt in ('-h','-H','--help'):
|
||||
self.usageExit()
|
||||
if opt in ('-q','--quiet'):
|
||||
self.verbosity = 0
|
||||
if opt in ('-v','--verbose'):
|
||||
self.verbosity = 2
|
||||
if opt in ('-f','--failfast'):
|
||||
if self.failfast is None:
|
||||
self.failfast = True
|
||||
# Should this raise an exception if -f is not valid?
|
||||
if opt in ('-c','--catch'):
|
||||
if self.catchbreak is None and installHandler is not None:
|
||||
self.catchbreak = True
|
||||
# Should this raise an exception if -c is not valid?
|
||||
if opt in ('-b','--buffer'):
|
||||
if self.buffer is None:
|
||||
self.buffer = True
|
||||
# Should this raise an exception if -b is not valid?
|
||||
if len(args) == 0 and self.defaultTest is None:
|
||||
# createTests will load tests from self.module
|
||||
self.testNames = None
|
||||
elif len(args) > 0:
|
||||
self.testNames = args
|
||||
if __name__ == '__main__':
|
||||
# to support python -m unittest ...
|
||||
self.module = None
|
||||
else:
|
||||
self.testNames = (self.defaultTest,)
|
||||
self.createTests()
|
||||
except getopt.error, msg:
|
||||
self.usageExit(msg)
|
||||
|
||||
def createTests(self):
|
||||
if self.testNames is None:
|
||||
self.test = self.testLoader.loadTestsFromModule(self.module)
|
||||
else:
|
||||
self.test = self.testLoader.loadTestsFromNames(self.testNames,
|
||||
self.module)
|
||||
|
||||
def _do_discovery(self, argv, Loader=loader.TestLoader):
|
||||
# handle command line args for test discovery
|
||||
self.progName = '%s discover' % self.progName
|
||||
import optparse
|
||||
parser = optparse.OptionParser()
|
||||
parser.prog = self.progName
|
||||
parser.add_option('-v', '--verbose', dest='verbose', default=False,
|
||||
help='Verbose output', action='store_true')
|
||||
if self.failfast != False:
|
||||
parser.add_option('-f', '--failfast', dest='failfast', default=False,
|
||||
help='Stop on first fail or error',
|
||||
action='store_true')
|
||||
if self.catchbreak != False and installHandler is not None:
|
||||
parser.add_option('-c', '--catch', dest='catchbreak', default=False,
|
||||
help='Catch ctrl-C and display results so far',
|
||||
action='store_true')
|
||||
if self.buffer != False:
|
||||
parser.add_option('-b', '--buffer', dest='buffer', default=False,
|
||||
help='Buffer stdout and stderr during tests',
|
||||
action='store_true')
|
||||
parser.add_option('-s', '--start-directory', dest='start', default='.',
|
||||
help="Directory to start discovery ('.' default)")
|
||||
parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
|
||||
help="Pattern to match tests ('test*.py' default)")
|
||||
parser.add_option('-t', '--top-level-directory', dest='top', default=None,
|
||||
help='Top level directory of project (defaults to start directory)')
|
||||
|
||||
options, args = parser.parse_args(argv)
|
||||
if len(args) > 3:
|
||||
self.usageExit()
|
||||
|
||||
for name, value in zip(('start', 'pattern', 'top'), args):
|
||||
setattr(options, name, value)
|
||||
|
||||
# only set options from the parsing here
|
||||
# if they weren't set explicitly in the constructor
|
||||
if self.failfast is None:
|
||||
self.failfast = options.failfast
|
||||
if self.catchbreak is None and installHandler is not None:
|
||||
self.catchbreak = options.catchbreak
|
||||
if self.buffer is None:
|
||||
self.buffer = options.buffer
|
||||
|
||||
if options.verbose:
|
||||
self.verbosity = 2
|
||||
|
||||
start_dir = options.start
|
||||
pattern = options.pattern
|
||||
top_level_dir = options.top
|
||||
|
||||
loader = Loader()
|
||||
self.test = loader.discover(start_dir, pattern, top_level_dir)
|
||||
|
||||
def runTests(self):
|
||||
if self.catchbreak:
|
||||
installHandler()
|
||||
if self.testRunner is None:
|
||||
self.testRunner = runner.TextTestRunner
|
||||
if isinstance(self.testRunner, (type, types.ClassType)):
|
||||
try:
|
||||
testRunner = self.testRunner(verbosity=self.verbosity,
|
||||
failfast=self.failfast,
|
||||
buffer=self.buffer)
|
||||
except TypeError:
|
||||
# didn't accept the verbosity, buffer or failfast arguments
|
||||
testRunner = self.testRunner()
|
||||
else:
|
||||
# it is assumed to be a TestRunner instance
|
||||
testRunner = self.testRunner
|
||||
self.result = testRunner.run(self.test)
|
||||
if self.exit:
|
||||
sys.exit(not self.result.wasSuccessful())
|
||||
|
||||
main = TestProgram
|
||||
|
||||
def main_():
|
||||
TestProgram.USAGE = USAGE_AS_MAIN
|
||||
main(module=None)
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
"""Test result object"""
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
import unittest
|
||||
|
||||
from StringIO import StringIO
|
||||
|
||||
from django.utils.unittest import util
|
||||
from django.utils.unittest.compatibility import wraps
|
||||
|
||||
__unittest = True
|
||||
|
||||
def failfast(method):
|
||||
@wraps(method)
|
||||
def inner(self, *args, **kw):
|
||||
if getattr(self, 'failfast', False):
|
||||
self.stop()
|
||||
return method(self, *args, **kw)
|
||||
return inner
|
||||
|
||||
|
||||
STDOUT_LINE = '\nStdout:\n%s'
|
||||
STDERR_LINE = '\nStderr:\n%s'
|
||||
|
||||
class TestResult(unittest.TestResult):
|
||||
"""Holder for test result information.
|
||||
|
||||
Test results are automatically managed by the TestCase and TestSuite
|
||||
classes, and do not need to be explicitly manipulated by writers of tests.
|
||||
|
||||
Each instance holds the total number of tests run, and collections of
|
||||
failures and errors that occurred among those test runs. The collections
|
||||
contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
|
||||
formatted traceback of the error that occurred.
|
||||
"""
|
||||
_previousTestClass = None
|
||||
_moduleSetUpFailed = False
|
||||
|
||||
def __init__(self):
|
||||
self.failfast = False
|
||||
self.failures = []
|
||||
self.errors = []
|
||||
self.testsRun = 0
|
||||
self.skipped = []
|
||||
self.expectedFailures = []
|
||||
self.unexpectedSuccesses = []
|
||||
self.shouldStop = False
|
||||
self.buffer = False
|
||||
self._stdout_buffer = None
|
||||
self._stderr_buffer = None
|
||||
self._original_stdout = sys.stdout
|
||||
self._original_stderr = sys.stderr
|
||||
self._mirrorOutput = False
|
||||
|
||||
def startTest(self, test):
|
||||
"Called when the given test is about to be run"
|
||||
self.testsRun += 1
|
||||
self._mirrorOutput = False
|
||||
if self.buffer:
|
||||
if self._stderr_buffer is None:
|
||||
self._stderr_buffer = StringIO()
|
||||
self._stdout_buffer = StringIO()
|
||||
sys.stdout = self._stdout_buffer
|
||||
sys.stderr = self._stderr_buffer
|
||||
|
||||
def startTestRun(self):
|
||||
"""Called once before any tests are executed.
|
||||
|
||||
See startTest for a method called before each test.
|
||||
"""
|
||||
|
||||
def stopTest(self, test):
|
||||
"""Called when the given test has been run"""
|
||||
if self.buffer:
|
||||
if self._mirrorOutput:
|
||||
output = sys.stdout.getvalue()
|
||||
error = sys.stderr.getvalue()
|
||||
if output:
|
||||
if not output.endswith('\n'):
|
||||
output += '\n'
|
||||
self._original_stdout.write(STDOUT_LINE % output)
|
||||
if error:
|
||||
if not error.endswith('\n'):
|
||||
error += '\n'
|
||||
self._original_stderr.write(STDERR_LINE % error)
|
||||
|
||||
sys.stdout = self._original_stdout
|
||||
sys.stderr = self._original_stderr
|
||||
self._stdout_buffer.seek(0)
|
||||
self._stdout_buffer.truncate()
|
||||
self._stderr_buffer.seek(0)
|
||||
self._stderr_buffer.truncate()
|
||||
self._mirrorOutput = False
|
||||
|
||||
|
||||
def stopTestRun(self):
|
||||
"""Called once after all tests are executed.
|
||||
|
||||
See stopTest for a method called after each test.
|
||||
"""
|
||||
|
||||
@failfast
|
||||
def addError(self, test, err):
|
||||
"""Called when an error has occurred. 'err' is a tuple of values as
|
||||
returned by sys.exc_info().
|
||||
"""
|
||||
self.errors.append((test, self._exc_info_to_string(err, test)))
|
||||
self._mirrorOutput = True
|
||||
|
||||
@failfast
|
||||
def addFailure(self, test, err):
|
||||
"""Called when an error has occurred. 'err' is a tuple of values as
|
||||
returned by sys.exc_info()."""
|
||||
self.failures.append((test, self._exc_info_to_string(err, test)))
|
||||
self._mirrorOutput = True
|
||||
|
||||
def addSuccess(self, test):
|
||||
"Called when a test has completed successfully"
|
||||
pass
|
||||
|
||||
def addSkip(self, test, reason):
|
||||
"""Called when a test is skipped."""
|
||||
self.skipped.append((test, reason))
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
"""Called when an expected failure/error occured."""
|
||||
self.expectedFailures.append(
|
||||
(test, self._exc_info_to_string(err, test)))
|
||||
|
||||
@failfast
|
||||
def addUnexpectedSuccess(self, test):
|
||||
"""Called when a test was expected to fail, but succeed."""
|
||||
self.unexpectedSuccesses.append(test)
|
||||
|
||||
def wasSuccessful(self):
|
||||
"Tells whether or not this result was a success"
|
||||
return (len(self.failures) + len(self.errors) == 0)
|
||||
|
||||
def stop(self):
|
||||
"Indicates that the tests should be aborted"
|
||||
self.shouldStop = True
|
||||
|
||||
def _exc_info_to_string(self, err, test):
|
||||
"""Converts a sys.exc_info()-style tuple of values into a string."""
|
||||
exctype, value, tb = err
|
||||
# Skip test runner traceback levels
|
||||
while tb and self._is_relevant_tb_level(tb):
|
||||
tb = tb.tb_next
|
||||
if exctype is test.failureException:
|
||||
# Skip assert*() traceback levels
|
||||
length = self._count_relevant_tb_levels(tb)
|
||||
msgLines = traceback.format_exception(exctype, value, tb, length)
|
||||
else:
|
||||
msgLines = traceback.format_exception(exctype, value, tb)
|
||||
|
||||
if self.buffer:
|
||||
output = sys.stdout.getvalue()
|
||||
error = sys.stderr.getvalue()
|
||||
if output:
|
||||
if not output.endswith('\n'):
|
||||
output += '\n'
|
||||
msgLines.append(STDOUT_LINE % output)
|
||||
if error:
|
||||
if not error.endswith('\n'):
|
||||
error += '\n'
|
||||
msgLines.append(STDERR_LINE % error)
|
||||
return ''.join(msgLines)
|
||||
|
||||
def _is_relevant_tb_level(self, tb):
|
||||
return '__unittest' in tb.tb_frame.f_globals
|
||||
|
||||
def _count_relevant_tb_levels(self, tb):
|
||||
length = 0
|
||||
while tb and not self._is_relevant_tb_level(tb):
|
||||
length += 1
|
||||
tb = tb.tb_next
|
||||
return length
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s run=%i errors=%i failures=%i>" % \
|
||||
(util.strclass(self.__class__), self.testsRun, len(self.errors),
|
||||
len(self.failures))
|
|
@ -0,0 +1,206 @@
|
|||
"""Running tests"""
|
||||
|
||||
import sys
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from django.utils.unittest import result
|
||||
|
||||
try:
|
||||
from django.utils.unittest.signals import registerResult
|
||||
except ImportError:
|
||||
def registerResult(_):
|
||||
pass
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
class _WritelnDecorator(object):
|
||||
"""Used to decorate file-like objects with a handy 'writeln' method"""
|
||||
def __init__(self,stream):
|
||||
self.stream = stream
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if attr in ('stream', '__getstate__'):
|
||||
raise AttributeError(attr)
|
||||
return getattr(self.stream,attr)
|
||||
|
||||
def writeln(self, arg=None):
|
||||
if arg:
|
||||
self.write(arg)
|
||||
self.write('\n') # text-mode streams translate to \r\n if needed
|
||||
|
||||
|
||||
class TextTestResult(result.TestResult):
|
||||
"""A test result class that can print formatted text results to a stream.
|
||||
|
||||
Used by TextTestRunner.
|
||||
"""
|
||||
separator1 = '=' * 70
|
||||
separator2 = '-' * 70
|
||||
|
||||
def __init__(self, stream, descriptions, verbosity):
|
||||
super(TextTestResult, self).__init__()
|
||||
self.stream = stream
|
||||
self.showAll = verbosity > 1
|
||||
self.dots = verbosity == 1
|
||||
self.descriptions = descriptions
|
||||
|
||||
def getDescription(self, test):
|
||||
doc_first_line = test.shortDescription()
|
||||
if self.descriptions and doc_first_line:
|
||||
return '\n'.join((str(test), doc_first_line))
|
||||
else:
|
||||
return str(test)
|
||||
|
||||
def startTest(self, test):
|
||||
super(TextTestResult, self).startTest(test)
|
||||
if self.showAll:
|
||||
self.stream.write(self.getDescription(test))
|
||||
self.stream.write(" ... ")
|
||||
self.stream.flush()
|
||||
|
||||
def addSuccess(self, test):
|
||||
super(TextTestResult, self).addSuccess(test)
|
||||
if self.showAll:
|
||||
self.stream.writeln("ok")
|
||||
elif self.dots:
|
||||
self.stream.write('.')
|
||||
self.stream.flush()
|
||||
|
||||
def addError(self, test, err):
|
||||
super(TextTestResult, self).addError(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("ERROR")
|
||||
elif self.dots:
|
||||
self.stream.write('E')
|
||||
self.stream.flush()
|
||||
|
||||
def addFailure(self, test, err):
|
||||
super(TextTestResult, self).addFailure(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("FAIL")
|
||||
elif self.dots:
|
||||
self.stream.write('F')
|
||||
self.stream.flush()
|
||||
|
||||
def addSkip(self, test, reason):
|
||||
super(TextTestResult, self).addSkip(test, reason)
|
||||
if self.showAll:
|
||||
self.stream.writeln("skipped %r" % (reason,))
|
||||
elif self.dots:
|
||||
self.stream.write("s")
|
||||
self.stream.flush()
|
||||
|
||||
def addExpectedFailure(self, test, err):
|
||||
super(TextTestResult, self).addExpectedFailure(test, err)
|
||||
if self.showAll:
|
||||
self.stream.writeln("expected failure")
|
||||
elif self.dots:
|
||||
self.stream.write("x")
|
||||
self.stream.flush()
|
||||
|
||||
def addUnexpectedSuccess(self, test):
|
||||
super(TextTestResult, self).addUnexpectedSuccess(test)
|
||||
if self.showAll:
|
||||
self.stream.writeln("unexpected success")
|
||||
elif self.dots:
|
||||
self.stream.write("u")
|
||||
self.stream.flush()
|
||||
|
||||
def printErrors(self):
|
||||
if self.dots or self.showAll:
|
||||
self.stream.writeln()
|
||||
self.printErrorList('ERROR', self.errors)
|
||||
self.printErrorList('FAIL', self.failures)
|
||||
|
||||
def printErrorList(self, flavour, errors):
|
||||
for test, err in errors:
|
||||
self.stream.writeln(self.separator1)
|
||||
self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
|
||||
self.stream.writeln(self.separator2)
|
||||
self.stream.writeln("%s" % err)
|
||||
|
||||
def stopTestRun(self):
|
||||
super(TextTestResult, self).stopTestRun()
|
||||
self.printErrors()
|
||||
|
||||
|
||||
class TextTestRunner(unittest.TextTestRunner):
|
||||
"""A test runner class that displays results in textual form.
|
||||
|
||||
It prints out the names of tests as they are run, errors as they
|
||||
occur, and a summary of the results at the end of the test run.
|
||||
"""
|
||||
resultclass = TextTestResult
|
||||
|
||||
def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
|
||||
failfast=False, buffer=False, resultclass=None):
|
||||
self.stream = _WritelnDecorator(stream)
|
||||
self.descriptions = descriptions
|
||||
self.verbosity = verbosity
|
||||
self.failfast = failfast
|
||||
self.buffer = buffer
|
||||
if resultclass is not None:
|
||||
self.resultclass = resultclass
|
||||
|
||||
def _makeResult(self):
|
||||
return self.resultclass(self.stream, self.descriptions, self.verbosity)
|
||||
|
||||
def run(self, test):
|
||||
"Run the given test case or test suite."
|
||||
result = self._makeResult()
|
||||
result.failfast = self.failfast
|
||||
result.buffer = self.buffer
|
||||
registerResult(result)
|
||||
|
||||
startTime = time.time()
|
||||
startTestRun = getattr(result, 'startTestRun', None)
|
||||
if startTestRun is not None:
|
||||
startTestRun()
|
||||
try:
|
||||
test(result)
|
||||
finally:
|
||||
stopTestRun = getattr(result, 'stopTestRun', None)
|
||||
if stopTestRun is not None:
|
||||
stopTestRun()
|
||||
else:
|
||||
result.printErrors()
|
||||
stopTime = time.time()
|
||||
timeTaken = stopTime - startTime
|
||||
if hasattr(result, 'separator2'):
|
||||
self.stream.writeln(result.separator2)
|
||||
run = result.testsRun
|
||||
self.stream.writeln("Ran %d test%s in %.3fs" %
|
||||
(run, run != 1 and "s" or "", timeTaken))
|
||||
self.stream.writeln()
|
||||
|
||||
expectedFails = unexpectedSuccesses = skipped = 0
|
||||
try:
|
||||
results = map(len, (result.expectedFailures,
|
||||
result.unexpectedSuccesses,
|
||||
result.skipped))
|
||||
expectedFails, unexpectedSuccesses, skipped = results
|
||||
except AttributeError:
|
||||
pass
|
||||
infos = []
|
||||
if not result.wasSuccessful():
|
||||
self.stream.write("FAILED")
|
||||
failed, errored = map(len, (result.failures, result.errors))
|
||||
if failed:
|
||||
infos.append("failures=%d" % failed)
|
||||
if errored:
|
||||
infos.append("errors=%d" % errored)
|
||||
else:
|
||||
self.stream.write("OK")
|
||||
if skipped:
|
||||
infos.append("skipped=%d" % skipped)
|
||||
if expectedFails:
|
||||
infos.append("expected failures=%d" % expectedFails)
|
||||
if unexpectedSuccesses:
|
||||
infos.append("unexpected successes=%d" % unexpectedSuccesses)
|
||||
if infos:
|
||||
self.stream.writeln(" (%s)" % (", ".join(infos),))
|
||||
else:
|
||||
self.stream.write("\n")
|
||||
return result
|
|
@ -0,0 +1,57 @@
|
|||
import signal
|
||||
import weakref
|
||||
|
||||
from django.utils.unittest.compatibility import wraps
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
class _InterruptHandler(object):
|
||||
def __init__(self, default_handler):
|
||||
self.called = False
|
||||
self.default_handler = default_handler
|
||||
|
||||
def __call__(self, signum, frame):
|
||||
installed_handler = signal.getsignal(signal.SIGINT)
|
||||
if installed_handler is not self:
|
||||
# if we aren't the installed handler, then delegate immediately
|
||||
# to the default handler
|
||||
self.default_handler(signum, frame)
|
||||
|
||||
if self.called:
|
||||
self.default_handler(signum, frame)
|
||||
self.called = True
|
||||
for result in _results.keys():
|
||||
result.stop()
|
||||
|
||||
_results = weakref.WeakKeyDictionary()
|
||||
def registerResult(result):
|
||||
_results[result] = 1
|
||||
|
||||
def removeResult(result):
|
||||
return bool(_results.pop(result, None))
|
||||
|
||||
_interrupt_handler = None
|
||||
def installHandler():
|
||||
global _interrupt_handler
|
||||
if _interrupt_handler is None:
|
||||
default_handler = signal.getsignal(signal.SIGINT)
|
||||
_interrupt_handler = _InterruptHandler(default_handler)
|
||||
signal.signal(signal.SIGINT, _interrupt_handler)
|
||||
|
||||
|
||||
def removeHandler(method=None):
|
||||
if method is not None:
|
||||
@wraps(method)
|
||||
def inner(*args, **kwargs):
|
||||
initial = signal.getsignal(signal.SIGINT)
|
||||
removeHandler()
|
||||
try:
|
||||
return method(*args, **kwargs)
|
||||
finally:
|
||||
signal.signal(signal.SIGINT, initial)
|
||||
return inner
|
||||
|
||||
global _interrupt_handler
|
||||
if _interrupt_handler is not None:
|
||||
signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
|
|
@ -0,0 +1,287 @@
|
|||
"""TestSuite"""
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from django.utils.unittest import case, util
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
class BaseTestSuite(unittest.TestSuite):
|
||||
"""A simple test suite that doesn't provide class or module shared fixtures.
|
||||
"""
|
||||
def __init__(self, tests=()):
|
||||
self._tests = []
|
||||
self.addTests(tests)
|
||||
|
||||
def __repr__(self):
|
||||
return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, self.__class__):
|
||||
return NotImplemented
|
||||
return list(self) == list(other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
# Can't guarantee hash invariant, so flag as unhashable
|
||||
__hash__ = None
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._tests)
|
||||
|
||||
def countTestCases(self):
|
||||
cases = 0
|
||||
for test in self:
|
||||
cases += test.countTestCases()
|
||||
return cases
|
||||
|
||||
def addTest(self, test):
|
||||
# sanity checks
|
||||
if not hasattr(test, '__call__'):
|
||||
raise TypeError("%r is not callable" % (repr(test),))
|
||||
if isinstance(test, type) and issubclass(test,
|
||||
(case.TestCase, TestSuite)):
|
||||
raise TypeError("TestCases and TestSuites must be instantiated "
|
||||
"before passing them to addTest()")
|
||||
self._tests.append(test)
|
||||
|
||||
def addTests(self, tests):
|
||||
if isinstance(tests, basestring):
|
||||
raise TypeError("tests must be an iterable of tests, not a string")
|
||||
for test in tests:
|
||||
self.addTest(test)
|
||||
|
||||
def run(self, result):
|
||||
for test in self:
|
||||
if result.shouldStop:
|
||||
break
|
||||
test(result)
|
||||
return result
|
||||
|
||||
def __call__(self, *args, **kwds):
|
||||
return self.run(*args, **kwds)
|
||||
|
||||
def debug(self):
|
||||
"""Run the tests without collecting errors in a TestResult"""
|
||||
for test in self:
|
||||
test.debug()
|
||||
|
||||
|
||||
class TestSuite(BaseTestSuite):
|
||||
"""A test suite is a composite test consisting of a number of TestCases.
|
||||
|
||||
For use, create an instance of TestSuite, then add test case instances.
|
||||
When all tests have been added, the suite can be passed to a test
|
||||
runner, such as TextTestRunner. It will run the individual test cases
|
||||
in the order in which they were added, aggregating the results. When
|
||||
subclassing, do not forget to call the base class constructor.
|
||||
"""
|
||||
|
||||
|
||||
def run(self, result):
|
||||
self._wrapped_run(result)
|
||||
self._tearDownPreviousClass(None, result)
|
||||
self._handleModuleTearDown(result)
|
||||
return result
|
||||
|
||||
def debug(self):
|
||||
"""Run the tests without collecting errors in a TestResult"""
|
||||
debug = _DebugResult()
|
||||
self._wrapped_run(debug, True)
|
||||
self._tearDownPreviousClass(None, debug)
|
||||
self._handleModuleTearDown(debug)
|
||||
|
||||
################################
|
||||
# private methods
|
||||
def _wrapped_run(self, result, debug=False):
|
||||
for test in self:
|
||||
if result.shouldStop:
|
||||
break
|
||||
|
||||
if _isnotsuite(test):
|
||||
self._tearDownPreviousClass(test, result)
|
||||
self._handleModuleFixture(test, result)
|
||||
self._handleClassSetUp(test, result)
|
||||
result._previousTestClass = test.__class__
|
||||
|
||||
if (getattr(test.__class__, '_classSetupFailed', False) or
|
||||
getattr(result, '_moduleSetUpFailed', False)):
|
||||
continue
|
||||
|
||||
if hasattr(test, '_wrapped_run'):
|
||||
test._wrapped_run(result, debug)
|
||||
elif not debug:
|
||||
test(result)
|
||||
else:
|
||||
test.debug()
|
||||
|
||||
def _handleClassSetUp(self, test, result):
|
||||
previousClass = getattr(result, '_previousTestClass', None)
|
||||
currentClass = test.__class__
|
||||
if currentClass == previousClass:
|
||||
return
|
||||
if result._moduleSetUpFailed:
|
||||
return
|
||||
if getattr(currentClass, "__unittest_skip__", False):
|
||||
return
|
||||
|
||||
try:
|
||||
currentClass._classSetupFailed = False
|
||||
except TypeError:
|
||||
# test may actually be a function
|
||||
# so its class will be a builtin-type
|
||||
pass
|
||||
|
||||
setUpClass = getattr(currentClass, 'setUpClass', None)
|
||||
if setUpClass is not None:
|
||||
try:
|
||||
setUpClass()
|
||||
except Exception, e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
currentClass._classSetupFailed = True
|
||||
className = util.strclass(currentClass)
|
||||
errorName = 'setUpClass (%s)' % className
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
|
||||
def _get_previous_module(self, result):
|
||||
previousModule = None
|
||||
previousClass = getattr(result, '_previousTestClass', None)
|
||||
if previousClass is not None:
|
||||
previousModule = previousClass.__module__
|
||||
return previousModule
|
||||
|
||||
|
||||
def _handleModuleFixture(self, test, result):
|
||||
previousModule = self._get_previous_module(result)
|
||||
currentModule = test.__class__.__module__
|
||||
if currentModule == previousModule:
|
||||
return
|
||||
|
||||
self._handleModuleTearDown(result)
|
||||
|
||||
|
||||
result._moduleSetUpFailed = False
|
||||
try:
|
||||
module = sys.modules[currentModule]
|
||||
except KeyError:
|
||||
return
|
||||
setUpModule = getattr(module, 'setUpModule', None)
|
||||
if setUpModule is not None:
|
||||
try:
|
||||
setUpModule()
|
||||
except Exception, e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
result._moduleSetUpFailed = True
|
||||
errorName = 'setUpModule (%s)' % currentModule
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
|
||||
def _addClassOrModuleLevelException(self, result, exception, errorName):
|
||||
error = _ErrorHolder(errorName)
|
||||
addSkip = getattr(result, 'addSkip', None)
|
||||
if addSkip is not None and isinstance(exception, case.SkipTest):
|
||||
addSkip(error, str(exception))
|
||||
else:
|
||||
result.addError(error, sys.exc_info())
|
||||
|
||||
def _handleModuleTearDown(self, result):
|
||||
previousModule = self._get_previous_module(result)
|
||||
if previousModule is None:
|
||||
return
|
||||
if result._moduleSetUpFailed:
|
||||
return
|
||||
|
||||
try:
|
||||
module = sys.modules[previousModule]
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
tearDownModule = getattr(module, 'tearDownModule', None)
|
||||
if tearDownModule is not None:
|
||||
try:
|
||||
tearDownModule()
|
||||
except Exception, e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
errorName = 'tearDownModule (%s)' % previousModule
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
|
||||
def _tearDownPreviousClass(self, test, result):
|
||||
previousClass = getattr(result, '_previousTestClass', None)
|
||||
currentClass = test.__class__
|
||||
if currentClass == previousClass:
|
||||
return
|
||||
if getattr(previousClass, '_classSetupFailed', False):
|
||||
return
|
||||
if getattr(result, '_moduleSetUpFailed', False):
|
||||
return
|
||||
if getattr(previousClass, "__unittest_skip__", False):
|
||||
return
|
||||
|
||||
tearDownClass = getattr(previousClass, 'tearDownClass', None)
|
||||
if tearDownClass is not None:
|
||||
try:
|
||||
tearDownClass()
|
||||
except Exception, e:
|
||||
if isinstance(result, _DebugResult):
|
||||
raise
|
||||
className = util.strclass(previousClass)
|
||||
errorName = 'tearDownClass (%s)' % className
|
||||
self._addClassOrModuleLevelException(result, e, errorName)
|
||||
|
||||
|
||||
class _ErrorHolder(object):
|
||||
"""
|
||||
Placeholder for a TestCase inside a result. As far as a TestResult
|
||||
is concerned, this looks exactly like a unit test. Used to insert
|
||||
arbitrary errors into a test suite run.
|
||||
"""
|
||||
# Inspired by the ErrorHolder from Twisted:
|
||||
# http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
|
||||
|
||||
# attribute used by TestResult._exc_info_to_string
|
||||
failureException = None
|
||||
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
|
||||
def id(self):
|
||||
return self.description
|
||||
|
||||
def shortDescription(self):
|
||||
return None
|
||||
|
||||
def __repr__(self):
|
||||
return "<ErrorHolder description=%r>" % (self.description,)
|
||||
|
||||
def __str__(self):
|
||||
return self.id()
|
||||
|
||||
def run(self, result):
|
||||
# could call result.addError(...) - but this test-like object
|
||||
# shouldn't be run anyway
|
||||
pass
|
||||
|
||||
def __call__(self, result):
|
||||
return self.run(result)
|
||||
|
||||
def countTestCases(self):
|
||||
return 0
|
||||
|
||||
def _isnotsuite(test):
|
||||
"A crude way to tell apart testcases and suites with duck-typing"
|
||||
try:
|
||||
iter(test)
|
||||
except TypeError:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class _DebugResult(object):
|
||||
"Used by the TestSuite to hold previous class when running in debug."
|
||||
_previousTestClass = None
|
||||
_moduleSetUpFailed = False
|
||||
shouldStop = False
|
|
@ -0,0 +1,99 @@
|
|||
"""Various utility functions."""
|
||||
|
||||
__unittest = True
|
||||
|
||||
|
||||
_MAX_LENGTH = 80
|
||||
def safe_repr(obj, short=False):
|
||||
try:
|
||||
result = repr(obj)
|
||||
except Exception:
|
||||
result = object.__repr__(obj)
|
||||
if not short or len(result) < _MAX_LENGTH:
|
||||
return result
|
||||
return result[:_MAX_LENGTH] + ' [truncated]...'
|
||||
|
||||
def safe_str(obj):
|
||||
try:
|
||||
return str(obj)
|
||||
except Exception:
|
||||
return object.__str__(obj)
|
||||
|
||||
def strclass(cls):
|
||||
return "%s.%s" % (cls.__module__, cls.__name__)
|
||||
|
||||
def sorted_list_difference(expected, actual):
|
||||
"""Finds elements in only one or the other of two, sorted input lists.
|
||||
|
||||
Returns a two-element tuple of lists. The first list contains those
|
||||
elements in the "expected" list but not in the "actual" list, and the
|
||||
second contains those elements in the "actual" list but not in the
|
||||
"expected" list. Duplicate elements in either input list are ignored.
|
||||
"""
|
||||
i = j = 0
|
||||
missing = []
|
||||
unexpected = []
|
||||
while True:
|
||||
try:
|
||||
e = expected[i]
|
||||
a = actual[j]
|
||||
if e < a:
|
||||
missing.append(e)
|
||||
i += 1
|
||||
while expected[i] == e:
|
||||
i += 1
|
||||
elif e > a:
|
||||
unexpected.append(a)
|
||||
j += 1
|
||||
while actual[j] == a:
|
||||
j += 1
|
||||
else:
|
||||
i += 1
|
||||
try:
|
||||
while expected[i] == e:
|
||||
i += 1
|
||||
finally:
|
||||
j += 1
|
||||
while actual[j] == a:
|
||||
j += 1
|
||||
except IndexError:
|
||||
missing.extend(expected[i:])
|
||||
unexpected.extend(actual[j:])
|
||||
break
|
||||
return missing, unexpected
|
||||
|
||||
def unorderable_list_difference(expected, actual, ignore_duplicate=False):
|
||||
"""Same behavior as sorted_list_difference but
|
||||
for lists of unorderable items (like dicts).
|
||||
|
||||
As it does a linear search per item (remove) it
|
||||
has O(n*n) performance.
|
||||
"""
|
||||
missing = []
|
||||
unexpected = []
|
||||
while expected:
|
||||
item = expected.pop()
|
||||
try:
|
||||
actual.remove(item)
|
||||
except ValueError:
|
||||
missing.append(item)
|
||||
if ignore_duplicate:
|
||||
for lst in expected, actual:
|
||||
try:
|
||||
while True:
|
||||
lst.remove(item)
|
||||
except ValueError:
|
||||
pass
|
||||
if ignore_duplicate:
|
||||
while actual:
|
||||
item = actual.pop()
|
||||
unexpected.append(item)
|
||||
try:
|
||||
while True:
|
||||
actual.remove(item)
|
||||
except ValueError:
|
||||
pass
|
||||
return missing, unexpected
|
||||
|
||||
# anything left in actual is unexpected
|
||||
return missing, actual
|
|
@ -136,3 +136,31 @@ have been added to Django's own code as well -- most notably, the
|
|||
error emails sent on a HTTP 500 server error are now handled as a
|
||||
logging activity. See :doc:`the documentation on Django's logging
|
||||
interface </topics/logging>` for more details.
|
||||
|
||||
``unittest2`` support
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Python 2.7 introduced some major changes to the unittest library,
|
||||
adding some extremely useful features. To ensure that every Django
|
||||
project can benefit from these new features, Django ships with a
|
||||
copy of unittest2_, a copy of the Python 2.7 unittest library,
|
||||
backported for Python 2.4 compatibility.
|
||||
|
||||
To access this library, Django provides the
|
||||
``django.utils.unittest`` module alias. If you are using Python
|
||||
2.7, or you have installed unittest2 locally, Django will mapt the
|
||||
alias to the installed version of the unittest library Otherwise,
|
||||
Django will use it's own bundled version of unittest2.
|
||||
|
||||
To use this alias, simply use::
|
||||
|
||||
from django.utils import unittest
|
||||
|
||||
wherever you would historically used::
|
||||
|
||||
import unittest
|
||||
|
||||
If you want to continue to use the base unittest libary, you can --
|
||||
you just won't get any of the nice new unittest2 features.
|
||||
|
||||
.. _unittest2: http://pypi.python.org/pypi/unittest2
|
||||
|
|
|
@ -57,8 +57,8 @@ frameworks are:
|
|||
class MyFuncTestCase(unittest.TestCase):
|
||||
def testBasic(self):
|
||||
a = ['larry', 'curly', 'moe']
|
||||
self.assertEquals(my_func(a, 0), 'larry')
|
||||
self.assertEquals(my_func(a, 1), 'curly')
|
||||
self.assertEqual(my_func(a, 0), 'larry')
|
||||
self.assertEqual(my_func(a, 1), 'curly')
|
||||
|
||||
You can choose the test framework you like, depending on which syntax you
|
||||
prefer, or you can mix and match, using one framework for some of your code and
|
||||
|
@ -151,9 +151,38 @@ documentation for doctest`_.
|
|||
Writing unit tests
|
||||
------------------
|
||||
|
||||
Like doctests, Django's unit tests use a standard library module: unittest_.
|
||||
This module uses a different way of defining tests, taking a class-based
|
||||
approach.
|
||||
Like doctests, Django's unit tests use a Python standard library
|
||||
module: unittest_. This module uses a different way of defining tests,
|
||||
taking a class-based approach.
|
||||
|
||||
.. admonition:: unittest2
|
||||
|
||||
.. versionchanged:: 1.3
|
||||
|
||||
Python 2.7 introduced some major changes to the unittest library,
|
||||
adding some extremely useful features. To ensure that every Django
|
||||
project can benefit from these new features, Django ships with a
|
||||
copy of unittest2_, a copy of the Python 2.7 unittest library,
|
||||
backported for Python 2.4 compatibility.
|
||||
|
||||
To access this library, Django provides the
|
||||
``django.utils.unittest`` module alias. If you are using Python
|
||||
2.7, or you have installed unittest2 locally, Django will mapt the
|
||||
alias to the installed version of the unittest library Otherwise,
|
||||
Django will use it's own bundled version of unittest2.
|
||||
|
||||
To use this alias, simply use::
|
||||
|
||||
from django.utils import unittest
|
||||
|
||||
wherever you would historically used::
|
||||
|
||||
import unittest
|
||||
|
||||
If you want to continue to use the base unittest libary, you can --
|
||||
you just won't get any of the nice new unittest2 features.
|
||||
|
||||
.. _unittest2: http://pypi.python.org/pypi/unittest2
|
||||
|
||||
As with doctests, for a given Django application, the test runner looks for
|
||||
unit tests in two places:
|
||||
|
@ -168,7 +197,7 @@ unit tests in two places:
|
|||
This example ``unittest.TestCase`` subclass is equivalent to the example given
|
||||
in the doctest section above::
|
||||
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
from myapp.models import Animal
|
||||
|
||||
class AnimalTestCase(unittest.TestCase):
|
||||
|
@ -177,8 +206,8 @@ in the doctest section above::
|
|||
self.cat = Animal.objects.create(name="cat", sound="meow")
|
||||
|
||||
def testSpeaking(self):
|
||||
self.assertEquals(self.lion.speak(), 'The lion says "roar"')
|
||||
self.assertEquals(self.cat.speak(), 'The cat says "meow"')
|
||||
self.assertEqual(self.lion.speak(), 'The lion says "roar"')
|
||||
self.assertEqual(self.cat.speak(), 'The cat says "meow"')
|
||||
|
||||
When you :ref:`run your tests <running-tests>`, the default behavior of the
|
||||
test utility is to find all the test cases (that is, subclasses of
|
||||
|
@ -199,6 +228,7 @@ documentation`_.
|
|||
.. _standard library unittest documentation: unittest_
|
||||
.. _suggested organization: http://docs.python.org/library/unittest.html#organizing-tests
|
||||
|
||||
|
||||
Which should I use?
|
||||
-------------------
|
||||
|
||||
|
@ -231,6 +261,8 @@ you:
|
|||
routines, which give you a high level of control over the environment
|
||||
in which your test cases are run.
|
||||
|
||||
* If you're writing tests for Django itself, you should use ``unittest``.
|
||||
|
||||
Again, remember that you can use both systems side-by-side (even in the same
|
||||
app). In the end, most projects will eventually end up using both. Each shines
|
||||
in different circumstances.
|
||||
|
@ -964,7 +996,7 @@ Example
|
|||
|
||||
The following is a simple unit test using the test client::
|
||||
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
from django.test.client import Client
|
||||
|
||||
class SimpleTest(unittest.TestCase):
|
||||
|
@ -977,10 +1009,10 @@ The following is a simple unit test using the test client::
|
|||
response = self.client.get('/customer/details/')
|
||||
|
||||
# Check that the response is 200 OK.
|
||||
self.failUnlessEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Check that the rendered context contains 5 customers.
|
||||
self.failUnlessEqual(len(response.context['customers']), 5)
|
||||
self.assertEqual(len(response.context['customers']), 5)
|
||||
|
||||
TestCase
|
||||
--------
|
||||
|
@ -1061,19 +1093,19 @@ worry about state (such as cookies) carrying over from one test to another.
|
|||
|
||||
This means, instead of instantiating a ``Client`` in each test::
|
||||
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
from django.test.client import Client
|
||||
|
||||
class SimpleTest(unittest.TestCase):
|
||||
def test_details(self):
|
||||
client = Client()
|
||||
response = client.get('/customer/details/')
|
||||
self.failUnlessEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_index(self):
|
||||
client = Client()
|
||||
response = client.get('/customer/index/')
|
||||
self.failUnlessEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
...you can just refer to ``self.client``, like so::
|
||||
|
||||
|
@ -1082,11 +1114,11 @@ This means, instead of instantiating a ``Client`` in each test::
|
|||
class SimpleTest(TestCase):
|
||||
def test_details(self):
|
||||
response = self.client.get('/customer/details/')
|
||||
self.failUnlessEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_index(self):
|
||||
response = self.client.get('/customer/index/')
|
||||
self.failUnlessEqual(response.status_code, 200)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
Customizing the test client
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -1265,7 +1297,7 @@ Assertions
|
|||
Addded ``msg_prefix`` argument.
|
||||
|
||||
As Python's normal ``unittest.TestCase`` class implements assertion methods
|
||||
such as ``assertTrue`` and ``assertEquals``, Django's custom ``TestCase`` class
|
||||
such as ``assertTrue`` and ``assertEqual``, Django's custom ``TestCase`` class
|
||||
provides a number of custom assertion methods that are useful for testing Web
|
||||
applications:
|
||||
|
||||
|
@ -1385,10 +1417,10 @@ and contents::
|
|||
fail_silently=False)
|
||||
|
||||
# Test that one message has been sent.
|
||||
self.assertEquals(len(mail.outbox), 1)
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
|
||||
# Verify that the subject of the first message is correct.
|
||||
self.assertEquals(mail.outbox[0].subject, 'Subject here')
|
||||
self.assertEqual(mail.outbox[0].subject, 'Subject here')
|
||||
|
||||
As noted :ref:`previously <emptying-test-outbox>`, the test outbox is emptied
|
||||
at the start of every test in a Django ``TestCase``. To empty the outbox
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
This is a basic model with only two non-primary-key fields.
|
||||
"""
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db import models, DEFAULT_DB_ALIAS, connection
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(max_length=100, default='Default headline')
|
||||
|
@ -359,9 +359,7 @@ AttributeError: Manager isn't accessible via Article instances
|
|||
|
||||
from django.conf import settings
|
||||
|
||||
building_docs = getattr(settings, 'BUILDING_DOCS', False)
|
||||
|
||||
if building_docs or settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.postgresql':
|
||||
if connection.features.supports_microsecond_precision:
|
||||
__test__['API_TESTS'] += """
|
||||
# In PostgreSQL, microsecond-level precision is available.
|
||||
>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
|
||||
|
@ -369,8 +367,7 @@ if building_docs or settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db
|
|||
>>> Article.objects.get(id__exact=9).pub_date
|
||||
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
|
||||
"""
|
||||
|
||||
if building_docs or settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.mysql':
|
||||
else:
|
||||
__test__['API_TESTS'] += """
|
||||
# In MySQL, microsecond-level precision isn't available. You'll lose
|
||||
# microsecond-level precision once the data is saved.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from django.conf import settings
|
||||
from django.db import DEFAULT_DB_ALIAS, transaction, IntegrityError
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipIfDBFeature
|
||||
|
||||
from models import Employee, Business, Bar, Foo
|
||||
|
||||
|
@ -168,16 +168,15 @@ class CustomPKTests(TestCase):
|
|||
self.assertEqual(f, new_foo),
|
||||
self.assertEqual(f.bar, new_bar)
|
||||
|
||||
|
||||
# SQLite lets objects be saved with an empty primary key, even though an
|
||||
# integer is expected. So we can't check for an error being raised in that
|
||||
# case for SQLite. Remove it from the suite for this next bit.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.sqlite3':
|
||||
def test_required_pk(self):
|
||||
# The primary key must be specified, so an error is raised if you
|
||||
# try to create an object without it.
|
||||
sid = transaction.savepoint()
|
||||
self.assertRaises(IntegrityError,
|
||||
Employee.objects.create, first_name="Tom", last_name="Smith"
|
||||
)
|
||||
transaction.savepoint_rollback(sid)
|
||||
@skipIfDBFeature('supports_unspecified_pk')
|
||||
def test_required_pk(self):
|
||||
# The primary key must be specified, so an error is raised if you
|
||||
# try to create an object without it.
|
||||
sid = transaction.savepoint()
|
||||
self.assertRaises(IntegrityError,
|
||||
Employee.objects.create, first_name="Tom", last_name="Smith"
|
||||
)
|
||||
transaction.savepoint_rollback(sid)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import StringIO
|
||||
import sys
|
||||
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
from django.conf import settings
|
||||
from django.core import management
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
|
||||
|
||||
from models import Article, Blog, Book, Category, Person, Spy, Tag, Visa
|
||||
|
||||
|
||||
class TestCaseFixtureLoadingTests(TestCase):
|
||||
fixtures = ['fixture1.json', 'fixture2.json']
|
||||
|
||||
|
@ -291,46 +292,46 @@ class FixtureLoadingTests(TestCase):
|
|||
self._dumpdata_assert(['fixtures'], """<?xml version="1.0" encoding="utf-8"?>
|
||||
<django-objects version="1.0"><object pk="1" model="fixtures.category"><field type="CharField" name="title">News Stories</field><field type="TextField" name="description">Latest news stories</field></object><object pk="3" model="fixtures.article"><field type="CharField" name="headline">Time to reform copyright</field><field type="DateTimeField" name="pub_date">2006-06-16 13:00:00</field></object><object pk="2" model="fixtures.article"><field type="CharField" name="headline">Poker has no place on ESPN</field><field type="DateTimeField" name="pub_date">2006-06-16 12:00:00</field></object><object pk="1" model="fixtures.article"><field type="CharField" name="headline">Python program becomes self aware</field><field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field></object><object pk="1" model="fixtures.tag"><field type="CharField" name="name">copyright</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="2" model="fixtures.tag"><field type="CharField" name="name">law</field><field to="contenttypes.contenttype" name="tagged_type" rel="ManyToOneRel"><natural>fixtures</natural><natural>article</natural></field><field type="PositiveIntegerField" name="tagged_id">3</field></object><object pk="1" model="fixtures.person"><field type="CharField" name="name">Django Reinhardt</field></object><object pk="3" model="fixtures.person"><field type="CharField" name="name">Prince</field></object><object pk="2" model="fixtures.person"><field type="CharField" name="name">Stephane Grappelli</field></object></django-objects>""", format='xml', natural_keys=True)
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
|
||||
class FixtureTransactionTests(TransactionTestCase):
|
||||
def _dumpdata_assert(self, args, output, format='json'):
|
||||
new_io = StringIO.StringIO()
|
||||
management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io})
|
||||
command_output = new_io.getvalue().strip()
|
||||
self.assertEqual(command_output, output)
|
||||
class FixtureTransactionTests(TransactionTestCase):
|
||||
def _dumpdata_assert(self, args, output, format='json'):
|
||||
new_io = StringIO.StringIO()
|
||||
management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io})
|
||||
command_output = new_io.getvalue().strip()
|
||||
self.assertEqual(command_output, output)
|
||||
|
||||
def test_format_discovery(self):
|
||||
# Load fixture 1 again, using format discovery
|
||||
management.call_command('loaddata', 'fixture1', verbosity=0, commit=False)
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
@skipUnlessDBFeature('supports_forward_references')
|
||||
def test_format_discovery(self):
|
||||
# Load fixture 1 again, using format discovery
|
||||
management.call_command('loaddata', 'fixture1', verbosity=0, commit=False)
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
|
||||
# Try to load fixture 2 using format discovery; this will fail
|
||||
# because there are two fixture2's in the fixtures directory
|
||||
new_io = StringIO.StringIO()
|
||||
management.call_command('loaddata', 'fixture2', verbosity=0, stderr=new_io)
|
||||
output = new_io.getvalue().strip().split('\n')
|
||||
self.assertEqual(len(output), 1)
|
||||
self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture2'"))
|
||||
# Try to load fixture 2 using format discovery; this will fail
|
||||
# because there are two fixture2's in the fixtures directory
|
||||
new_io = StringIO.StringIO()
|
||||
management.call_command('loaddata', 'fixture2', verbosity=0, stderr=new_io)
|
||||
output = new_io.getvalue().strip().split('\n')
|
||||
self.assertEqual(len(output), 1)
|
||||
self.assertTrue(output[0].startswith("Multiple fixtures named 'fixture2'"))
|
||||
|
||||
# object list is unaffected
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
# object list is unaffected
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
|
||||
# Dump the current contents of the database as a JSON fixture
|
||||
self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]')
|
||||
# Dump the current contents of the database as a JSON fixture
|
||||
self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": 1, "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]')
|
||||
|
||||
# Load fixture 4 (compressed), using format discovery
|
||||
management.call_command('loaddata', 'fixture4', verbosity=0, commit=False)
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Django pets kitten>',
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
# Load fixture 4 (compressed), using format discovery
|
||||
management.call_command('loaddata', 'fixture4', verbosity=0, commit=False)
|
||||
self.assertQuerysetEqual(Article.objects.all(), [
|
||||
'<Article: Django pets kitten>',
|
||||
'<Article: Time to reform copyright>',
|
||||
'<Article: Poker has no place on ESPN>',
|
||||
'<Article: Python program becomes self aware>'
|
||||
])
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
This demonstrates features of the database API.
|
||||
"""
|
||||
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db import models, DEFAULT_DB_ALIAS, connection
|
||||
from django.conf import settings
|
||||
|
||||
class Article(models.Model):
|
||||
|
@ -41,15 +41,16 @@ False
|
|||
# There should be some now!
|
||||
>>> Article.objects.exists()
|
||||
True
|
||||
"""}
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] in (
|
||||
'django.db.backends.postgresql',
|
||||
'django.db.backends.postgresql_pysycopg2'):
|
||||
__test__['API_TESTS'] += r"""
|
||||
# text matching tests for PostgreSQL 8.3
|
||||
# Integer value can be queried using string
|
||||
>>> Article.objects.filter(id__iexact='1')
|
||||
[<Article: Article 1>]
|
||||
|
||||
"""}
|
||||
|
||||
if connection.features.supports_date_lookup_using_string:
|
||||
__test__['API_TESTS'] += r"""
|
||||
# A date lookup can be performed using a string search
|
||||
>>> Article.objects.filter(pub_date__startswith='2005')
|
||||
[<Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||
"""
|
||||
|
@ -409,7 +410,7 @@ FieldError: Join on field 'headline' not permitted. Did you misspell 'starts' fo
|
|||
"""
|
||||
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
|
||||
if connection.features.supports_regex_backreferencing:
|
||||
__test__['API_TESTS'] += r"""
|
||||
# grouping and backreferences
|
||||
>>> Article.objects.filter(headline__regex=r'b(.).*b\1')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Validate that you can override the default test suite
|
||||
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
|
||||
def suite():
|
||||
"""
|
||||
|
|
|
@ -1,155 +1,159 @@
|
|||
from django.test import TransactionTestCase
|
||||
from django.db import connection, transaction, IntegrityError, DEFAULT_DB_ALIAS
|
||||
from django.conf import settings
|
||||
from django.test import TransactionTestCase, skipUnlessDBFeature
|
||||
|
||||
from models import Reporter
|
||||
|
||||
PGSQL = 'psycopg2' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE']
|
||||
MYSQL = 'mysql' in settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE']
|
||||
|
||||
class TransactionTests(TransactionTestCase):
|
||||
def create_a_reporter_then_fail(self, first, last):
|
||||
a = Reporter(first_name=first, last_name=last)
|
||||
a.save()
|
||||
raise Exception("I meant to do that")
|
||||
|
||||
if not MYSQL:
|
||||
def remove_a_reporter(self, first_name):
|
||||
r = Reporter.objects.get(first_name="Alice")
|
||||
r.delete()
|
||||
|
||||
def create_a_reporter_then_fail(self, first, last):
|
||||
a = Reporter(first_name=first, last_name=last)
|
||||
a.save()
|
||||
raise Exception("I meant to do that")
|
||||
def manually_managed(self):
|
||||
r = Reporter(first_name="Dirk", last_name="Gently")
|
||||
r.save()
|
||||
transaction.commit()
|
||||
|
||||
def remove_a_reporter(self, first_name):
|
||||
r = Reporter.objects.get(first_name="Alice")
|
||||
r.delete()
|
||||
def manually_managed_mistake(self):
|
||||
r = Reporter(first_name="Edward", last_name="Woodward")
|
||||
r.save()
|
||||
# Oops, I forgot to commit/rollback!
|
||||
|
||||
def manually_managed(self):
|
||||
r = Reporter(first_name="Dirk", last_name="Gently")
|
||||
r.save()
|
||||
transaction.commit()
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_autocommit(self):
|
||||
"""
|
||||
The default behavior is to autocommit after each save() action.
|
||||
"""
|
||||
self.assertRaises(Exception,
|
||||
self.create_a_reporter_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
|
||||
def manually_managed_mistake(self):
|
||||
r = Reporter(first_name="Edward", last_name="Woodward")
|
||||
r.save()
|
||||
# Oops, I forgot to commit/rollback!
|
||||
# The object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
|
||||
def execute_bad_sql(self):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');")
|
||||
transaction.set_dirty()
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_autocommit_decorator(self):
|
||||
"""
|
||||
The autocommit decorator works exactly the same as the default behavior.
|
||||
"""
|
||||
autocomitted_create_then_fail = transaction.autocommit(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
autocomitted_create_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
# Again, the object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
|
||||
def test_autocommit(self):
|
||||
"""
|
||||
The default behavior is to autocommit after each save() action.
|
||||
"""
|
||||
self.assertRaises(Exception,
|
||||
self.create_a_reporter_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_autocommit_decorator_with_using(self):
|
||||
"""
|
||||
The autocommit decorator also works with a using argument.
|
||||
"""
|
||||
autocomitted_create_then_fail = transaction.autocommit(using='default')(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
autocomitted_create_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
# Again, the object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
|
||||
# The object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_commit_on_success(self):
|
||||
"""
|
||||
With the commit_on_success decorator, the transaction is only committed
|
||||
if the function doesn't throw an exception.
|
||||
"""
|
||||
committed_on_success = transaction.commit_on_success(
|
||||
self.create_a_reporter_then_fail)
|
||||
self.assertRaises(Exception, committed_on_success, "Dirk", "Gently")
|
||||
# This time the object never got saved
|
||||
self.assertEqual(Reporter.objects.count(), 0)
|
||||
|
||||
def test_autocommit_decorator(self):
|
||||
"""
|
||||
The autocommit decorator works exactly the same as the default behavior.
|
||||
"""
|
||||
autocomitted_create_then_fail = transaction.autocommit(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
autocomitted_create_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
# Again, the object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_commit_on_success_with_using(self):
|
||||
"""
|
||||
The commit_on_success decorator also works with a using argument.
|
||||
"""
|
||||
using_committed_on_success = transaction.commit_on_success(using='default')(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
using_committed_on_success,
|
||||
"Dirk", "Gently"
|
||||
)
|
||||
# This time the object never got saved
|
||||
self.assertEqual(Reporter.objects.count(), 0)
|
||||
|
||||
def test_autocommit_decorator_with_using(self):
|
||||
"""
|
||||
The autocommit decorator also works with a using argument.
|
||||
"""
|
||||
autocomitted_create_then_fail = transaction.autocommit(using='default')(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
autocomitted_create_then_fail,
|
||||
"Alice", "Smith"
|
||||
)
|
||||
# Again, the object created before the exception still exists
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_commit_on_success_succeed(self):
|
||||
"""
|
||||
If there aren't any exceptions, the data will get saved.
|
||||
"""
|
||||
Reporter.objects.create(first_name="Alice", last_name="Smith")
|
||||
remove_comitted_on_success = transaction.commit_on_success(
|
||||
self.remove_a_reporter
|
||||
)
|
||||
remove_comitted_on_success("Alice")
|
||||
self.assertEqual(list(Reporter.objects.all()), [])
|
||||
|
||||
def test_commit_on_success(self):
|
||||
"""
|
||||
With the commit_on_success decorator, the transaction is only committed
|
||||
if the function doesn't throw an exception.
|
||||
"""
|
||||
committed_on_success = transaction.commit_on_success(
|
||||
self.create_a_reporter_then_fail)
|
||||
self.assertRaises(Exception, committed_on_success, "Dirk", "Gently")
|
||||
# This time the object never got saved
|
||||
self.assertEqual(Reporter.objects.count(), 0)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_manually_managed(self):
|
||||
"""
|
||||
You can manually manage transactions if you really want to, but you
|
||||
have to remember to commit/rollback.
|
||||
"""
|
||||
manually_managed = transaction.commit_manually(self.manually_managed)
|
||||
manually_managed()
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
|
||||
def test_commit_on_success_with_using(self):
|
||||
"""
|
||||
The commit_on_success decorator also works with a using argument.
|
||||
"""
|
||||
using_committed_on_success = transaction.commit_on_success(using='default')(
|
||||
self.create_a_reporter_then_fail
|
||||
)
|
||||
self.assertRaises(Exception,
|
||||
using_committed_on_success,
|
||||
"Dirk", "Gently"
|
||||
)
|
||||
# This time the object never got saved
|
||||
self.assertEqual(Reporter.objects.count(), 0)
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_manually_managed_mistake(self):
|
||||
"""
|
||||
If you forget, you'll get bad errors.
|
||||
"""
|
||||
manually_managed_mistake = transaction.commit_manually(
|
||||
self.manually_managed_mistake
|
||||
)
|
||||
self.assertRaises(transaction.TransactionManagementError,
|
||||
manually_managed_mistake)
|
||||
|
||||
def test_commit_on_success_succeed(self):
|
||||
"""
|
||||
If there aren't any exceptions, the data will get saved.
|
||||
"""
|
||||
Reporter.objects.create(first_name="Alice", last_name="Smith")
|
||||
remove_comitted_on_success = transaction.commit_on_success(
|
||||
self.remove_a_reporter
|
||||
)
|
||||
remove_comitted_on_success("Alice")
|
||||
self.assertEqual(list(Reporter.objects.all()), [])
|
||||
@skipUnlessDBFeature('supports_transactions')
|
||||
def test_manually_managed_with_using(self):
|
||||
"""
|
||||
The commit_manually function also works with a using argument.
|
||||
"""
|
||||
using_manually_managed_mistake = transaction.commit_manually(using='default')(
|
||||
self.manually_managed_mistake
|
||||
)
|
||||
self.assertRaises(transaction.TransactionManagementError,
|
||||
using_manually_managed_mistake
|
||||
)
|
||||
|
||||
def test_manually_managed(self):
|
||||
"""
|
||||
You can manually manage transactions if you really want to, but you
|
||||
have to remember to commit/rollback.
|
||||
"""
|
||||
manually_managed = transaction.commit_manually(self.manually_managed)
|
||||
manually_managed()
|
||||
self.assertEqual(Reporter.objects.count(), 1)
|
||||
class TransactionRollbackTests(TransactionTestCase):
|
||||
def execute_bad_sql(self):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("INSERT INTO transactions_reporter (first_name, last_name) VALUES ('Douglas', 'Adams');")
|
||||
transaction.set_dirty()
|
||||
|
||||
def test_manually_managed_mistake(self):
|
||||
"""
|
||||
If you forget, you'll get bad errors.
|
||||
"""
|
||||
manually_managed_mistake = transaction.commit_manually(
|
||||
self.manually_managed_mistake
|
||||
)
|
||||
self.assertRaises(transaction.TransactionManagementError,
|
||||
manually_managed_mistake)
|
||||
|
||||
def test_manually_managed_with_using(self):
|
||||
"""
|
||||
The commit_manually function also works with a using argument.
|
||||
"""
|
||||
using_manually_managed_mistake = transaction.commit_manually(using='default')(
|
||||
self.manually_managed_mistake
|
||||
)
|
||||
self.assertRaises(transaction.TransactionManagementError,
|
||||
using_manually_managed_mistake
|
||||
)
|
||||
|
||||
if PGSQL:
|
||||
|
||||
def test_bad_sql(self):
|
||||
"""
|
||||
Regression for #11900: If a function wrapped by commit_on_success
|
||||
writes a transaction that can't be committed, that transaction should
|
||||
be rolled back. The bug is only visible using the psycopg2 backend,
|
||||
though the fix is generally a good idea.
|
||||
"""
|
||||
execute_bad_sql = transaction.commit_on_success(self.execute_bad_sql)
|
||||
self.assertRaises(IntegrityError, execute_bad_sql)
|
||||
transaction.rollback()
|
||||
@skipUnlessDBFeature('requires_rollback_on_dirty_transaction')
|
||||
def test_bad_sql(self):
|
||||
"""
|
||||
Regression for #11900: If a function wrapped by commit_on_success
|
||||
writes a transaction that can't be committed, that transaction should
|
||||
be rolled back. The bug is only visible using the psycopg2 backend,
|
||||
though the fix is generally a good idea.
|
||||
"""
|
||||
execute_bad_sql = transaction.commit_on_success(self.execute_bad_sql)
|
||||
self.assertRaises(IntegrityError, execute_bad_sql)
|
||||
transaction.rollback()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import unittest
|
||||
from django.utils import unittest
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import unittest
|
||||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import connection
|
||||
from django.utils import unittest
|
||||
|
||||
from models import CustomPKModel, UniqueTogetherModel, UniqueFieldsModel, UniqueForDateModel, ModelToValidate
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from unittest import TestCase
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
from modeltests.validation import ValidationTestCase
|
||||
from models import *
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import types
|
||||
from unittest import TestCase
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import *
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
NOW = datetime.now()
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ advertised - especially with regards to the handling of the DJANGO_SETTINGS_MODU
|
|||
and default settings.py files.
|
||||
"""
|
||||
import os
|
||||
import unittest
|
||||
import shutil
|
||||
import sys
|
||||
import re
|
||||
|
||||
from django import conf, bin, get_version
|
||||
from django.conf import settings
|
||||
from django.utils import unittest
|
||||
|
||||
class AdminScriptTestCase(unittest.TestCase):
|
||||
def write_settings(self, filename, apps=None, is_dir=False, sdict=None):
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
from datetime import datetime
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.formats import localize
|
||||
from django.test import TestCase
|
||||
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin.util import display_for_field, label_for_field, lookup_field
|
||||
from django.contrib.admin.util import NestedObjects
|
||||
from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.admin.util import NestedObjects
|
||||
from django.db import models
|
||||
from django.test import TestCase
|
||||
from django.utils import unittest
|
||||
from django.utils.formats import localize
|
||||
|
||||
from models import Article, Count
|
||||
|
||||
|
|
|
@ -12,13 +12,14 @@ from django.contrib.admin.sites import LOGIN_FORM_KEY
|
|||
from django.contrib.admin.util import quote
|
||||
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
|
||||
from django.forms.util import ErrorList
|
||||
import django.template.context
|
||||
from django.test import TestCase
|
||||
from django.utils import formats
|
||||
from django.utils.cache import get_max_age
|
||||
from django.utils.encoding import iri_to_uri
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import get_date_formats, activate, deactivate
|
||||
import django.template.context
|
||||
from django.utils import unittest
|
||||
|
||||
# local test models
|
||||
from models import Article, BarAccount, CustomArticle, EmptyModel, \
|
||||
|
@ -2210,51 +2211,52 @@ class UserAdminTest(TestCase):
|
|||
self.assertNotEquals(new_user.password, UNUSABLE_PASSWORD)
|
||||
|
||||
try:
|
||||
# If docutils isn't installed, skip the AdminDocs tests.
|
||||
import docutils
|
||||
|
||||
class AdminDocsTest(TestCase):
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
def setUp(self):
|
||||
self.client.login(username='super', password='secret')
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_tags(self):
|
||||
response = self.client.get('/test_admin/admin/doc/tags/')
|
||||
|
||||
# The builtin tag group exists
|
||||
self.assertContains(response, "<h2>Built-in tags</h2>", count=2)
|
||||
|
||||
# A builtin tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="built_in-autoescape">autoescape</h3>')
|
||||
self.assertContains(response, '<li><a href="#built_in-autoescape">autoescape</a></li>')
|
||||
|
||||
# An app tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="flatpages-get_flatpages">get_flatpages</h3>')
|
||||
self.assertContains(response, '<li><a href="#flatpages-get_flatpages">get_flatpages</a></li>')
|
||||
|
||||
# The admin list tag group exists
|
||||
self.assertContains(response, "<h2>admin_list</h2>", count=2)
|
||||
|
||||
# An admin list tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="admin_list-admin_actions">admin_actions</h3>')
|
||||
self.assertContains(response, '<li><a href="#admin_list-admin_actions">admin_actions</a></li>')
|
||||
|
||||
def test_filters(self):
|
||||
response = self.client.get('/test_admin/admin/doc/filters/')
|
||||
|
||||
# The builtin filter group exists
|
||||
self.assertContains(response, "<h2>Built-in filters</h2>", count=2)
|
||||
|
||||
# A builtin filter exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="built_in-add">add</h3>')
|
||||
self.assertContains(response, '<li><a href="#built_in-add">add</a></li>')
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
docutils = None
|
||||
|
||||
#@unittest.skipUnless(docutils, "no docutils installed.")
|
||||
class AdminDocsTest(TestCase):
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
||||
def setUp(self):
|
||||
self.client.login(username='super', password='secret')
|
||||
|
||||
def tearDown(self):
|
||||
self.client.logout()
|
||||
|
||||
def test_tags(self):
|
||||
response = self.client.get('/test_admin/admin/doc/tags/')
|
||||
|
||||
# The builtin tag group exists
|
||||
self.assertContains(response, "<h2>Built-in tags</h2>", count=2)
|
||||
|
||||
# A builtin tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="built_in-autoescape">autoescape</h3>')
|
||||
self.assertContains(response, '<li><a href="#built_in-autoescape">autoescape</a></li>')
|
||||
|
||||
# An app tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="flatpages-get_flatpages">get_flatpages</h3>')
|
||||
self.assertContains(response, '<li><a href="#flatpages-get_flatpages">get_flatpages</a></li>')
|
||||
|
||||
# The admin list tag group exists
|
||||
self.assertContains(response, "<h2>admin_list</h2>", count=2)
|
||||
|
||||
# An admin list tag exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="admin_list-admin_actions">admin_actions</h3>')
|
||||
self.assertContains(response, '<li><a href="#admin_list-admin_actions">admin_actions</a></li>')
|
||||
|
||||
def test_filters(self):
|
||||
response = self.client.get('/test_admin/admin/doc/filters/')
|
||||
|
||||
# The builtin filter group exists
|
||||
self.assertContains(response, "<h2>Built-in filters</h2>", count=2)
|
||||
|
||||
# A builtin filter exists in both the index and detail
|
||||
self.assertContains(response, '<h3 id="built_in-add">add</h3>')
|
||||
self.assertContains(response, '<li><a href="#built_in-add">add</a></li>')
|
||||
|
||||
AdminDocsTest = unittest.skipUnless(docutils, "no docutils installed.")(AdminDocsTest)
|
||||
|
||||
class ValidXHTMLTests(TestCase):
|
||||
fixtures = ['admin-views-users.xml']
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
from django import forms
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin import widgets
|
||||
from unittest import TestCase
|
||||
from django.test import TestCase as DjangoTestCase
|
||||
from django.db.models import DateField
|
||||
from django.test import TestCase as DjangoTestCase
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
import models
|
||||
|
||||
class AdminFormfieldForDBFieldTests(TestCase):
|
||||
|
|
|
@ -3,32 +3,13 @@ from decimal import Decimal
|
|||
|
||||
from django.core.exceptions import FieldError
|
||||
from django.conf import settings
|
||||
from django.test import TestCase, Approximate
|
||||
from django.test import TestCase, Approximate, skipUnlessDBFeature
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
from django.db.models import Count, Max, Avg, Sum, StdDev, Variance, F
|
||||
|
||||
from regressiontests.aggregation_regress.models import *
|
||||
|
||||
|
||||
def run_stddev_tests():
|
||||
"""Check to see if StdDev/Variance tests should be run.
|
||||
|
||||
Stddev and Variance are not guaranteed to be available for SQLite, and
|
||||
are not available for PostgreSQL before 8.2.
|
||||
"""
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.sqlite3':
|
||||
return False
|
||||
|
||||
class StdDevPop(object):
|
||||
sql_function = 'STDDEV_POP'
|
||||
|
||||
try:
|
||||
connection.ops.check_aggregate_support(StdDevPop())
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class AggregationTests(TestCase):
|
||||
def assertObjectAttrs(self, obj, **kwargs):
|
||||
for attr, value in kwargs.iteritems():
|
||||
|
@ -75,27 +56,27 @@ class AggregationTests(TestCase):
|
|||
qs2 = books.filter(id__in=list(qs))
|
||||
self.assertEqual(list(qs1), list(qs2))
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.oracle':
|
||||
def test_annotate_with_extra(self):
|
||||
"""
|
||||
Regression test for #11916: Extra params + aggregation creates
|
||||
incorrect SQL.
|
||||
"""
|
||||
#oracle doesn't support subqueries in group by clause
|
||||
shortest_book_sql = """
|
||||
SELECT name
|
||||
FROM aggregation_regress_book b
|
||||
WHERE b.publisher_id = aggregation_regress_publisher.id
|
||||
ORDER BY b.pages
|
||||
LIMIT 1
|
||||
"""
|
||||
# tests that this query does not raise a DatabaseError due to the full
|
||||
# subselect being (erroneously) added to the GROUP BY parameters
|
||||
qs = Publisher.objects.extra(select={
|
||||
'name_of_shortest_book': shortest_book_sql,
|
||||
}).annotate(total_books=Count('book'))
|
||||
# force execution of the query
|
||||
list(qs)
|
||||
@skipUnlessDBFeature('supports_subqueries_in_group_by')
|
||||
def test_annotate_with_extra(self):
|
||||
"""
|
||||
Regression test for #11916: Extra params + aggregation creates
|
||||
incorrect SQL.
|
||||
"""
|
||||
#oracle doesn't support subqueries in group by clause
|
||||
shortest_book_sql = """
|
||||
SELECT name
|
||||
FROM aggregation_regress_book b
|
||||
WHERE b.publisher_id = aggregation_regress_publisher.id
|
||||
ORDER BY b.pages
|
||||
LIMIT 1
|
||||
"""
|
||||
# tests that this query does not raise a DatabaseError due to the full
|
||||
# subselect being (erroneously) added to the GROUP BY parameters
|
||||
qs = Publisher.objects.extra(select={
|
||||
'name_of_shortest_book': shortest_book_sql,
|
||||
}).annotate(total_books=Count('book'))
|
||||
# force execution of the query
|
||||
list(qs)
|
||||
|
||||
def test_aggregate(self):
|
||||
# Ordering requests are ignored
|
||||
|
@ -641,64 +622,64 @@ class AggregationTests(TestCase):
|
|||
lambda: Book.objects.annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age'))
|
||||
)
|
||||
|
||||
if run_stddev_tests():
|
||||
def test_stddev(self):
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('pages')),
|
||||
{'pages__stddev': Approximate(311.46, 1)}
|
||||
)
|
||||
@skipUnlessDBFeature('supports_stddev')
|
||||
def test_stddev(self):
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('pages')),
|
||||
{'pages__stddev': Approximate(311.46, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('rating')),
|
||||
{'rating__stddev': Approximate(0.60, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('rating')),
|
||||
{'rating__stddev': Approximate(0.60, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('price')),
|
||||
{'price__stddev': Approximate(24.16, 2)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('price')),
|
||||
{'price__stddev': Approximate(24.16, 2)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('pages', sample=True)),
|
||||
{'pages__stddev': Approximate(341.19, 2)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('pages', sample=True)),
|
||||
{'pages__stddev': Approximate(341.19, 2)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('rating', sample=True)),
|
||||
{'rating__stddev': Approximate(0.66, 2)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('rating', sample=True)),
|
||||
{'rating__stddev': Approximate(0.66, 2)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('price', sample=True)),
|
||||
{'price__stddev': Approximate(26.46, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(StdDev('price', sample=True)),
|
||||
{'price__stddev': Approximate(26.46, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('pages')),
|
||||
{'pages__variance': Approximate(97010.80, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('pages')),
|
||||
{'pages__variance': Approximate(97010.80, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('rating')),
|
||||
{'rating__variance': Approximate(0.36, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('rating')),
|
||||
{'rating__variance': Approximate(0.36, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('price')),
|
||||
{'price__variance': Approximate(583.77, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('price')),
|
||||
{'price__variance': Approximate(583.77, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('pages', sample=True)),
|
||||
{'pages__variance': Approximate(116412.96, 1)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('pages', sample=True)),
|
||||
{'pages__variance': Approximate(116412.96, 1)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('rating', sample=True)),
|
||||
{'rating__variance': Approximate(0.44, 2)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('rating', sample=True)),
|
||||
{'rating__variance': Approximate(0.44, 2)}
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('price', sample=True)),
|
||||
{'price__variance': Approximate(700.53, 2)}
|
||||
)
|
||||
self.assertEqual(
|
||||
Book.objects.aggregate(Variance('price', sample=True)),
|
||||
{'price__variance': Approximate(700.53, 2)}
|
||||
)
|
||||
|
|
|
@ -2,10 +2,10 @@ import copy
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
from unittest import TestCase
|
||||
|
||||
from django.conf import Settings
|
||||
from django.db.models.loading import cache, load_app
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
__test__ = {"API_TESTS": """
|
||||
Test the globbing of INSTALLED_APPS.
|
||||
|
|
|
@ -28,7 +28,7 @@ class SchoolClass(models.Model):
|
|||
|
||||
# Unfortunately, the following model breaks MySQL hard.
|
||||
# Until #13711 is fixed, this test can't be run under MySQL.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
|
||||
if connection.features.supports_long_model_names:
|
||||
class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ(models.Model):
|
||||
class Meta:
|
||||
# We need to use a short actual table name or
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Unit and doctests for specific database backends.
|
||||
import datetime
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import management
|
||||
|
@ -9,48 +8,46 @@ from django.core.management.color import no_style
|
|||
from django.db import backend, connection, connections, DEFAULT_DB_ALIAS
|
||||
from django.db.backends.signals import connection_created
|
||||
from django.db.backends.postgresql import version as pg_version
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils import unittest
|
||||
|
||||
from regressiontests.backends import models
|
||||
|
||||
class Callproc(unittest.TestCase):
|
||||
class OracleChecks(unittest.TestCase):
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'oracle',
|
||||
"No need to check Oracle cursor semantics")
|
||||
def test_dbms_session(self):
|
||||
# If the backend is Oracle, test that we can call a standard
|
||||
# stored procedure through our cursor wrapper.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||
convert_unicode = backend.convert_unicode
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
|
||||
[convert_unicode('_django_testing!'),])
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
convert_unicode = backend.convert_unicode
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
|
||||
[convert_unicode('_django_testing!'),])
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'oracle',
|
||||
"No need to check Oracle cursor semantics")
|
||||
def test_cursor_var(self):
|
||||
# If the backend is Oracle, test that we can pass cursor variables
|
||||
# as query parameters.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||
cursor = connection.cursor()
|
||||
var = cursor.var(backend.Database.STRING)
|
||||
cursor.execute("BEGIN %s := 'X'; END; ", [var])
|
||||
self.assertEqual(var.getvalue(), 'X')
|
||||
|
||||
|
||||
class LongString(unittest.TestCase):
|
||||
cursor = connection.cursor()
|
||||
var = cursor.var(backend.Database.STRING)
|
||||
cursor.execute("BEGIN %s := 'X'; END; ", [var])
|
||||
self.assertEqual(var.getvalue(), 'X')
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'oracle',
|
||||
"No need to check Oracle cursor semantics")
|
||||
def test_long_string(self):
|
||||
# If the backend is Oracle, test that we can save a text longer
|
||||
# than 4000 chars and read it properly
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||
c = connection.cursor()
|
||||
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
|
||||
long_str = ''.join([unicode(x) for x in xrange(4000)])
|
||||
c.execute('INSERT INTO ltext VALUES (%s)',[long_str])
|
||||
c.execute('SELECT text FROM ltext')
|
||||
row = c.fetchone()
|
||||
self.assertEquals(long_str, row[0].read())
|
||||
c.execute('DROP TABLE ltext')
|
||||
c = connection.cursor()
|
||||
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
|
||||
long_str = ''.join([unicode(x) for x in xrange(4000)])
|
||||
c.execute('INSERT INTO ltext VALUES (%s)',[long_str])
|
||||
c.execute('SELECT text FROM ltext')
|
||||
row = c.fetchone()
|
||||
self.assertEqual(long_str, row[0].read())
|
||||
c.execute('DROP TABLE ltext')
|
||||
|
||||
class DateQuotingTest(TestCase):
|
||||
|
||||
|
@ -97,46 +94,48 @@ class ParameterHandlingTest(TestCase):
|
|||
# Unfortunately, the following tests would be a good test to run on all
|
||||
# backends, but it breaks MySQL hard. Until #13711 is fixed, it can't be run
|
||||
# everywhere (although it would be an effective test of #13711).
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
|
||||
class LongNameTest(TestCase):
|
||||
"""Long primary keys and model names can result in a sequence name
|
||||
that exceeds the database limits, which will result in truncation
|
||||
on certain databases (e.g., Postgres). The backend needs to use
|
||||
the correct sequence name in last_insert_id and other places, so
|
||||
check it is. Refs #8901.
|
||||
"""
|
||||
class LongNameTest(TestCase):
|
||||
"""Long primary keys and model names can result in a sequence name
|
||||
that exceeds the database limits, which will result in truncation
|
||||
on certain databases (e.g., Postgres). The backend needs to use
|
||||
the correct sequence name in last_insert_id and other places, so
|
||||
check it is. Refs #8901.
|
||||
"""
|
||||
|
||||
def test_sequence_name_length_limits_create(self):
|
||||
"""Test creation of model with long name and long pk name doesn't error. Ref #8901"""
|
||||
models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
|
||||
@skipUnlessDBFeature('supports_long_model_names')
|
||||
def test_sequence_name_length_limits_create(self):
|
||||
"""Test creation of model with long name and long pk name doesn't error. Ref #8901"""
|
||||
models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
|
||||
|
||||
def test_sequence_name_length_limits_m2m(self):
|
||||
"""Test an m2m save of a model with a long name and a long m2m field name doesn't error as on Django >=1.2 this now uses object saves. Ref #8901"""
|
||||
obj = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
|
||||
rel_obj = models.Person.objects.create(first_name='Django', last_name='Reinhardt')
|
||||
obj.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.add(rel_obj)
|
||||
@skipUnlessDBFeature('supports_long_model_names')
|
||||
def test_sequence_name_length_limits_m2m(self):
|
||||
"""Test an m2m save of a model with a long name and a long m2m field name doesn't error as on Django >=1.2 this now uses object saves. Ref #8901"""
|
||||
obj = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.objects.create()
|
||||
rel_obj = models.Person.objects.create(first_name='Django', last_name='Reinhardt')
|
||||
obj.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.add(rel_obj)
|
||||
|
||||
def test_sequence_name_length_limits_flush(self):
|
||||
"""Test that sequence resetting as part of a flush with model with long name and long pk name doesn't error. Ref #8901"""
|
||||
# A full flush is expensive to the full test, so we dig into the
|
||||
# internals to generate the likely offending SQL and run it manually
|
||||
@skipUnlessDBFeature('supports_long_model_names')
|
||||
def test_sequence_name_length_limits_flush(self):
|
||||
"""Test that sequence resetting as part of a flush with model with long name and long pk name doesn't error. Ref #8901"""
|
||||
# A full flush is expensive to the full test, so we dig into the
|
||||
# internals to generate the likely offending SQL and run it manually
|
||||
|
||||
# Some convenience aliases
|
||||
VLM = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
|
||||
VLM_m2m = VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through
|
||||
tables = [
|
||||
VLM._meta.db_table,
|
||||
VLM_m2m._meta.db_table,
|
||||
]
|
||||
sequences = [
|
||||
{
|
||||
'column': VLM._meta.pk.column,
|
||||
'table': VLM._meta.db_table
|
||||
},
|
||||
]
|
||||
cursor = connection.cursor()
|
||||
for statement in connection.ops.sql_flush(no_style(), tables, sequences):
|
||||
cursor.execute(statement)
|
||||
# Some convenience aliases
|
||||
VLM = models.VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
|
||||
VLM_m2m = VLM.m2m_also_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.through
|
||||
tables = [
|
||||
VLM._meta.db_table,
|
||||
VLM_m2m._meta.db_table,
|
||||
]
|
||||
sequences = [
|
||||
{
|
||||
'column': VLM._meta.pk.column,
|
||||
'table': VLM._meta.db_table
|
||||
},
|
||||
]
|
||||
cursor = connection.cursor()
|
||||
for statement in connection.ops.sql_flush(no_style(), tables, sequences):
|
||||
cursor.execute(statement)
|
||||
|
||||
class SequenceResetTest(TestCase):
|
||||
def test_generic_relation(self):
|
||||
|
@ -170,22 +169,22 @@ class PostgresVersionTest(TestCase):
|
|||
# Unfortunately with sqlite3 the in-memory test database cannot be
|
||||
# closed, and so it cannot be re-opened during testing, and so we
|
||||
# sadly disable this test for now.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]["ENGINE"] != "django.db.backends.sqlite3":
|
||||
class ConnectionCreatedSignalTest(TestCase):
|
||||
def test_signal(self):
|
||||
data = {}
|
||||
def receiver(sender, connection, **kwargs):
|
||||
data["connection"] = connection
|
||||
class ConnectionCreatedSignalTest(TestCase):
|
||||
@skipUnlessDBFeature('test_db_allows_multiple_connections')
|
||||
def test_signal(self):
|
||||
data = {}
|
||||
def receiver(sender, connection, **kwargs):
|
||||
data["connection"] = connection
|
||||
|
||||
connection_created.connect(receiver)
|
||||
connection.close()
|
||||
cursor = connection.cursor()
|
||||
self.assertTrue(data["connection"] is connection)
|
||||
connection_created.connect(receiver)
|
||||
connection.close()
|
||||
cursor = connection.cursor()
|
||||
self.assertTrue(data["connection"] is connection)
|
||||
|
||||
connection_created.disconnect(receiver)
|
||||
data.clear()
|
||||
cursor = connection.cursor()
|
||||
self.assertTrue(data == {})
|
||||
connection_created.disconnect(receiver)
|
||||
data.clear()
|
||||
cursor = connection.cursor()
|
||||
self.assertTrue(data == {})
|
||||
|
||||
|
||||
class BackendTestCase(TestCase):
|
||||
|
@ -225,3 +224,4 @@ class BackendTestCase(TestCase):
|
|||
self.assertEqual(cursor.fetchone(), (u'Clark', u'Kent'))
|
||||
self.assertEqual(list(cursor.fetchmany(2)), [(u'Jane', u'Doe'), (u'John', u'Doe')])
|
||||
self.assertEqual(list(cursor.fetchall()), [(u'Mary', u'Agnelline'), (u'Peter', u'Parker')])
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
A series of tests to establish that the command-line bash completion works.
|
||||
"""
|
||||
import os
|
||||
import unittest
|
||||
import sys
|
||||
import StringIO
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import ManagementUtility
|
||||
from django.utils import unittest
|
||||
|
||||
class BashCompletionTests(unittest.TestCase):
|
||||
"""
|
||||
|
|
|
@ -6,9 +6,10 @@ ModelForm's save() method causes Model.save() to be called more than once.
|
|||
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.utils import unittest
|
||||
|
||||
from regressiontests.bug639.models import Photo, PhotoForm, temp_storage_dir
|
||||
|
||||
class Bug639Test(unittest.TestCase):
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from django.contrib import admin
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
class Bug8245Test(TestCase):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from unittest import TestCase
|
||||
from StringIO import StringIO
|
||||
|
||||
from django.core.servers.basehttp import ServerHandler
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
#
|
||||
# Tests for #9659: wsgi.file_wrapper in the builtin server.
|
||||
|
|
|
@ -7,7 +7,6 @@ import os
|
|||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -17,6 +16,7 @@ from django.core.cache.backends.base import InvalidCacheBackendError, CacheKeyWa
|
|||
from django.http import HttpResponse, HttpRequest
|
||||
from django.middleware.cache import FetchFromCacheMiddleware, UpdateCacheMiddleware
|
||||
from django.utils import translation
|
||||
from django.utils import unittest
|
||||
from django.utils.cache import patch_vary_headers, get_cache_key, learn_cache_key
|
||||
from django.utils.hashcompat import md5_constructor
|
||||
from regressiontests.cache.models import Poll, expensive_calculation
|
||||
|
@ -393,6 +393,7 @@ class BaseCacheTests(object):
|
|||
# runner doesn't add any global warning filters (it currently
|
||||
# does not).
|
||||
warnings.resetwarnings()
|
||||
warnings.simplefilter("ignore", PendingDeprecationWarning)
|
||||
|
||||
class DBCacheTests(unittest.TestCase, BaseCacheTests):
|
||||
def setUp(self):
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import DEFAULT_DB_ALIAS
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipIfDBFeature
|
||||
from django.utils import tzinfo
|
||||
|
||||
from models import Donut, RumBaba
|
||||
from django.conf import settings
|
||||
|
||||
class DataTypesTestCase(TestCase):
|
||||
|
||||
|
@ -73,14 +74,14 @@ class DataTypesTestCase(TestCase):
|
|||
newd = Donut.objects.get(id=d.id)
|
||||
self.assert_(isinstance(newd.review, unicode))
|
||||
|
||||
def test_tz_awareness_mysql(self):
|
||||
@skipIfDBFeature('supports_timezones')
|
||||
def test_error_on_timezone(self):
|
||||
"""Regression test for #8354: the MySQL backend should raise an error
|
||||
if given a timezone-aware datetime object."""
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.mysql':
|
||||
dt = datetime.datetime(2008, 8, 31, 16, 20, tzinfo=tzinfo.FixedOffset(0))
|
||||
d = Donut(name='Bear claw', consumed_at=dt)
|
||||
self.assertRaises(ValueError, d.save)
|
||||
# ValueError: MySQL backend does not support timezone-aware datetimes.
|
||||
dt = datetime.datetime(2008, 8, 31, 16, 20, tzinfo=tzinfo.FixedOffset(0))
|
||||
d = Donut(name='Bear claw', consumed_at=dt)
|
||||
self.assertRaises(ValueError, d.save)
|
||||
# ValueError: MySQL backend does not support timezone-aware datetimes.
|
||||
|
||||
def test_datefield_auto_now_add(self):
|
||||
"""Regression test for #10970, auto_now_add for DateField should store
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
from unittest import TestCase
|
||||
from sys import version_info
|
||||
try:
|
||||
from functools import wraps
|
||||
except ImportError:
|
||||
from django.utils.functional import wraps # Python 2.4 fallback.
|
||||
|
||||
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.http import HttpResponse, HttpRequest
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.functional import allow_lazy, lazy, memoize
|
||||
from django.utils.unittest import TestCase
|
||||
from django.views.decorators.http import require_http_methods, require_GET, require_POST
|
||||
from django.views.decorators.vary import vary_on_headers, vary_on_cookie
|
||||
from django.views.decorators.cache import cache_page, never_cache, cache_control
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.decorators import login_required, permission_required, user_passes_test
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
|
||||
|
||||
def fully_decorated(request):
|
||||
"""Expected __doc__"""
|
||||
|
@ -70,25 +71,25 @@ class DecoratorsTest(TestCase):
|
|||
def test1(user):
|
||||
user.decorators_applied.append('test1')
|
||||
return True
|
||||
|
||||
|
||||
def test2(user):
|
||||
user.decorators_applied.append('test2')
|
||||
return True
|
||||
|
||||
|
||||
def callback(request):
|
||||
return request.user.decorators_applied
|
||||
|
||||
callback = user_passes_test(test1)(callback)
|
||||
callback = user_passes_test(test2)(callback)
|
||||
|
||||
|
||||
class DummyUser(object): pass
|
||||
class DummyRequest(object): pass
|
||||
|
||||
|
||||
request = DummyRequest()
|
||||
request.user = DummyUser()
|
||||
request.user.decorators_applied = []
|
||||
response = callback(request)
|
||||
|
||||
|
||||
self.assertEqual(response, ['test2', 'test1'])
|
||||
|
||||
def test_cache_page_new_style(self):
|
||||
|
|
|
@ -2,64 +2,65 @@ import datetime
|
|||
|
||||
from django.conf import settings
|
||||
from django.db import backend, connection, transaction, DEFAULT_DB_ALIAS
|
||||
from django.test import TestCase, TransactionTestCase
|
||||
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
|
||||
|
||||
from models import Book, Award, AwardNote, Person, Child, Toy, PlayedWith, PlayedWithNote
|
||||
|
||||
|
||||
# Can't run this test under SQLite, because you can't
|
||||
# get two connections to an in-memory database.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.sqlite3':
|
||||
class DeleteLockingTest(TransactionTestCase):
|
||||
def setUp(self):
|
||||
# Create a second connection to the default database
|
||||
conn_settings = settings.DATABASES[DEFAULT_DB_ALIAS]
|
||||
self.conn2 = backend.DatabaseWrapper({
|
||||
'HOST': conn_settings['HOST'],
|
||||
'NAME': conn_settings['NAME'],
|
||||
'OPTIONS': conn_settings['OPTIONS'],
|
||||
'PASSWORD': conn_settings['PASSWORD'],
|
||||
'PORT': conn_settings['PORT'],
|
||||
'USER': conn_settings['USER'],
|
||||
'TIME_ZONE': settings.TIME_ZONE,
|
||||
})
|
||||
class DeleteLockingTest(TransactionTestCase):
|
||||
def setUp(self):
|
||||
# Create a second connection to the default database
|
||||
conn_settings = settings.DATABASES[DEFAULT_DB_ALIAS]
|
||||
self.conn2 = backend.DatabaseWrapper({
|
||||
'HOST': conn_settings['HOST'],
|
||||
'NAME': conn_settings['NAME'],
|
||||
'OPTIONS': conn_settings['OPTIONS'],
|
||||
'PASSWORD': conn_settings['PASSWORD'],
|
||||
'PORT': conn_settings['PORT'],
|
||||
'USER': conn_settings['USER'],
|
||||
'TIME_ZONE': settings.TIME_ZONE,
|
||||
})
|
||||
|
||||
# Put both DB connections into managed transaction mode
|
||||
transaction.enter_transaction_management()
|
||||
transaction.managed(True)
|
||||
self.conn2._enter_transaction_management(True)
|
||||
# Put both DB connections into managed transaction mode
|
||||
transaction.enter_transaction_management()
|
||||
transaction.managed(True)
|
||||
self.conn2._enter_transaction_management(True)
|
||||
|
||||
def tearDown(self):
|
||||
# Close down the second connection.
|
||||
transaction.leave_transaction_management()
|
||||
self.conn2.close()
|
||||
def tearDown(self):
|
||||
# Close down the second connection.
|
||||
transaction.leave_transaction_management()
|
||||
self.conn2.close()
|
||||
|
||||
def test_concurrent_delete(self):
|
||||
"Deletes on concurrent transactions don't collide and lock the database. Regression for #9479"
|
||||
@skipUnlessDBFeature('test_db_allows_multiple_connections')
|
||||
def test_concurrent_delete(self):
|
||||
"Deletes on concurrent transactions don't collide and lock the database. Regression for #9479"
|
||||
|
||||
# Create some dummy data
|
||||
b1 = Book(id=1, pagecount=100)
|
||||
b2 = Book(id=2, pagecount=200)
|
||||
b3 = Book(id=3, pagecount=300)
|
||||
b1.save()
|
||||
b2.save()
|
||||
b3.save()
|
||||
# Create some dummy data
|
||||
b1 = Book(id=1, pagecount=100)
|
||||
b2 = Book(id=2, pagecount=200)
|
||||
b3 = Book(id=3, pagecount=300)
|
||||
b1.save()
|
||||
b2.save()
|
||||
b3.save()
|
||||
|
||||
transaction.commit()
|
||||
transaction.commit()
|
||||
|
||||
self.assertEquals(3, Book.objects.count())
|
||||
self.assertEqual(3, Book.objects.count())
|
||||
|
||||
# Delete something using connection 2.
|
||||
cursor2 = self.conn2.cursor()
|
||||
cursor2.execute('DELETE from delete_regress_book WHERE id=1')
|
||||
self.conn2._commit();
|
||||
# Delete something using connection 2.
|
||||
cursor2 = self.conn2.cursor()
|
||||
cursor2.execute('DELETE from delete_regress_book WHERE id=1')
|
||||
self.conn2._commit();
|
||||
|
||||
# Now perform a queryset delete that covers the object
|
||||
# deleted in connection 2. This causes an infinite loop
|
||||
# under MySQL InnoDB unless we keep track of already
|
||||
# deleted objects.
|
||||
Book.objects.filter(pagecount__lt=250).delete()
|
||||
transaction.commit()
|
||||
self.assertEquals(1, Book.objects.count())
|
||||
# Now perform a queryset delete that covers the object
|
||||
# deleted in connection 2. This causes an infinite loop
|
||||
# under MySQL InnoDB unless we keep track of already
|
||||
# deleted objects.
|
||||
Book.objects.filter(pagecount__lt=250).delete()
|
||||
transaction.commit()
|
||||
self.assertEqual(1, Book.objects.count())
|
||||
|
||||
class DeleteCascadeTests(TestCase):
|
||||
def test_generic_relation_cascade(self):
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from django.dispatch import Signal
|
||||
import unittest
|
||||
import sys
|
||||
import gc
|
||||
import sys
|
||||
|
||||
from django.dispatch import Signal
|
||||
from django.utils import unittest
|
||||
import django.utils.copycompat as copy
|
||||
|
||||
if sys.platform.startswith('java'):
|
||||
|
@ -20,7 +21,7 @@ def receiver_1_arg(val, **kwargs):
|
|||
class Callable(object):
|
||||
def __call__(self, val, **kwargs):
|
||||
return val
|
||||
|
||||
|
||||
def a(self, val, **kwargs):
|
||||
return val
|
||||
|
||||
|
@ -35,7 +36,7 @@ class DispatcherTests(unittest.TestCase):
|
|||
|
||||
# force cleanup just in case
|
||||
signal.receivers = []
|
||||
|
||||
|
||||
def testExact(self):
|
||||
a_signal.connect(receiver_1_arg, sender=self)
|
||||
expected = [(receiver_1_arg,"test")]
|
||||
|
@ -51,7 +52,7 @@ class DispatcherTests(unittest.TestCase):
|
|||
self.assertEqual(result, expected)
|
||||
a_signal.disconnect(receiver_1_arg)
|
||||
self._testIsClean(a_signal)
|
||||
|
||||
|
||||
def testGarbageCollected(self):
|
||||
a = Callable()
|
||||
a_signal.connect(a.a, sender=self)
|
||||
|
@ -61,7 +62,7 @@ class DispatcherTests(unittest.TestCase):
|
|||
result = a_signal.send(sender=self, val="test")
|
||||
self.assertEqual(result, expected)
|
||||
self._testIsClean(a_signal)
|
||||
|
||||
|
||||
def testMultipleRegistration(self):
|
||||
a = Callable()
|
||||
a_signal.connect(a)
|
||||
|
@ -90,7 +91,7 @@ class DispatcherTests(unittest.TestCase):
|
|||
self.assertEqual(len(a_signal.receivers), 1)
|
||||
a_signal.disconnect(dispatch_uid = "uid")
|
||||
self._testIsClean(a_signal)
|
||||
|
||||
|
||||
def testRobust(self):
|
||||
"""Test the sendRobust function"""
|
||||
def fails(val, **kwargs):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.dispatch.saferef import *
|
||||
|
||||
import unittest
|
||||
from django.utils import unittest
|
||||
|
||||
class Test1(object):
|
||||
def x(self):
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
"""
|
||||
Spanning tests for all the operations that F() expressions can perform.
|
||||
"""
|
||||
from django.test import TestCase, Approximate
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db.models import F
|
||||
from django.test import TestCase, Approximate, skipUnlessDBFeature
|
||||
|
||||
from regressiontests.expressions_regress.models import Number
|
||||
|
||||
|
||||
class ExpressionsRegressTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -130,13 +130,13 @@ class ExpressionOperatorTests(TestCase):
|
|||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 40)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.oracle':
|
||||
def test_lefthand_bitwise_or(self):
|
||||
# LH Bitwise or on integers
|
||||
Number.objects.filter(pk=self.n.pk).update(integer=F('integer') | 48)
|
||||
@skipUnlessDBFeature('supports_bitwise_or')
|
||||
def test_lefthand_bitwise_or(self):
|
||||
# LH Bitwise or on integers
|
||||
Number.objects.filter(pk=self.n.pk).update(integer=F('integer') | 48)
|
||||
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 58)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
|
||||
def test_right_hand_addition(self):
|
||||
# Right hand operators
|
||||
|
@ -185,11 +185,11 @@ class ExpressionOperatorTests(TestCase):
|
|||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 10)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.oracle':
|
||||
def test_right_hand_bitwise_or(self):
|
||||
# RH Bitwise or on integers
|
||||
Number.objects.filter(pk=self.n.pk).update(integer=15 | F('integer'))
|
||||
@skipUnlessDBFeature('supports_bitwise_or')
|
||||
def test_right_hand_bitwise_or(self):
|
||||
# RH Bitwise or on integers
|
||||
Number.objects.filter(pk=self.n.pk).update(integer=15 | F('integer'))
|
||||
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 47)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).integer, 47)
|
||||
self.assertEqual(Number.objects.get(pk=self.n.pk).float, Approximate(15.500, places=3))
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import shutil
|
|||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
from cStringIO import StringIO
|
||||
from datetime import datetime, timedelta
|
||||
from django.conf import settings
|
||||
|
@ -14,7 +13,8 @@ from django.core.files.images import get_image_dimensions
|
|||
from django.core.files.storage import FileSystemStorage, get_storage_class
|
||||
from django.core.files.uploadedfile import UploadedFile
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from unittest import TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
|
@ -294,7 +294,7 @@ class SlowFile(ContentFile):
|
|||
time.sleep(1)
|
||||
return super(ContentFile, self).chunks()
|
||||
|
||||
class FileSaveRaceConditionTest(TestCase):
|
||||
class FileSaveRaceConditionTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.storage_dir = tempfile.mkdtemp()
|
||||
self.storage = FileSystemStorage(self.storage_dir)
|
||||
|
@ -315,7 +315,7 @@ class FileSaveRaceConditionTest(TestCase):
|
|||
self.storage.delete('conflict')
|
||||
self.storage.delete('conflict_1')
|
||||
|
||||
class FileStoragePermissions(TestCase):
|
||||
class FileStoragePermissions(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.old_perms = settings.FILE_UPLOAD_PERMISSIONS
|
||||
settings.FILE_UPLOAD_PERMISSIONS = 0666
|
||||
|
@ -332,7 +332,7 @@ class FileStoragePermissions(TestCase):
|
|||
self.assertEqual(actual_mode, 0666)
|
||||
|
||||
|
||||
class FileStoragePathParsing(TestCase):
|
||||
class FileStoragePathParsing(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.storage_dir = tempfile.mkdtemp()
|
||||
self.storage = FileSystemStorage(self.storage_dir)
|
||||
|
@ -370,64 +370,67 @@ class FileStoragePathParsing(TestCase):
|
|||
else:
|
||||
self.assert_(os.path.exists(os.path.join(self.storage_dir, 'dotted.path/.test_1')))
|
||||
|
||||
if Image is not None:
|
||||
class DimensionClosingBug(TestCase):
|
||||
class DimensionClosingBug(unittest.TestCase):
|
||||
"""
|
||||
Test that get_image_dimensions() properly closes files (#8817)
|
||||
"""
|
||||
@unittest.skipUnless(Image, "PIL not installed")
|
||||
def test_not_closing_of_files(self):
|
||||
"""
|
||||
Test that get_image_dimensions() properly closes files (#8817)
|
||||
Open files passed into get_image_dimensions() should stay opened.
|
||||
"""
|
||||
def test_not_closing_of_files(self):
|
||||
"""
|
||||
Open files passed into get_image_dimensions() should stay opened.
|
||||
"""
|
||||
empty_io = StringIO()
|
||||
try:
|
||||
get_image_dimensions(empty_io)
|
||||
finally:
|
||||
self.assert_(not empty_io.closed)
|
||||
empty_io = StringIO()
|
||||
try:
|
||||
get_image_dimensions(empty_io)
|
||||
finally:
|
||||
self.assert_(not empty_io.closed)
|
||||
|
||||
def test_closing_of_filenames(self):
|
||||
"""
|
||||
get_image_dimensions() called with a filename should closed the file.
|
||||
"""
|
||||
# We need to inject a modified open() builtin into the images module
|
||||
# that checks if the file was closed properly if the function is
|
||||
# called with a filename instead of an file object.
|
||||
# get_image_dimensions will call our catching_open instead of the
|
||||
# regular builtin one.
|
||||
|
||||
class FileWrapper(object):
|
||||
_closed = []
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.f, name)
|
||||
def close(self):
|
||||
self._closed.append(True)
|
||||
self.f.close()
|
||||
|
||||
def catching_open(*args):
|
||||
return FileWrapper(open(*args))
|
||||
|
||||
from django.core.files import images
|
||||
images.open = catching_open
|
||||
try:
|
||||
get_image_dimensions(os.path.join(os.path.dirname(__file__), "test1.png"))
|
||||
finally:
|
||||
del images.open
|
||||
self.assert_(FileWrapper._closed)
|
||||
|
||||
class InconsistentGetImageDimensionsBug(TestCase):
|
||||
@unittest.skipUnless(Image, "PIL not installed")
|
||||
def test_closing_of_filenames(self):
|
||||
"""
|
||||
Test that get_image_dimensions() works properly after various calls using a file handler (#11158)
|
||||
get_image_dimensions() called with a filename should closed the file.
|
||||
"""
|
||||
def test_multiple_calls(self):
|
||||
"""
|
||||
Multiple calls of get_image_dimensions() should return the same size.
|
||||
"""
|
||||
from django.core.files.images import ImageFile
|
||||
img_path = os.path.join(os.path.dirname(__file__), "test.png")
|
||||
image = ImageFile(open(img_path, 'rb'))
|
||||
image_pil = Image.open(img_path)
|
||||
size_1, size_2 = get_image_dimensions(image), get_image_dimensions(image)
|
||||
self.assertEqual(image_pil.size, size_1)
|
||||
self.assertEqual(size_1, size_2)
|
||||
# We need to inject a modified open() builtin into the images module
|
||||
# that checks if the file was closed properly if the function is
|
||||
# called with a filename instead of an file object.
|
||||
# get_image_dimensions will call our catching_open instead of the
|
||||
# regular builtin one.
|
||||
|
||||
class FileWrapper(object):
|
||||
_closed = []
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.f, name)
|
||||
def close(self):
|
||||
self._closed.append(True)
|
||||
self.f.close()
|
||||
|
||||
def catching_open(*args):
|
||||
return FileWrapper(open(*args))
|
||||
|
||||
from django.core.files import images
|
||||
images.open = catching_open
|
||||
try:
|
||||
get_image_dimensions(os.path.join(os.path.dirname(__file__), "test1.png"))
|
||||
finally:
|
||||
del images.open
|
||||
self.assert_(FileWrapper._closed)
|
||||
|
||||
class InconsistentGetImageDimensionsBug(unittest.TestCase):
|
||||
"""
|
||||
Test that get_image_dimensions() works properly after various calls
|
||||
using a file handler (#11158)
|
||||
"""
|
||||
@unittest.skipUnless(Image, "PIL not installed")
|
||||
def test_multiple_calls(self):
|
||||
"""
|
||||
Multiple calls of get_image_dimensions() should return the same size.
|
||||
"""
|
||||
from django.core.files.images import ImageFile
|
||||
img_path = os.path.join(os.path.dirname(__file__), "test.png")
|
||||
image = ImageFile(open(img_path, 'rb'))
|
||||
image_pil = Image.open(img_path)
|
||||
size_1, size_2 = get_image_dimensions(image), get_image_dimensions(image)
|
||||
self.assertEqual(image_pil.size, size_1)
|
||||
self.assertEqual(size_1, size_2)
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
import os
|
||||
import errno
|
||||
import shutil
|
||||
import unittest
|
||||
from StringIO import StringIO
|
||||
|
||||
from django.core.files import temp as tempfile
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.http.multipartparser import MultiPartParser
|
||||
from django.test import TestCase, client
|
||||
from django.utils import simplejson
|
||||
from django.utils import unittest
|
||||
from django.utils.hashcompat import sha_constructor
|
||||
from django.http.multipartparser import MultiPartParser
|
||||
|
||||
from models import FileModel, temp_storage, UPLOAD_TO
|
||||
import uploadhandler
|
||||
|
@ -223,7 +223,7 @@ class FileUploadTests(TestCase):
|
|||
ret = super(POSTAccessingHandler, self).handle_uncaught_exception(request, resolver, exc_info)
|
||||
p = request.POST
|
||||
return ret
|
||||
|
||||
|
||||
post_data = {
|
||||
'name': 'Ringo',
|
||||
'file_field': open(__file__),
|
||||
|
@ -244,7 +244,7 @@ class FileUploadTests(TestCase):
|
|||
response = self.client.post('/file_uploads/upload_errors/', post_data)
|
||||
except reference_error.__class__, err:
|
||||
self.failIf(
|
||||
str(err) == str(reference_error),
|
||||
str(err) == str(reference_error),
|
||||
"Caught a repeated exception that'll cause an infinite loop in file uploads."
|
||||
)
|
||||
except Exception, err:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db import models, DEFAULT_DB_ALIAS, connection
|
||||
from django.contrib.auth.models import User
|
||||
from django.conf import settings
|
||||
|
||||
|
@ -31,7 +31,7 @@ class Stuff(models.Model):
|
|||
# Oracle doesn't distinguish between None and the empty string.
|
||||
# This hack makes the test case pass using Oracle.
|
||||
name = self.name
|
||||
if (settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle'
|
||||
if (connection.features.interprets_empty_strings_as_nulls
|
||||
and name == u''):
|
||||
name = None
|
||||
return unicode(name) + u' is owned by ' + unicode(self.owner)
|
||||
|
|
|
@ -30,11 +30,10 @@ import re
|
|||
import os
|
||||
from decimal import Decimal
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.forms import *
|
||||
from django.forms.widgets import RadioFieldRenderer
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
def fix_os_paths(x):
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from datetime import time, date, datetime
|
||||
from unittest import TestCase
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.utils.translation import activate, deactivate
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
class LocalizedTimeTests(TestCase):
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
class TestFieldWithValidators(TestCase):
|
||||
|
|
|
@ -1265,10 +1265,9 @@ u'<input type="hidden" name="date_0" value="17.09.2007" /><input type="hidden" n
|
|||
|
||||
"""
|
||||
|
||||
|
||||
from django.utils import copycompat as copy
|
||||
from unittest import TestCase
|
||||
from django import forms
|
||||
from django.utils import copycompat as copy
|
||||
from django.utils.unittest import TestCase
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import copy
|
||||
import pickle
|
||||
import unittest
|
||||
|
||||
from django.http import QueryDict, HttpResponse, CompatCookie, BadHeaderError
|
||||
from django.utils import unittest
|
||||
|
||||
class QueryDictTests(unittest.TestCase):
|
||||
def test_missing_key(self):
|
||||
|
@ -17,7 +18,7 @@ class QueryDictTests(unittest.TestCase):
|
|||
self.assertRaises(AttributeError, q.pop, 'foo')
|
||||
self.assertRaises(AttributeError, q.popitem)
|
||||
self.assertRaises(AttributeError, q.clear)
|
||||
|
||||
|
||||
def test_immutable_get_with_default(self):
|
||||
q = QueryDict('')
|
||||
self.assertEqual(q.get('foo', 'default'), 'default')
|
||||
|
@ -34,7 +35,7 @@ class QueryDictTests(unittest.TestCase):
|
|||
self.assertEqual(q.values(), [])
|
||||
self.assertEqual(len(q), 0)
|
||||
self.assertEqual(q.urlencode(), '')
|
||||
|
||||
|
||||
def test_single_key_value(self):
|
||||
"""Test QueryDict with one key/value pair"""
|
||||
|
||||
|
@ -47,7 +48,7 @@ class QueryDictTests(unittest.TestCase):
|
|||
self.assertEqual(q.get('bar', 'default'), 'default')
|
||||
self.assertEqual(q.getlist('foo'), ['bar'])
|
||||
self.assertEqual(q.getlist('bar'), [])
|
||||
|
||||
|
||||
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar'])
|
||||
self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
|
||||
|
||||
|
@ -67,16 +68,16 @@ class QueryDictTests(unittest.TestCase):
|
|||
self.assertRaises(AttributeError, q.popitem)
|
||||
self.assertRaises(AttributeError, q.clear)
|
||||
self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar')
|
||||
|
||||
|
||||
self.assertEqual(q.urlencode(), 'foo=bar')
|
||||
|
||||
|
||||
def test_mutable_copy(self):
|
||||
"""A copy of a QueryDict is mutable."""
|
||||
q = QueryDict('').copy()
|
||||
self.assertRaises(KeyError, q.__getitem__, "foo")
|
||||
q['name'] = 'john'
|
||||
self.assertEqual(q['name'], 'john')
|
||||
|
||||
|
||||
def test_mutable_delete(self):
|
||||
q = QueryDict('').copy()
|
||||
q['name'] = 'john'
|
||||
|
@ -126,20 +127,20 @@ class QueryDictTests(unittest.TestCase):
|
|||
"""Test QueryDict with two key/value pairs with same keys."""
|
||||
|
||||
q = QueryDict('vote=yes&vote=no')
|
||||
|
||||
|
||||
self.assertEqual(q['vote'], u'no')
|
||||
self.assertRaises(AttributeError, q.__setitem__, 'something', 'bar')
|
||||
|
||||
|
||||
self.assertEqual(q.get('vote', 'default'), u'no')
|
||||
self.assertEqual(q.get('foo', 'default'), 'default')
|
||||
self.assertEqual(q.getlist('vote'), [u'yes', u'no'])
|
||||
self.assertEqual(q.getlist('foo'), [])
|
||||
|
||||
|
||||
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz'])
|
||||
self.assertRaises(AttributeError, q.setlist, 'foo', ['bar', 'baz'])
|
||||
self.assertRaises(AttributeError, q.appendlist, 'foo', ['bar'])
|
||||
|
||||
self.assertEqual(q.has_key('vote'), True)
|
||||
self.assertEqual(q.has_key('vote'), True)
|
||||
self.assertEqual('vote' in q, True)
|
||||
self.assertEqual(q.has_key('foo'), False)
|
||||
self.assertEqual('foo' in q, False)
|
||||
|
@ -148,23 +149,23 @@ class QueryDictTests(unittest.TestCase):
|
|||
self.assertEqual(q.keys(), [u'vote'])
|
||||
self.assertEqual(q.values(), [u'no'])
|
||||
self.assertEqual(len(q), 1)
|
||||
|
||||
|
||||
self.assertRaises(AttributeError, q.update, {'foo': 'bar'})
|
||||
self.assertRaises(AttributeError, q.pop, 'foo')
|
||||
self.assertRaises(AttributeError, q.popitem)
|
||||
self.assertRaises(AttributeError, q.clear)
|
||||
self.assertRaises(AttributeError, q.setdefault, 'foo', 'bar')
|
||||
self.assertRaises(AttributeError, q.__delitem__, 'vote')
|
||||
|
||||
|
||||
def test_invalid_input_encoding(self):
|
||||
"""
|
||||
QueryDicts must be able to handle invalid input encoding (in this
|
||||
case, bad UTF-8 encoding).
|
||||
"""
|
||||
q = QueryDict('foo=bar&foo=\xff')
|
||||
self.assertEqual(q['foo'], u'\ufffd')
|
||||
self.assertEqual(q['foo'], u'\ufffd')
|
||||
self.assertEqual(q.getlist('foo'), [u'bar', u'\ufffd'])
|
||||
|
||||
|
||||
def test_pickle(self):
|
||||
q = QueryDict('')
|
||||
q1 = pickle.loads(pickle.dumps(q, 2))
|
||||
|
@ -172,7 +173,7 @@ class QueryDictTests(unittest.TestCase):
|
|||
q = QueryDict('a=b&c=d')
|
||||
q1 = pickle.loads(pickle.dumps(q, 2))
|
||||
self.assertEqual(q == q1, True)
|
||||
q = QueryDict('a=b&c=d&a=1')
|
||||
q = QueryDict('a=b&c=d&a=1')
|
||||
q1 = pickle.loads(pickle.dumps(q, 2))
|
||||
self.assertEqual(q == q1 , True)
|
||||
|
||||
|
@ -181,21 +182,21 @@ class QueryDictTests(unittest.TestCase):
|
|||
x = QueryDict("a=1&a=2", mutable=True)
|
||||
y = QueryDict("a=3&a=4")
|
||||
x.update(y)
|
||||
self.assertEqual(x.getlist('a'), [u'1', u'2', u'3', u'4'])
|
||||
self.assertEqual(x.getlist('a'), [u'1', u'2', u'3', u'4'])
|
||||
|
||||
def test_non_default_encoding(self):
|
||||
"""#13572 - QueryDict with a non-default encoding"""
|
||||
q = QueryDict('sbb=one', encoding='rot_13')
|
||||
q = QueryDict('sbb=one', encoding='rot_13')
|
||||
self.assertEqual(q.encoding , 'rot_13' )
|
||||
self.assertEqual(q.items() , [(u'foo', u'bar')] )
|
||||
self.assertEqual(q.urlencode() , 'sbb=one' )
|
||||
q = q.copy()
|
||||
q = q.copy()
|
||||
self.assertEqual(q.encoding , 'rot_13' )
|
||||
self.assertEqual(q.items() , [(u'foo', u'bar')] )
|
||||
self.assertEqual(q.urlencode() , 'sbb=one' )
|
||||
self.assertEqual(copy.copy(q).encoding , 'rot_13' )
|
||||
self.assertEqual(copy.deepcopy(q).encoding , 'rot_13')
|
||||
|
||||
|
||||
class HttpResponseTests(unittest.TestCase):
|
||||
def test_unicode_headers(self):
|
||||
r = HttpResponse()
|
||||
|
@ -203,10 +204,10 @@ class HttpResponseTests(unittest.TestCase):
|
|||
# If we insert a unicode value it will be converted to an ascii
|
||||
r['value'] = u'test value'
|
||||
self.failUnless(isinstance(r['value'], str))
|
||||
|
||||
|
||||
# An error is raised ~hen a unicode object with non-ascii is assigned.
|
||||
self.assertRaises(UnicodeEncodeError, r.__setitem__, 'value', u't\xebst value')
|
||||
|
||||
|
||||
# An error is raised when a unicode object with non-ASCII format is
|
||||
# passed as initial mimetype or content_type.
|
||||
self.assertRaises(UnicodeEncodeError, HttpResponse,
|
||||
|
@ -216,12 +217,12 @@ class HttpResponseTests(unittest.TestCase):
|
|||
self.assertRaises(UnicodeEncodeError, HttpResponse,
|
||||
content_type=u't\xebst value')
|
||||
|
||||
# The response also converts unicode keys to strings.)
|
||||
# The response also converts unicode keys to strings.)
|
||||
r[u'test'] = 'testing key'
|
||||
l = list(r.items())
|
||||
l.sort()
|
||||
self.assertEqual(l[1], ('test', 'testing key'))
|
||||
|
||||
|
||||
# It will also raise errors for keys with non-ascii data.
|
||||
self.assertRaises(UnicodeEncodeError, r.__setitem__, u't\xebst key', 'value')
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import unittest
|
||||
from datetime import timedelta, date
|
||||
|
||||
from django.template import Template, Context, add_to_builtins
|
||||
from django.utils import unittest
|
||||
from django.utils.dateformat import DateFormat
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.html import escape
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from django.conf import settings
|
||||
from django.db import connection, DEFAULT_DB_ALIAS
|
||||
from django.test import TestCase
|
||||
from django.test import TestCase, skipUnlessDBFeature
|
||||
from django.utils import functional
|
||||
|
||||
from models import Reporter, Article
|
||||
|
@ -77,13 +77,13 @@ class IntrospectionTests(TestCase):
|
|||
)
|
||||
|
||||
# Regression test for #9991 - 'real' types in postgres
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'].startswith('django.db.backends.postgresql'):
|
||||
def test_postgresql_real_type(self):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("CREATE TABLE django_ixn_real_test_table (number REAL);")
|
||||
desc = connection.introspection.get_table_description(cursor, 'django_ixn_real_test_table')
|
||||
cursor.execute('DROP TABLE django_ixn_real_test_table;')
|
||||
self.assertEqual(datatype(desc[0][1], desc[0]), 'FloatField')
|
||||
@skipUnlessDBFeature('has_real_datatype')
|
||||
def test_postgresql_real_type(self):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("CREATE TABLE django_ixn_real_test_table (number REAL);")
|
||||
desc = connection.introspection.get_table_description(cursor, 'django_ixn_real_test_table')
|
||||
cursor.execute('DROP TABLE django_ixn_real_test_table;')
|
||||
self.assertEqual(datatype(desc[0][1], desc[0]), 'FloatField')
|
||||
|
||||
def test_get_relations(self):
|
||||
cursor = connection.cursor()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import unittest
|
||||
from django.test import TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
# just import your tests here
|
||||
from us.tests import *
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from unittest import TestCase
|
||||
from django.db import DatabaseError
|
||||
from django.utils import unittest
|
||||
from regressiontests.max_lengths.models import PersonWithDefaultMaxLengths, PersonWithCustomMaxLengths
|
||||
|
||||
class MaxLengthArgumentsTests(TestCase):
|
||||
|
||||
class MaxLengthArgumentsTests(unittest.TestCase):
|
||||
|
||||
def verify_max_length(self, model,field,length):
|
||||
self.assertEquals(model._meta.get_field(field).max_length,length)
|
||||
|
||||
|
||||
def test_default_max_lengths(self):
|
||||
self.verify_max_length(PersonWithDefaultMaxLengths, 'email', 75)
|
||||
self.verify_max_length(PersonWithDefaultMaxLengths, 'vcard', 100)
|
||||
|
@ -19,7 +19,7 @@ class MaxLengthArgumentsTests(TestCase):
|
|||
self.verify_max_length(PersonWithCustomMaxLengths, 'homepage', 250)
|
||||
self.verify_max_length(PersonWithCustomMaxLengths, 'avatar', 250)
|
||||
|
||||
class MaxLengthORMTests(TestCase):
|
||||
class MaxLengthORMTests(unittest.TestCase):
|
||||
|
||||
def test_custom_max_lengths(self):
|
||||
args = {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import datetime
|
||||
import unittest
|
||||
from decimal import Decimal
|
||||
|
||||
import django.test
|
||||
from django import test
|
||||
from django import forms
|
||||
from django.db import models
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models.fields.files import FieldFile
|
||||
from django.utils import unittest
|
||||
|
||||
from models import Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post, NullBooleanModel, BooleanModel, Document
|
||||
|
||||
|
@ -22,7 +22,7 @@ if Image:
|
|||
TwoImageFieldTests
|
||||
|
||||
|
||||
class BasicFieldTests(django.test.TestCase):
|
||||
class BasicFieldTests(test.TestCase):
|
||||
def test_show_hidden_initial(self):
|
||||
"""
|
||||
Regression test for #12913. Make sure fields with choices respect
|
||||
|
@ -48,7 +48,7 @@ class BasicFieldTests(django.test.TestCase):
|
|||
except ValidationError, e:
|
||||
self.fail("NullBooleanField failed validation with value of None: %s" % e.messages)
|
||||
|
||||
class DecimalFieldTests(django.test.TestCase):
|
||||
class DecimalFieldTests(test.TestCase):
|
||||
def test_to_python(self):
|
||||
f = models.DecimalField(max_digits=4, decimal_places=2)
|
||||
self.assertEqual(f.to_python(3), Decimal("3"))
|
||||
|
@ -95,7 +95,7 @@ class DecimalFieldTests(django.test.TestCase):
|
|||
# This should not crash. That counts as a win for our purposes.
|
||||
Foo.objects.filter(d__gte=100000000000)
|
||||
|
||||
class ForeignKeyTests(django.test.TestCase):
|
||||
class ForeignKeyTests(test.TestCase):
|
||||
def test_callable_default(self):
|
||||
"""Test the use of a lazy callable for ForeignKey.default"""
|
||||
a = Foo.objects.create(id=1, a='abc', d=Decimal("12.34"))
|
||||
|
@ -194,7 +194,7 @@ class BooleanFieldTests(unittest.TestCase):
|
|||
select={'string_length': 'LENGTH(string)'})[0]
|
||||
self.assertFalse(isinstance(b5.pk, bool))
|
||||
|
||||
class ChoicesTests(django.test.TestCase):
|
||||
class ChoicesTests(test.TestCase):
|
||||
def test_choices_and_field_display(self):
|
||||
"""
|
||||
Check that get_choices and get_flatchoices interact with
|
||||
|
@ -206,7 +206,7 @@ class ChoicesTests(django.test.TestCase):
|
|||
self.assertEqual(Whiz(c=None).get_c_display(), None) # Blank value
|
||||
self.assertEqual(Whiz(c='').get_c_display(), '') # Empty value
|
||||
|
||||
class SlugFieldTests(django.test.TestCase):
|
||||
class SlugFieldTests(test.TestCase):
|
||||
def test_slugfield_max_length(self):
|
||||
"""
|
||||
Make sure SlugField honors max_length (#9706)
|
||||
|
@ -216,7 +216,7 @@ class SlugFieldTests(django.test.TestCase):
|
|||
self.assertEqual(bs.s, 'slug'*50)
|
||||
|
||||
|
||||
class ValidationTest(django.test.TestCase):
|
||||
class ValidationTest(test.TestCase):
|
||||
def test_charfield_raises_error_on_empty_string(self):
|
||||
f = models.CharField()
|
||||
self.assertRaises(ValidationError, f.clean, "", None)
|
||||
|
@ -271,7 +271,7 @@ class ValidationTest(django.test.TestCase):
|
|||
self.assertRaises(ValidationError, f.clean, None, None)
|
||||
|
||||
|
||||
class BigIntegerFieldTests(django.test.TestCase):
|
||||
class BigIntegerFieldTests(test.TestCase):
|
||||
def test_limits(self):
|
||||
# Ensure that values that are right at the limits can be saved
|
||||
# and then retrieved without corruption.
|
||||
|
@ -299,7 +299,7 @@ class BigIntegerFieldTests(django.test.TestCase):
|
|||
b = BigInt.objects.get(value = '10')
|
||||
self.assertEqual(b.value, 10)
|
||||
|
||||
class TypeCoercionTests(django.test.TestCase):
|
||||
class TypeCoercionTests(test.TestCase):
|
||||
"""
|
||||
Test that database lookups can accept the wrong types and convert
|
||||
them with no error: especially on Postgres 8.3+ which does not do
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db import models, DEFAULT_DB_ALIAS, connection
|
||||
from django.utils import tzinfo
|
||||
|
||||
CHOICES = (
|
||||
|
@ -149,9 +149,7 @@ datetime.datetime(2000, 1, 1, 6, 1, 1)
|
|||
|
||||
"""}
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] not in (
|
||||
"django.db.backends.mysql",
|
||||
"django.db.backends.oracle"):
|
||||
if connection.features.supports_timezones:
|
||||
__test__["timezone-tests"] = """
|
||||
# Saving an updating with timezone-aware datetime Python objects. Regression
|
||||
# test for #10443.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from django.core.paginator import Paginator, EmptyPage
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
class PaginatorTests(TestCase):
|
||||
"""
|
||||
|
|
|
@ -8,7 +8,7 @@ import sys
|
|||
import threading
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models, DEFAULT_DB_ALIAS
|
||||
from django.db import models, DEFAULT_DB_ALIAS, connection
|
||||
from django.db.models import Count
|
||||
from django.db.models.query import Q, ITER_CHUNK_SIZE, EmptyQuerySet
|
||||
|
||||
|
@ -1307,13 +1307,13 @@ FieldError: Infinite loop caused by ordering.
|
|||
|
||||
|
||||
# In Oracle, we expect a null CharField to return u'' instead of None.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == "django.db.backends.oracle":
|
||||
if connection.features.interprets_empty_strings_as_nulls:
|
||||
__test__["API_TESTS"] = __test__["API_TESTS"].replace("<NONE_OR_EMPTY_UNICODE>", "u''")
|
||||
else:
|
||||
__test__["API_TESTS"] = __test__["API_TESTS"].replace("<NONE_OR_EMPTY_UNICODE>", "None")
|
||||
|
||||
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == "django.db.backends.mysql":
|
||||
if connection.features.requires_explicit_null_ordering_when_grouping:
|
||||
__test__["API_TESTS"] += """
|
||||
When grouping without specifying ordering, we add an explicit "ORDER BY NULL"
|
||||
portion in MySQL to prevent unnecessary sorting.
|
||||
|
@ -1342,7 +1342,7 @@ Using an empty generator expression as the rvalue for an "__in" lookup is legal
|
|||
|
||||
# Sqlite 3 does not support passing in more than 1000 parameters except by
|
||||
# changing a parameter at compilation time.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != "django.db.backends.sqlite3":
|
||||
if connection.features.supports_1000_query_paramters:
|
||||
__test__["API_TESTS"] += """
|
||||
Bug #14244: Test that the "in" lookup works with lists of 1000 items or more.
|
||||
>>> Number.objects.all().delete()
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import unittest
|
||||
|
||||
from django.db import DatabaseError, connections, DEFAULT_DB_ALIAS
|
||||
from django.db.models import Count
|
||||
from django.test import TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
from models import Tag, Annotation, DumbCategory, Note, ExtraInfo, Number
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ except ImportError:
|
|||
|
||||
from django.conf import settings
|
||||
from django.core import serializers, management
|
||||
from django.db import transaction, DEFAULT_DB_ALIAS
|
||||
from django.db import transaction, DEFAULT_DB_ALIAS, connection
|
||||
from django.test import TestCase
|
||||
from django.utils.functional import curry
|
||||
|
||||
|
@ -335,7 +335,7 @@ The end."""),
|
|||
# Because Oracle treats the empty string as NULL, Oracle is expected to fail
|
||||
# when field.empty_strings_allowed is True and the value is None; skip these
|
||||
# tests.
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||
if connection.features.interprets_empty_strings_as_nulls:
|
||||
test_data = [data for data in test_data
|
||||
if not (data[0] == data_obj and
|
||||
data[2]._meta.get_field('data').empty_strings_allowed and
|
||||
|
@ -344,7 +344,7 @@ if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle'
|
|||
# Regression test for #8651 -- a FK to an object iwth PK of 0
|
||||
# This won't work on MySQL since it won't let you create an object
|
||||
# with a primary key of 0,
|
||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] != 'django.db.backends.mysql':
|
||||
if connection.features.allows_primary_key_0:
|
||||
test_data.extend([
|
||||
(data_obj, 0, Anchor, "Anchor 0"),
|
||||
(fk_obj, 465, FKData, 0),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import unittest
|
||||
from django.conf import settings
|
||||
from django.utils import unittest
|
||||
|
||||
class SettingsTests(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ from django.conf import settings
|
|||
if __name__ == '__main__':
|
||||
settings.configure()
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import pkg_resources
|
||||
import imp
|
||||
|
@ -21,6 +20,8 @@ from django.template import TemplateDoesNotExist, Context
|
|||
from django.template.loaders.eggs import load_template_source as lts_egg
|
||||
from django.template.loaders.eggs import Loader as EggLoader
|
||||
from django.template import loader
|
||||
from django.utils import unittest
|
||||
|
||||
|
||||
# Mock classes and objects for pkg_resources functions.
|
||||
class MockProvider(pkg_resources.NullProvider):
|
||||
|
@ -73,6 +74,7 @@ class DeprecatedEggLoaderTest(unittest.TestCase):
|
|||
def tearDown(self):
|
||||
settings.INSTALLED_APPS = self._old_installed_apps
|
||||
warnings.resetwarnings()
|
||||
warnings.simplefilter("ignore", PendingDeprecationWarning)
|
||||
|
||||
def test_existing(self):
|
||||
"A template can be loaded from an egg"
|
||||
|
@ -80,8 +82,6 @@ class DeprecatedEggLoaderTest(unittest.TestCase):
|
|||
contents, template_name = lts_egg("y.html")
|
||||
self.assertEqual(contents, "y")
|
||||
self.assertEqual(template_name, "egg:egg_1:templates/y.html")
|
||||
warnings.resetwarnings()
|
||||
warnings.simplefilter("ignore", PendingDeprecationWarning)
|
||||
|
||||
|
||||
class EggLoaderTest(unittest.TestCase):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from unittest import TestCase
|
||||
from django.template.loader import get_template_from_string
|
||||
from django.template import VariableNode
|
||||
from django.utils.unittest import TestCase
|
||||
|
||||
|
||||
class NodelistTest(TestCase):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import unittest
|
||||
from django.template.smartif import IfParser, Literal
|
||||
from django.utils import unittest
|
||||
|
||||
class SmartIfTests(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ import time
|
|||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import unittest
|
||||
|
||||
from django import template
|
||||
from django.core import urlresolvers
|
||||
from django.template import loader
|
||||
from django.template.loaders import app_directories, filesystem, cached
|
||||
from django.utils import unittest
|
||||
from django.utils.translation import activate, deactivate, ugettext as _
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.tzinfo import LocalTimezone
|
||||
|
@ -506,16 +506,16 @@ class Templates(unittest.TestCase):
|
|||
'basic-syntax28': ("{{ a.b }}", {'a': SilentGetItemClass()}, ('', 'INVALID')),
|
||||
'basic-syntax29': ("{{ a.b }}", {'a': SilentAttrClass()}, ('', 'INVALID')),
|
||||
|
||||
# Something that starts like a number but has an extra lookup works as a lookup.
|
||||
'basic-syntax30': ("{{ 1.2.3 }}", {"1": {"2": {"3": "d"}}}, "d"),
|
||||
'basic-syntax31': ("{{ 1.2.3 }}", {"1": {"2": ("a", "b", "c", "d")}}, "d"),
|
||||
'basic-syntax32': ("{{ 1.2.3 }}", {"1": (("x", "x", "x", "x"), ("y", "y", "y", "y"), ("a", "b", "c", "d"))}, "d"),
|
||||
'basic-syntax33': ("{{ 1.2.3 }}", {"1": ("xxxx", "yyyy", "abcd")}, "d"),
|
||||
'basic-syntax34': ("{{ 1.2.3 }}", {"1": ({"x": "x"}, {"y": "y"}, {"z": "z", "3": "d"})}, "d"),
|
||||
|
||||
# Numbers are numbers even if their digits are in the context.
|
||||
'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),
|
||||
'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),
|
||||
# Something that starts like a number but has an extra lookup works as a lookup.
|
||||
'basic-syntax30': ("{{ 1.2.3 }}", {"1": {"2": {"3": "d"}}}, "d"),
|
||||
'basic-syntax31': ("{{ 1.2.3 }}", {"1": {"2": ("a", "b", "c", "d")}}, "d"),
|
||||
'basic-syntax32': ("{{ 1.2.3 }}", {"1": (("x", "x", "x", "x"), ("y", "y", "y", "y"), ("a", "b", "c", "d"))}, "d"),
|
||||
'basic-syntax33': ("{{ 1.2.3 }}", {"1": ("xxxx", "yyyy", "abcd")}, "d"),
|
||||
'basic-syntax34': ("{{ 1.2.3 }}", {"1": ({"x": "x"}, {"y": "y"}, {"z": "z", "3": "d"})}, "d"),
|
||||
|
||||
# Numbers are numbers even if their digits are in the context.
|
||||
'basic-syntax35': ("{{ 1 }}", {"1": "abc"}, "1"),
|
||||
'basic-syntax36': ("{{ 1.2 }}", {"1": "abc"}, "1.2"),
|
||||
|
||||
# List-index syntax allows a template to access a certain item of a subscriptable object.
|
||||
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),
|
||||
|
@ -603,7 +603,7 @@ class Templates(unittest.TestCase):
|
|||
|
||||
#filters should accept empty string constants
|
||||
'filter-syntax20': ('{{ ""|default_if_none:"was none" }}', {}, ""),
|
||||
|
||||
|
||||
### COMMENT SYNTAX ########################################################
|
||||
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
|
||||
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
|
||||
|
@ -1300,8 +1300,8 @@ class Templates(unittest.TestCase):
|
|||
|
||||
# Regression test for #11270.
|
||||
'cache17': ('{% load cache %}{% cache 10 long_cache_key poem %}Some Content{% endcache %}', {'poem': 'Oh freddled gruntbuggly/Thy micturations are to me/As plurdled gabbleblotchits/On a lurgid bee/That mordiously hath bitled out/Its earted jurtles/Into a rancid festering/Or else I shall rend thee in the gobberwarts with my blurglecruncheon/See if I dont.'}, 'Some Content'),
|
||||
|
||||
|
||||
|
||||
|
||||
### AUTOESCAPE TAG ##############################################
|
||||
'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),
|
||||
'autoescape-tag02': ("{% autoescape off %}{{ first }}{% endautoescape %}", {"first": "<b>hello</b>"}, "<b>hello</b>"),
|
||||
|
@ -1330,23 +1330,23 @@ class Templates(unittest.TestCase):
|
|||
# implementation details (fortunately, the (no)autoescape block
|
||||
# tags can be used in those cases)
|
||||
'autoescape-filtertag01': ("{{ first }}{% filter safe %}{{ first }} x<y{% endfilter %}", {"first": "<a>"}, template.TemplateSyntaxError),
|
||||
|
||||
|
||||
# ifqeual compares unescaped vales.
|
||||
'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes" ),
|
||||
|
||||
# Arguments to filters are 'safe' and manipulate their input unescaped.
|
||||
'autoescape-filters01': ('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ),
|
||||
'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry" ),
|
||||
|
||||
# Literal strings are safe.
|
||||
'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that" ),
|
||||
|
||||
# Iterating over strings outputs safe characters.
|
||||
'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&,R," ),
|
||||
|
||||
# Escape requirement survives lookup.
|
||||
'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this & that" ),
|
||||
|
||||
'autoescape-ifequal01': ('{% ifequal var "this & that" %}yes{% endifequal %}', { "var": "this & that" }, "yes" ),
|
||||
|
||||
# Arguments to filters are 'safe' and manipulate their input unescaped.
|
||||
'autoescape-filters01': ('{{ var|cut:"&" }}', { "var": "this & that" }, "this that" ),
|
||||
'autoescape-filters02': ('{{ var|join:" & \" }}', { "var": ("Tom", "Dick", "Harry") }, "Tom & Dick & Harry" ),
|
||||
|
||||
# Literal strings are safe.
|
||||
'autoescape-literals01': ('{{ "this & that" }}',{}, "this & that" ),
|
||||
|
||||
# Iterating over strings outputs safe characters.
|
||||
'autoescape-stringiterations01': ('{% for l in var %}{{ l }},{% endfor %}', {'var': 'K&R'}, "K,&,R," ),
|
||||
|
||||
# Escape requirement survives lookup.
|
||||
'autoescape-lookup01': ('{{ var.key }}', { "var": {"key": "this & that" }}, "this & that" ),
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,83 +35,83 @@ class AssertContainsTests(TestCase):
|
|||
try:
|
||||
self.assertContains(response, 'text', status_code=999)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Couldn't retrieve content: Response code was 200 (expected 999)")
|
||||
self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'text', status_code=999, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Couldn't retrieve content: Response code was 200 (expected 999)")
|
||||
self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
|
||||
|
||||
try:
|
||||
self.assertNotContains(response, 'text', status_code=999)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Couldn't retrieve content: Response code was 200 (expected 999)")
|
||||
self.assertIn("Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
|
||||
try:
|
||||
self.assertNotContains(response, 'text', status_code=999, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Couldn't retrieve content: Response code was 200 (expected 999)")
|
||||
self.assertIn("abc: Couldn't retrieve content: Response code was 200 (expected 999)", str(e))
|
||||
|
||||
try:
|
||||
self.assertNotContains(response, 'once')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response should not contain 'once'")
|
||||
self.assertIn("Response should not contain 'once'", str(e))
|
||||
try:
|
||||
self.assertNotContains(response, 'once', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Response should not contain 'once'")
|
||||
self.assertIn("abc: Response should not contain 'once'", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'never', 1)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Found 0 instances of 'never' in response (expected 1)")
|
||||
self.assertIn("Found 0 instances of 'never' in response (expected 1)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'never', 1, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Found 0 instances of 'never' in response (expected 1)")
|
||||
self.assertIn("abc: Found 0 instances of 'never' in response (expected 1)", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'once', 0)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Found 1 instances of 'once' in response (expected 0)")
|
||||
self.assertIn("Found 1 instances of 'once' in response (expected 0)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'once', 0, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Found 1 instances of 'once' in response (expected 0)")
|
||||
self.assertIn("abc: Found 1 instances of 'once' in response (expected 0)", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'once', 2)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Found 1 instances of 'once' in response (expected 2)")
|
||||
self.assertIn("Found 1 instances of 'once' in response (expected 2)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'once', 2, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Found 1 instances of 'once' in response (expected 2)")
|
||||
self.assertIn("abc: Found 1 instances of 'once' in response (expected 2)", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'twice', 1)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Found 2 instances of 'twice' in response (expected 1)")
|
||||
self.assertIn("Found 2 instances of 'twice' in response (expected 1)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'twice', 1, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Found 2 instances of 'twice' in response (expected 1)")
|
||||
self.assertIn("abc: Found 2 instances of 'twice' in response (expected 1)", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'thrice')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Couldn't find 'thrice' in response")
|
||||
self.assertIn("Couldn't find 'thrice' in response", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'thrice', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Couldn't find 'thrice' in response")
|
||||
self.assertIn("abc: Couldn't find 'thrice' in response", str(e))
|
||||
|
||||
try:
|
||||
self.assertContains(response, 'thrice', 3)
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Found 0 instances of 'thrice' in response (expected 3)")
|
||||
self.assertIn("Found 0 instances of 'thrice' in response (expected 3)", str(e))
|
||||
try:
|
||||
self.assertContains(response, 'thrice', 3, msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Found 0 instances of 'thrice' in response (expected 3)")
|
||||
self.assertIn("abc: Found 0 instances of 'thrice' in response (expected 3)", str(e))
|
||||
|
||||
def test_unicode_contains(self):
|
||||
"Unicode characters can be found in template context"
|
||||
|
@ -141,12 +141,12 @@ class AssertTemplateUsedTests(TestCase):
|
|||
try:
|
||||
self.assertTemplateUsed(response, 'GET Template')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "No templates used to render the response")
|
||||
self.assertIn("No templates used to render the response", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateUsed(response, 'GET Template', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: No templates used to render the response")
|
||||
self.assertIn("abc: No templates used to render the response", str(e))
|
||||
|
||||
def test_single_context(self):
|
||||
"Template assertions work when there is a single context"
|
||||
|
@ -155,22 +155,22 @@ class AssertTemplateUsedTests(TestCase):
|
|||
try:
|
||||
self.assertTemplateNotUsed(response, 'Empty GET Template')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Template 'Empty GET Template' was used unexpectedly in rendering the response")
|
||||
self.assertIn("Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateNotUsed(response, 'Empty GET Template', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Template 'Empty GET Template' was used unexpectedly in rendering the response")
|
||||
self.assertIn("abc: Template 'Empty GET Template' was used unexpectedly in rendering the response", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateUsed(response, 'Empty POST Template')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template")
|
||||
self.assertIn("Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateUsed(response, 'Empty POST Template', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template")
|
||||
self.assertIn("abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template", str(e))
|
||||
|
||||
def test_multiple_context(self):
|
||||
"Template assertions work when there are multiple contexts"
|
||||
|
@ -186,17 +186,17 @@ class AssertTemplateUsedTests(TestCase):
|
|||
try:
|
||||
self.assertTemplateNotUsed(response, "form_view.html")
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Template 'form_view.html' was used unexpectedly in rendering the response")
|
||||
self.assertIn("Template 'form_view.html' was used unexpectedly in rendering the response", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateNotUsed(response, 'base.html')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Template 'base.html' was used unexpectedly in rendering the response")
|
||||
self.assertIn("Template 'base.html' was used unexpectedly in rendering the response", str(e))
|
||||
|
||||
try:
|
||||
self.assertTemplateUsed(response, "Valid POST Template")
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html")
|
||||
self.assertIn("Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html", str(e))
|
||||
|
||||
class AssertRedirectsTests(TestCase):
|
||||
def test_redirect_page(self):
|
||||
|
@ -206,12 +206,12 @@ class AssertRedirectsTests(TestCase):
|
|||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 301 (expected 302)")
|
||||
self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
|
||||
|
||||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 301 (expected 302)")
|
||||
self.assertIn("abc: Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
|
||||
|
||||
def test_lost_query(self):
|
||||
"An assertion is raised if the redirect location doesn't preserve GET parameters"
|
||||
|
@ -219,12 +219,12 @@ class AssertRedirectsTests(TestCase):
|
|||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'")
|
||||
self.assertIn("Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
|
||||
|
||||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'")
|
||||
self.assertIn("abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'", str(e))
|
||||
|
||||
def test_incorrect_target(self):
|
||||
"An assertion is raised if the response redirects to another target"
|
||||
|
@ -233,7 +233,7 @@ class AssertRedirectsTests(TestCase):
|
|||
# Should redirect to get_view
|
||||
self.assertRedirects(response, '/test_client/some_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 301 (expected 302)")
|
||||
self.assertIn("Response didn't redirect as expected: Response code was 301 (expected 302)", str(e))
|
||||
|
||||
def test_target_page(self):
|
||||
"An assertion is raised if the response redirect target cannot be retrieved as expected"
|
||||
|
@ -242,13 +242,13 @@ class AssertRedirectsTests(TestCase):
|
|||
# The redirect target responds with a 301 code, not 200
|
||||
self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
|
||||
self.assertIn("Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
|
||||
|
||||
try:
|
||||
# The redirect target responds with a 301 code, not 200
|
||||
self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
|
||||
self.assertIn("abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)", str(e))
|
||||
|
||||
def test_redirect_chain(self):
|
||||
"You can follow a redirect chain of multiple redirects"
|
||||
|
@ -339,12 +339,12 @@ class AssertRedirectsTests(TestCase):
|
|||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 200 (expected 302)")
|
||||
self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
|
||||
|
||||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 200 (expected 302)")
|
||||
self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
|
||||
|
||||
def test_redirect_on_non_redirect_page(self):
|
||||
"An assertion is raised if the original page couldn't be retrieved as expected"
|
||||
|
@ -353,12 +353,12 @@ class AssertRedirectsTests(TestCase):
|
|||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 200 (expected 302)")
|
||||
self.assertIn("Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
|
||||
|
||||
try:
|
||||
self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 200 (expected 302)")
|
||||
self.assertIn("abc: Response didn't redirect as expected: Response code was 200 (expected 302)", str(e))
|
||||
|
||||
|
||||
class AssertFormErrorTests(TestCase):
|
||||
|
@ -378,11 +378,11 @@ class AssertFormErrorTests(TestCase):
|
|||
try:
|
||||
self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "The form 'wrong_form' was not used to render the response")
|
||||
self.assertIn("The form 'wrong_form' was not used to render the response", str(e))
|
||||
try:
|
||||
self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "abc: The form 'wrong_form' was not used to render the response")
|
||||
self.assertIn("abc: The form 'wrong_form' was not used to render the response", str(e))
|
||||
|
||||
def test_unknown_field(self):
|
||||
"An assertion is raised if the field name is unknown"
|
||||
|
@ -400,11 +400,11 @@ class AssertFormErrorTests(TestCase):
|
|||
try:
|
||||
self.assertFormError(response, 'form', 'some_field', 'Some error.')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "The form 'form' in context 0 does not contain the field 'some_field'")
|
||||
self.assertIn("The form 'form' in context 0 does not contain the field 'some_field'", str(e))
|
||||
try:
|
||||
self.assertFormError(response, 'form', 'some_field', 'Some error.', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "abc: The form 'form' in context 0 does not contain the field 'some_field'")
|
||||
self.assertIn("abc: The form 'form' in context 0 does not contain the field 'some_field'", str(e))
|
||||
|
||||
def test_noerror_field(self):
|
||||
"An assertion is raised if the field doesn't have any errors"
|
||||
|
@ -422,11 +422,11 @@ class AssertFormErrorTests(TestCase):
|
|||
try:
|
||||
self.assertFormError(response, 'form', 'value', 'Some error.')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "The field 'value' on form 'form' in context 0 contains no errors")
|
||||
self.assertIn("The field 'value' on form 'form' in context 0 contains no errors", str(e))
|
||||
try:
|
||||
self.assertFormError(response, 'form', 'value', 'Some error.', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "abc: The field 'value' on form 'form' in context 0 contains no errors")
|
||||
self.assertIn("abc: The field 'value' on form 'form' in context 0 contains no errors", str(e))
|
||||
|
||||
def test_unknown_error(self):
|
||||
"An assertion is raised if the field doesn't contain the provided error"
|
||||
|
@ -444,11 +444,11 @@ class AssertFormErrorTests(TestCase):
|
|||
try:
|
||||
self.assertFormError(response, 'form', 'email', 'Some error.')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])")
|
||||
self.assertIn("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
|
||||
try:
|
||||
self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])")
|
||||
self.assertIn("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])", str(e))
|
||||
|
||||
def test_unknown_nonfield_error(self):
|
||||
"""
|
||||
|
@ -469,11 +469,11 @@ class AssertFormErrorTests(TestCase):
|
|||
try:
|
||||
self.assertFormError(response, 'form', None, 'Some error.')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )")
|
||||
self.assertIn("The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
|
||||
try:
|
||||
self.assertFormError(response, 'form', None, 'Some error.', msg_prefix='abc')
|
||||
except AssertionError, e:
|
||||
self.assertEqual(str(e), "abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )")
|
||||
self.assertIn("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )", str(e))
|
||||
|
||||
class LoginTests(TestCase):
|
||||
fixtures = ['testdata']
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
Tests for django test runner
|
||||
"""
|
||||
import StringIO
|
||||
import unittest
|
||||
import django
|
||||
|
||||
from django.test import simple
|
||||
from django.utils import unittest
|
||||
|
||||
class DjangoTestRunnerTests(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""
|
||||
Unit tests for reverse URL lookups.
|
||||
"""
|
||||
import unittest
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.core.urlresolvers import reverse, resolve, NoReverseMatch,\
|
||||
|
@ -11,6 +9,7 @@ from django.core.urlresolvers import reverse, resolve, NoReverseMatch,\
|
|||
from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
|
||||
from django.shortcuts import redirect
|
||||
from django.test import TestCase
|
||||
from django.utils import unittest
|
||||
|
||||
import urlconf_outer
|
||||
import urlconf_inner
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue