1
0
mirror of https://github.com/django/django.git synced 2024-12-23 01:25:58 +00:00

Used assertRaisesMessage() to test Django's error messages.

This commit is contained in:
Mads Jensen 2017-05-28 21:37:21 +02:00 committed by Tim Graham
parent 38988f289f
commit a51c4de194
69 changed files with 448 additions and 173 deletions

View File

@ -30,7 +30,8 @@ class TestRegistration(SimpleTestCase):
def test_prevent_double_registration(self): def test_prevent_double_registration(self):
self.site.register(Person) self.site.register(Person)
with self.assertRaises(admin.sites.AlreadyRegistered): msg = 'The model Person is already registered'
with self.assertRaisesMessage(admin.sites.AlreadyRegistered, msg):
self.site.register(Person) self.site.register(Person)
def test_registration_with_star_star_options(self): def test_registration_with_star_star_options(self):
@ -55,7 +56,8 @@ class TestRegistration(SimpleTestCase):
Exception is raised when trying to register an abstract model. Exception is raised when trying to register an abstract model.
Refs #12004. Refs #12004.
""" """
with self.assertRaises(ImproperlyConfigured): msg = 'The model Location is abstract, so it cannot be registered with admin.'
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.site.register(Location) self.site.register(Location)
def test_is_registered_model(self): def test_is_registered_model(self):

View File

@ -222,7 +222,7 @@ class UtilsTests(SimpleTestCase):
"article" "article"
) )
with self.assertRaises(AttributeError): with self.assertRaisesMessage(AttributeError, "Unable to lookup 'unknown' on Article"):
label_for_field("unknown", Article) label_for_field("unknown", Article)
def test_callable(obj): def test_callable(obj):

View File

@ -431,13 +431,23 @@ class AggregationTests(TestCase):
def test_field_error(self): def test_field_error(self):
# Bad field requests in aggregates are caught and reported # Bad field requests in aggregates are caught and reported
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'foo' into field. Choices are: authors, "
"contact, contact_id, hardbackbook, id, isbn, name, pages, price, "
"pubdate, publisher, publisher_id, rating, store, tags"
)
with self.assertRaisesMessage(FieldError, msg):
Book.objects.all().aggregate(num_authors=Count('foo')) Book.objects.all().aggregate(num_authors=Count('foo'))
with self.assertRaises(FieldError): with self.assertRaisesMessage(FieldError, msg):
Book.objects.all().annotate(num_authors=Count('foo')) Book.objects.all().annotate(num_authors=Count('foo'))
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'foo' into field. Choices are: authors, "
"contact, contact_id, hardbackbook, id, isbn, name, num_authors, "
"pages, price, pubdate, publisher, publisher_id, rating, store, tags"
)
with self.assertRaisesMessage(FieldError, msg):
Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo')) Book.objects.all().annotate(num_authors=Count('authors__id')).aggregate(Max('foo'))
def test_more(self): def test_more(self):
@ -738,19 +748,25 @@ class AggregationTests(TestCase):
def test_duplicate_alias(self): def test_duplicate_alias(self):
# Regression for #11256 - duplicating a default alias raises ValueError. # Regression for #11256 - duplicating a default alias raises ValueError.
with self.assertRaises(ValueError): msg = (
"The named annotation 'authors__age__avg' conflicts with "
"the default name for another annotation."
)
with self.assertRaisesMessage(ValueError, msg):
Book.objects.all().annotate(Avg('authors__age'), authors__age__avg=Avg('authors__age')) Book.objects.all().annotate(Avg('authors__age'), authors__age__avg=Avg('authors__age'))
def test_field_name_conflict(self): def test_field_name_conflict(self):
# Regression for #11256 - providing an aggregate name # Regression for #11256 - providing an aggregate name
# that conflicts with a field name on the model raises ValueError # that conflicts with a field name on the model raises ValueError
with self.assertRaises(ValueError): msg = "The annotation 'age' conflicts with a field on the model."
with self.assertRaisesMessage(ValueError, msg):
Author.objects.annotate(age=Avg('friends__age')) Author.objects.annotate(age=Avg('friends__age'))
def test_m2m_name_conflict(self): def test_m2m_name_conflict(self):
# Regression for #11256 - providing an aggregate name # Regression for #11256 - providing an aggregate name
# that conflicts with an m2m name on the model raises ValueError # that conflicts with an m2m name on the model raises ValueError
with self.assertRaises(ValueError): msg = "The annotation 'friends' conflicts with a field on the model."
with self.assertRaisesMessage(ValueError, msg):
Author.objects.annotate(friends=Count('friends')) Author.objects.annotate(friends=Count('friends'))
def test_values_queryset_non_conflict(self): def test_values_queryset_non_conflict(self):
@ -778,7 +794,8 @@ class AggregationTests(TestCase):
def test_reverse_relation_name_conflict(self): def test_reverse_relation_name_conflict(self):
# Regression for #11256 - providing an aggregate name # Regression for #11256 - providing an aggregate name
# that conflicts with a reverse-related name on the model raises ValueError # that conflicts with a reverse-related name on the model raises ValueError
with self.assertRaises(ValueError): msg = "The annotation 'book_contact_set' conflicts with a field on the model."
with self.assertRaisesMessage(ValueError, msg):
Author.objects.annotate(book_contact_set=Avg('friends__age')) Author.objects.annotate(book_contact_set=Avg('friends__age'))
def test_pickle(self): def test_pickle(self):
@ -937,7 +954,8 @@ class AggregationTests(TestCase):
# Regression for #10766 - Shouldn't be able to reference an aggregate # Regression for #10766 - Shouldn't be able to reference an aggregate
# fields in an aggregate() call. # fields in an aggregate() call.
with self.assertRaises(FieldError): msg = "Cannot compute Avg('mean_age'): 'mean_age' is an aggregate"
with self.assertRaisesMessage(FieldError, msg):
Book.objects.annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age')) Book.objects.annotate(mean_age=Avg('authors__age')).annotate(Avg('mean_age'))
def test_empty_filter_count(self): def test_empty_filter_count(self):

View File

@ -53,7 +53,8 @@ class AppsTests(SimpleTestCase):
""" """
Tests when INSTALLED_APPS contains an incorrect app config. Tests when INSTALLED_APPS contains an incorrect app config.
""" """
with self.assertRaises(ImproperlyConfigured): msg = "'apps.apps.BadConfig' must supply a name attribute."
with self.assertRaisesMessage(ImproperlyConfigured, msg):
with self.settings(INSTALLED_APPS=['apps.apps.BadConfig']): with self.settings(INSTALLED_APPS=['apps.apps.BadConfig']):
pass pass
@ -61,7 +62,8 @@ class AppsTests(SimpleTestCase):
""" """
Tests when INSTALLED_APPS contains a class that isn't an app config. Tests when INSTALLED_APPS contains a class that isn't an app config.
""" """
with self.assertRaises(ImproperlyConfigured): msg = "'apps.apps.NotAConfig' isn't a subclass of AppConfig."
with self.assertRaisesMessage(ImproperlyConfigured, msg):
with self.settings(INSTALLED_APPS=['apps.apps.NotAConfig']): with self.settings(INSTALLED_APPS=['apps.apps.NotAConfig']):
pass pass

View File

@ -445,7 +445,11 @@ class NoBackendsTest(TestCase):
self.user = User.objects.create_user('test', 'test@example.com', 'test') self.user = User.objects.create_user('test', 'test@example.com', 'test')
def test_raises_exception(self): def test_raises_exception(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'No authentication backends have been defined. '
'Does AUTHENTICATION_BACKENDS contain anything?'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.user.has_perm(('perm', TestObj())) self.user.has_perm(('perm', TestObj()))
@ -626,7 +630,11 @@ class ImproperlyConfiguredUserModelTest(TestCase):
request = HttpRequest() request = HttpRequest()
request.session = self.client.session request.session = self.client.session
with self.assertRaises(ImproperlyConfigured): msg = (
"AUTH_USER_MODEL refers to model 'thismodel.doesntexist' "
"that has not been installed"
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
get_user(request) get_user(request)

View File

@ -97,13 +97,18 @@ class BasicTestCase(TestCase):
@override_settings(AUTH_USER_MODEL='badsetting') @override_settings(AUTH_USER_MODEL='badsetting')
def test_swappable_user_bad_setting(self): def test_swappable_user_bad_setting(self):
"The alternate user setting must point to something in the format app.model" "The alternate user setting must point to something in the format app.model"
with self.assertRaises(ImproperlyConfigured): msg = "AUTH_USER_MODEL must be of the form 'app_label.model_name'"
with self.assertRaisesMessage(ImproperlyConfigured, msg):
get_user_model() get_user_model()
@override_settings(AUTH_USER_MODEL='thismodel.doesntexist') @override_settings(AUTH_USER_MODEL='thismodel.doesntexist')
def test_swappable_user_nonexistent_model(self): def test_swappable_user_nonexistent_model(self):
"The current user model must point to an installed model" "The current user model must point to an installed model"
with self.assertRaises(ImproperlyConfigured): msg = (
"AUTH_USER_MODEL refers to model 'thismodel.doesntexist' "
"that has not been installed"
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
get_user_model() get_user_model()
def test_user_verbose_names_translatable(self): def test_user_verbose_names_translatable(self):

View File

@ -158,7 +158,8 @@ class ChangepasswordManagementCommandTestCase(TestCase):
A CommandError should be thrown by handle() if the user enters in A CommandError should be thrown by handle() if the user enters in
mismatched passwords three times. mismatched passwords three times.
""" """
with self.assertRaises(CommandError): msg = "Aborting password change for user 'joe' after 3 attempts"
with self.assertRaisesMessage(CommandError, msg):
call_command('changepassword', username='joe', stdout=self.stdout, stderr=self.stderr) call_command('changepassword', username='joe', stdout=self.stdout, stderr=self.stderr)
@mock.patch.object(changepassword.Command, '_get_pass', return_value='1234567890') @mock.patch.object(changepassword.Command, '_get_pass', return_value='1234567890')
@ -316,7 +317,7 @@ class CreatesuperuserManagementCommandTestCase(TestCase):
# We skip validation because the temporary substitution of the # We skip validation because the temporary substitution of the
# swappable User model messes with validation. # swappable User model messes with validation.
new_io = StringIO() new_io = StringIO()
with self.assertRaises(CommandError): with self.assertRaisesMessage(CommandError, 'You must use --email with --noinput.'):
call_command( call_command(
"createsuperuser", "createsuperuser",
interactive=False, interactive=False,

View File

@ -335,8 +335,8 @@ class ModelTest(TestCase):
self.assertEqual(article.headline, notlazy) self.assertEqual(article.headline, notlazy)
def test_emptyqs(self): def test_emptyqs(self):
# Can't be instantiated msg = "EmptyQuerySet can't be instantiated"
with self.assertRaises(TypeError): with self.assertRaisesMessage(TypeError, msg):
EmptyQuerySet() EmptyQuerySet()
self.assertIsInstance(Article.objects.none(), EmptyQuerySet) self.assertIsInstance(Article.objects.none(), EmptyQuerySet)
self.assertNotIsInstance('', EmptyQuerySet) self.assertNotIsInstance('', EmptyQuerySet)
@ -397,7 +397,8 @@ class ModelTest(TestCase):
def test_hash(self): def test_hash(self):
# Value based on PK # Value based on PK
self.assertEqual(hash(Article(id=1)), hash(1)) self.assertEqual(hash(Article(id=1)), hash(1))
with self.assertRaises(TypeError): msg = 'Model instances without primary key value are unhashable'
with self.assertRaisesMessage(TypeError, msg):
# No PK value -> unhashable (because save() would then change # No PK value -> unhashable (because save() would then change
# hash) # hash)
hash(Article()) hash(Article())
@ -618,7 +619,7 @@ class SelectOnSaveTests(TestCase):
with self.assertNumQueries(1): with self.assertNumQueries(1):
asos.save(force_update=True) asos.save(force_update=True)
Article.objects.all().delete() Article.objects.all().delete()
with self.assertRaises(DatabaseError): with self.assertRaisesMessage(DatabaseError, 'Forced update did not affect any rows.'):
with self.assertNumQueries(1): with self.assertNumQueries(1):
asos.save(force_update=True) asos.save(force_update=True)
@ -653,9 +654,13 @@ class SelectOnSaveTests(TestCase):
# This is not wanted behavior, but this is how Django has always # This is not wanted behavior, but this is how Django has always
# behaved for databases that do not return correct information # behaved for databases that do not return correct information
# about matched rows for UPDATE. # about matched rows for UPDATE.
with self.assertRaises(DatabaseError): with self.assertRaisesMessage(DatabaseError, 'Forced update did not affect any rows.'):
asos.save(force_update=True) asos.save(force_update=True)
with self.assertRaises(DatabaseError): msg = (
"An error occurred in the current transaction. You can't "
"execute queries until the end of the 'atomic' block."
)
with self.assertRaisesMessage(DatabaseError, msg):
asos.save(update_fields=['pub_date']) asos.save(update_fields=['pub_date'])
finally: finally:
Article._base_manager._queryset_class = orig_class Article._base_manager._queryset_class = orig_class
@ -688,7 +693,8 @@ class ModelRefreshTests(TestCase):
def test_unknown_kwarg(self): def test_unknown_kwarg(self):
s = SelfRef.objects.create() s = SelfRef.objects.create()
with self.assertRaises(TypeError): msg = "refresh_from_db() got an unexpected keyword argument 'unknown_kwarg'"
with self.assertRaisesMessage(TypeError, msg):
s.refresh_from_db(unknown_kwarg=10) s.refresh_from_db(unknown_kwarg=10)
def test_refresh_fk(self): def test_refresh_fk(self):

View File

@ -108,7 +108,8 @@ class BulkCreateTests(TestCase):
""" """
valid_country = Country(name='Germany', iso_two_letter='DE') valid_country = Country(name='Germany', iso_two_letter='DE')
invalid_country = Country(id=0, name='Poland', iso_two_letter='PL') invalid_country = Country(id=0, name='Poland', iso_two_letter='PL')
with self.assertRaises(ValueError): msg = 'The database backend does not accept 0 as a value for AutoField.'
with self.assertRaisesMessage(ValueError, msg):
Country.objects.bulk_create([valid_country, invalid_country]) Country.objects.bulk_create([valid_country, invalid_country])
def test_batch_same_vals(self): def test_batch_same_vals(self):

View File

@ -179,7 +179,8 @@ class CheckCommandTests(SimpleTestCase):
@override_system_checks([simple_system_check, tagged_system_check]) @override_system_checks([simple_system_check, tagged_system_check])
def test_invalid_tag(self): def test_invalid_tag(self):
with self.assertRaises(CommandError): msg = 'There is no system check with the "missingtag" tag.'
with self.assertRaisesMessage(CommandError, msg):
call_command('check', tags=['missingtag']) call_command('check', tags=['missingtag'])
@override_system_checks([simple_system_check]) @override_system_checks([simple_system_check])

View File

@ -37,7 +37,11 @@ class CustomColumnsTests(TestCase):
) )
def test_field_error(self): def test_field_error(self):
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'firstname' into field. Choices are: "
"Author_ID, article, first_name, last_name, primary_set"
)
with self.assertRaisesMessage(FieldError, msg):
Author.objects.filter(firstname__exact="John") Author.objects.filter(firstname__exact="John")
def test_attribute_error(self): def test_attribute_error(self):

View File

@ -319,7 +319,8 @@ class BilateralTransformTests(TestCase):
def test_bilateral_inner_qs(self): def test_bilateral_inner_qs(self):
with register_lookup(models.CharField, UpperBilateralTransform): with register_lookup(models.CharField, UpperBilateralTransform):
with self.assertRaises(NotImplementedError): msg = 'Bilateral transformations on nested querysets are not supported.'
with self.assertRaisesMessage(NotImplementedError, msg):
Author.objects.filter(name__upper__in=Author.objects.values_list('name')) Author.objects.filter(name__upper__in=Author.objects.values_list('name'))
def test_bilateral_multi_value(self): def test_bilateral_multi_value(self):
@ -501,13 +502,14 @@ class LookupTransformCallOrderTests(TestCase):
def test_call_order(self): def test_call_order(self):
with register_lookup(models.DateField, TrackCallsYearTransform): with register_lookup(models.DateField, TrackCallsYearTransform):
# junk lookup - tries lookup, then transform, then fails # junk lookup - tries lookup, then transform, then fails
with self.assertRaises(FieldError): msg = "Unsupported lookup 'junk' for IntegerField or join on the field not permitted."
with self.assertRaisesMessage(FieldError, msg):
Author.objects.filter(birthdate__testyear__junk=2012) Author.objects.filter(birthdate__testyear__junk=2012)
self.assertEqual(TrackCallsYearTransform.call_order, self.assertEqual(TrackCallsYearTransform.call_order,
['lookup', 'transform']) ['lookup', 'transform'])
TrackCallsYearTransform.call_order = [] TrackCallsYearTransform.call_order = []
# junk transform - tries transform only, then fails # junk transform - tries transform only, then fails
with self.assertRaises(FieldError): with self.assertRaisesMessage(FieldError, msg):
Author.objects.filter(birthdate__testyear__junk__more_junk=2012) Author.objects.filter(birthdate__testyear__junk__more_junk=2012)
self.assertEqual(TrackCallsYearTransform.call_order, self.assertEqual(TrackCallsYearTransform.call_order,
['transform']) ['transform'])

View File

@ -58,7 +58,8 @@ class CustomManagerTests(TestCase):
# Methods with queryset_only=False are copied even if they are private. # Methods with queryset_only=False are copied even if they are private.
manager._optin_private_method() manager._optin_private_method()
# Methods with queryset_only=True aren't copied even if they are public. # Methods with queryset_only=True aren't copied even if they are public.
with self.assertRaises(AttributeError): msg = "%r object has no attribute 'optout_public_method'" % manager.__class__.__name__
with self.assertRaisesMessage(AttributeError, msg):
manager.optout_public_method() manager.optout_public_method()
def test_manager_use_queryset_methods(self): def test_manager_use_queryset_methods(self):
@ -93,7 +94,8 @@ class CustomManagerTests(TestCase):
querysets. querysets.
""" """
Person.custom_queryset_custom_manager.manager_only() Person.custom_queryset_custom_manager.manager_only()
with self.assertRaises(AttributeError): msg = "'CustomQuerySet' object has no attribute 'manager_only'"
with self.assertRaisesMessage(AttributeError, msg):
Person.custom_queryset_custom_manager.all().manager_only() Person.custom_queryset_custom_manager.all().manager_only()
def test_queryset_and_manager(self): def test_queryset_and_manager(self):
@ -116,7 +118,8 @@ class CustomManagerTests(TestCase):
The default manager, "objects", doesn't exist, because a custom one The default manager, "objects", doesn't exist, because a custom one
was provided. was provided.
""" """
with self.assertRaises(AttributeError): msg = "type object 'Book' has no attribute 'objects'"
with self.assertRaisesMessage(AttributeError, msg):
Book.objects Book.objects
def test_filtering(self): def test_filtering(self):

View File

@ -145,7 +145,7 @@ class BasicCustomPKTests(TestCase):
# Or we can use the real attribute name for the primary key: # Or we can use the real attribute name for the primary key:
self.assertEqual(e.employee_code, 123) self.assertEqual(e.employee_code, 123)
with self.assertRaises(AttributeError): with self.assertRaisesMessage(AttributeError, "'Employee' object has no attribute 'id'"):
e.id e.id
def test_in_bulk(self): def test_in_bulk(self):

View File

@ -60,7 +60,11 @@ class OnDeleteTests(TestCase):
def test_protect(self): def test_protect(self):
a = create_a('protect') a = create_a('protect')
with self.assertRaises(IntegrityError): msg = (
"Cannot delete some instances of model 'R' because they are "
"referenced through a protected foreign key: 'A.protect'"
)
with self.assertRaisesMessage(IntegrityError, msg):
a.protect.delete() a.protect.delete()
def test_do_nothing(self): def test_do_nothing(self):

View File

@ -244,9 +244,10 @@ class ProxyDeleteTest(TestCase):
self.assertEqual(len(FooFileProxy.objects.all()), 0) self.assertEqual(len(FooFileProxy.objects.all()), 0)
def test_19187_values(self): def test_19187_values(self):
with self.assertRaises(TypeError): msg = 'Cannot call delete() after .values() or .values_list()'
with self.assertRaisesMessage(TypeError, msg):
Image.objects.values().delete() Image.objects.values().delete()
with self.assertRaises(TypeError): with self.assertRaisesMessage(TypeError, msg):
Image.objects.values_list().delete() Image.objects.values_list().delete()

View File

@ -97,16 +97,18 @@ class DistinctOnTests(TestCase):
def test_distinct_not_implemented_checks(self): def test_distinct_not_implemented_checks(self):
# distinct + annotate not allowed # distinct + annotate not allowed
with self.assertRaises(NotImplementedError): msg = 'annotate() + distinct(fields) is not implemented.'
with self.assertRaisesMessage(NotImplementedError, msg):
Celebrity.objects.annotate(Max('id')).distinct('id')[0] Celebrity.objects.annotate(Max('id')).distinct('id')[0]
with self.assertRaises(NotImplementedError): with self.assertRaisesMessage(NotImplementedError, msg):
Celebrity.objects.distinct('id').annotate(Max('id'))[0] Celebrity.objects.distinct('id').annotate(Max('id'))[0]
# However this check is done only when the query executes, so you # However this check is done only when the query executes, so you
# can use distinct() to remove the fields before execution. # can use distinct() to remove the fields before execution.
Celebrity.objects.distinct('id').annotate(Max('id')).distinct()[0] Celebrity.objects.distinct('id').annotate(Max('id')).distinct()[0]
# distinct + aggregate not allowed # distinct + aggregate not allowed
with self.assertRaises(NotImplementedError): msg = 'aggregate() + distinct(fields) not implemented.'
with self.assertRaisesMessage(NotImplementedError, msg):
Celebrity.objects.distinct('id').aggregate(Max('id')) Celebrity.objects.distinct('id').aggregate(Max('id'))
def test_distinct_on_in_ordered_subquery(self): def test_distinct_on_in_ordered_subquery(self):

View File

@ -246,7 +246,8 @@ class BasicExpressionsTests(TestCase):
) )
with transaction.atomic(): with transaction.atomic():
with self.assertRaises(FieldError): msg = "Joined field references are not permitted in this query"
with self.assertRaisesMessage(FieldError, msg):
Company.objects.exclude( Company.objects.exclude(
ceo__firstname=F('point_of_contact__firstname') ceo__firstname=F('point_of_contact__firstname')
).update(name=F('point_of_contact__lastname')) ).update(name=F('point_of_contact__lastname'))
@ -293,13 +294,15 @@ class BasicExpressionsTests(TestCase):
def test(): def test():
test_gmbh.point_of_contact = F("ceo") test_gmbh.point_of_contact = F("ceo")
with self.assertRaises(ValueError): msg = 'F(ceo)": "Company.point_of_contact" must be a "Employee" instance.'
with self.assertRaisesMessage(ValueError, msg):
test() test()
test_gmbh.point_of_contact = test_gmbh.ceo test_gmbh.point_of_contact = test_gmbh.ceo
test_gmbh.save() test_gmbh.save()
test_gmbh.name = F("ceo__last_name") test_gmbh.name = F("ceo__last_name")
with self.assertRaises(FieldError): msg = 'Joined field references are not permitted in this query'
with self.assertRaisesMessage(FieldError, msg):
test_gmbh.save() test_gmbh.save()
def test_object_update_unsaved_objects(self): def test_object_update_unsaved_objects(self):

View File

@ -128,17 +128,21 @@ class FlatpageTemplateTagTests(TestCase):
def render(t): def render(t):
return Template(t).render(Context()) return Template(t).render(Context())
with self.assertRaises(TemplateSyntaxError): msg = (
"get_flatpages expects a syntax of get_flatpages "
"['url_starts_with'] [for user] as context_name"
)
with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages %}") render("{% load flatpages %}{% get_flatpages %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages as %}") render("{% load flatpages %}{% get_flatpages as %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages cheesecake flatpages %}") render("{% load flatpages %}{% get_flatpages cheesecake flatpages %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages as flatpages asdf %}") render("{% load flatpages %}{% get_flatpages as flatpages asdf %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages cheesecake user as flatpages %}") render("{% load flatpages %}{% get_flatpages cheesecake user as flatpages %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages for user as flatpages asdf %}") render("{% load flatpages %}{% get_flatpages for user as flatpages asdf %}")
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
render("{% load flatpages %}{% get_flatpages prefix for user as flatpages asdf %}") render("{% load flatpages %}{% get_flatpages prefix for user as flatpages asdf %}")

View File

@ -20,13 +20,15 @@ class ForceTests(TestCase):
# Won't work because force_update and force_insert are mutually # Won't work because force_update and force_insert are mutually
# exclusive # exclusive
c.value = 4 c.value = 4
with self.assertRaises(ValueError): msg = 'Cannot force both insert and updating in model saving.'
with self.assertRaisesMessage(ValueError, msg):
c.save(force_insert=True, force_update=True) c.save(force_insert=True, force_update=True)
# Try to update something that doesn't have a primary key in the first # Try to update something that doesn't have a primary key in the first
# place. # place.
c1 = Counter(name="two", value=2) c1 = Counter(name="two", value=2)
with self.assertRaises(ValueError): msg = 'Cannot force an update in save() with no primary key.'
with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(): with transaction.atomic():
c1.save(force_update=True) c1.save(force_update=True)
c1.save(force_insert=True) c1.save(force_insert=True)
@ -40,7 +42,8 @@ class ForceTests(TestCase):
# Trying to update should still fail, even with manual primary keys, if # Trying to update should still fail, even with manual primary keys, if
# the data isn't in the database already. # the data isn't in the database already.
obj = WithCustomPK(name=1, value=1) obj = WithCustomPK(name=1, value=1)
with self.assertRaises(DatabaseError): msg = 'Forced update did not affect any rows.'
with self.assertRaisesMessage(DatabaseError, msg):
with transaction.atomic(): with transaction.atomic():
obj.save(force_update=True) obj.save(force_update=True)

View File

@ -368,7 +368,12 @@ class MultiColumnFKTests(TestCase):
ArticleTag.objects.create(article=a1, name="foo") ArticleTag.objects.create(article=a1, name="foo")
self.assertEqual(Article.objects.filter(tag__name="foo").count(), 1) self.assertEqual(Article.objects.filter(tag__name="foo").count(), 1)
self.assertEqual(Article.objects.filter(tag__name="bar").count(), 0) self.assertEqual(Article.objects.filter(tag__name="bar").count(), 0)
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'tags' into field. Choices are: "
"active_translation, active_translation_q, articletranslation, "
"id, idea_things, newsarticle, pub_date, tag"
)
with self.assertRaisesMessage(FieldError, msg):
Article.objects.filter(tags__name="foo") Article.objects.filter(tags__name="foo")
def test_many_to_many_related_query_name(self): def test_many_to_many_related_query_name(self):
@ -377,7 +382,12 @@ class MultiColumnFKTests(TestCase):
a1.ideas.add(i1) a1.ideas.add(i1)
self.assertEqual(Article.objects.filter(idea_things__name="idea1").count(), 1) self.assertEqual(Article.objects.filter(idea_things__name="idea1").count(), 1)
self.assertEqual(Article.objects.filter(idea_things__name="idea2").count(), 0) self.assertEqual(Article.objects.filter(idea_things__name="idea2").count(), 0)
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'ideas' into field. Choices are: "
"active_translation, active_translation_q, articletranslation, "
"id, idea_things, newsarticle, pub_date, tag"
)
with self.assertRaisesMessage(FieldError, msg):
Article.objects.filter(ideas__name="idea1") Article.objects.filter(ideas__name="idea1")
@translation.override('fi') @translation.override('fi')

View File

@ -18,9 +18,8 @@ class UUIDFieldTest(SimpleTestCase):
def test_uuidfield_3(self): def test_uuidfield_3(self):
field = UUIDField() field = UUIDField()
with self.assertRaises(ValidationError) as cm: with self.assertRaisesMessage(ValidationError, 'Enter a valid UUID.'):
field.clean('550e8400') field.clean('550e8400')
self.assertEqual(cm.exception.messages[0], 'Enter a valid UUID.')
def test_uuidfield_4(self): def test_uuidfield_4(self):
field = UUIDField() field = UUIDField()

View File

@ -1338,7 +1338,8 @@ ArticleFormSet = formset_factory(ArticleForm)
class TestIsBoundBehavior(SimpleTestCase): class TestIsBoundBehavior(SimpleTestCase):
def test_no_data_raises_validation_error(self): def test_no_data_raises_validation_error(self):
with self.assertRaises(ValidationError): msg = 'ManagementForm data is missing or has been tampered with'
with self.assertRaisesMessage(ValidationError, msg):
ArticleFormSet({}).is_valid() ArticleFormSet({}).is_valid()
def test_with_management_data_attrs_work_fine(self): def test_with_management_data_attrs_work_fine(self):

View File

@ -247,7 +247,11 @@ class RelatedModelFormTests(SimpleTestCase):
model = A model = A
fields = '__all__' fields = '__all__'
with self.assertRaises(ValueError): msg = (
"Cannot create form field for 'ref' yet, because "
"its related model 'B' has not been loaded yet"
)
with self.assertRaisesMessage(ValueError, msg):
ModelFormMetaclass('Form', (ModelForm,), {'Meta': Meta}) ModelFormMetaclass('Form', (ModelForm,), {'Meta': Meta})
class B(models.Model): class B(models.Model):

View File

@ -347,7 +347,12 @@ class GenericRelationsTests(TestCase):
def test_generic_relation_related_name_default(self): def test_generic_relation_related_name_default(self):
# GenericRelation isn't usable from the reverse side by default. # GenericRelation isn't usable from the reverse side by default.
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'vegetable' into field. Choices are: "
"animal, content_object, content_type, content_type_id, id, "
"manualpk, object_id, tag, valuabletaggeditem"
)
with self.assertRaisesMessage(FieldError, msg):
TaggedItem.objects.filter(vegetable__isnull=True) TaggedItem.objects.filter(vegetable__isnull=True)
def test_multiple_gfk(self): def test_multiple_gfk(self):

View File

@ -273,7 +273,11 @@ class TemplateViewTest(SimpleTestCase):
""" """
A template view must provide a template name. A template view must provide a template name.
""" """
with self.assertRaises(ImproperlyConfigured): msg = (
"TemplateResponseMixin requires either a definition of "
"'template_name' or an implementation of 'get_template_names()'"
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/template/no_template/') self.client.get('/template/no_template/')
@require_jinja2 @require_jinja2

View File

@ -79,7 +79,11 @@ class ArchiveIndexViewTests(TestDataMixin, TestCase):
self.assertTemplateUsed(res, 'generic_views/book_detail.html') self.assertTemplateUsed(res, 'generic_views/book_detail.html')
def test_archive_view_invalid(self): def test_archive_view_invalid(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'BookArchive is missing a QuerySet. Define BookArchive.model, '
'BookArchive.queryset, or override BookArchive.get_queryset().'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/dates/books/invalid/') self.client.get('/dates/books/invalid/')
def test_archive_view_by_month(self): def test_archive_view_by_month(self):

View File

@ -175,7 +175,11 @@ class DetailViewTest(TestCase):
self.client.get('/detail/author/invalid/url/') self.client.get('/detail/author/invalid/url/')
def test_invalid_queryset(self): def test_invalid_queryset(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'AuthorDetail is missing a QuerySet. Define AuthorDetail.model, '
'AuthorDetail.queryset, or override AuthorDetail.get_queryset().'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/detail/author/invalid/qs/') self.client.get('/detail/author/invalid/qs/')
def test_non_model_object_with_meta(self): def test_non_model_object_with_meta(self):

View File

@ -159,7 +159,11 @@ class CreateViewTests(TestCase):
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>']) self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
def test_create_without_redirect(self): def test_create_without_redirect(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'No URL to redirect to. Either provide a url or define a '
'get_absolute_url method on the Model.'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.post('/edit/authors/create/naive/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) self.client.post('/edit/authors/create/naive/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'})
def test_create_restricted(self): def test_create_restricted(self):
@ -312,9 +316,11 @@ class UpdateViewTests(TestCase):
name='Randall Munroe', name='Randall Munroe',
slug='randall-munroe', slug='randall-munroe',
) )
# Should raise exception -- No redirect URL provided, and no msg = (
# get_absolute_url provided 'No URL to redirect to. Either provide a url or define a '
with self.assertRaises(ImproperlyConfigured): 'get_absolute_url method on the Model.'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.post( self.client.post(
'/edit/author/%d/update/naive/' % a.pk, '/edit/author/%d/update/naive/' % a.pk,
{'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'}
@ -404,7 +410,6 @@ class DeleteViewTests(TestCase):
name='Randall Munroe', name='Randall Munroe',
slug='randall-munroe', slug='randall-munroe',
) )
# Should raise exception -- No redirect URL provided, and no msg = 'No URL to redirect to. Provide a success_url.'
# get_absolute_url provided with self.assertRaisesMessage(ImproperlyConfigured, msg):
with self.assertRaises(ImproperlyConfigured):
self.client.post('/edit/author/%d/delete/naive/' % a.pk) self.client.post('/edit/author/%d/delete/naive/' % a.pk)

View File

@ -200,7 +200,11 @@ class ListViewTests(TestCase):
self.assertTemplateUsed(res, 'generic_views/author_list.html') self.assertTemplateUsed(res, 'generic_views/author_list.html')
def test_missing_items(self): def test_missing_items(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'AuthorList is missing a QuerySet. Define AuthorList.model, '
'AuthorList.queryset, or override AuthorList.get_queryset().'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/list/authors/invalid/') self.client.get('/list/authors/invalid/')
def test_paginated_list_view_does_not_load_entire_table(self): def test_paginated_list_view_does_not_load_entire_table(self):

View File

@ -118,7 +118,11 @@ class EarliestOrLatestTests(TestCase):
# "get_latest_by" set -- just pass in the field name manually. # "get_latest_by" set -- just pass in the field name manually.
Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1)) Person.objects.create(name="Ralph", birthday=datetime(1950, 1, 1))
p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3)) p2 = Person.objects.create(name="Stephanie", birthday=datetime(1960, 2, 3))
with self.assertRaises(AssertionError): msg = (
"earliest() and latest() require either a field_name parameter or "
"'get_latest_by' in the model"
)
with self.assertRaisesMessage(AssertionError, msg):
Person.objects.latest() Person.objects.latest()
self.assertEqual(Person.objects.latest("birthday"), p2) self.assertEqual(Person.objects.latest("birthday"), p2)

View File

@ -78,7 +78,8 @@ class URLPrefixTests(URLTestCaseBase):
@override_settings(ROOT_URLCONF='i18n.patterns.urls.wrong') @override_settings(ROOT_URLCONF='i18n.patterns.urls.wrong')
def test_invalid_prefix_use(self): def test_invalid_prefix_use(self):
with self.assertRaises(ImproperlyConfigured): msg = 'Using i18n_patterns in an included URLconf is not allowed.'
with self.assertRaisesMessage(ImproperlyConfigured, msg):
reverse('account:register') reverse('account:register')

View File

@ -315,7 +315,11 @@ class LookupTests(TestCase):
# However, an exception FieldDoesNotExist will be thrown if you specify # However, an exception FieldDoesNotExist will be thrown if you specify
# a nonexistent field name in values() (a field that is neither in the # a nonexistent field name in values() (a field that is neither in the
# model nor in extra(select)). # model nor in extra(select)).
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'id_plus_two' into field. Choices are: "
"author, author_id, headline, id, id_plus_one, pub_date, slug, tag"
)
with self.assertRaisesMessage(FieldError, msg):
Article.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_two') Article.objects.extra(select={'id_plus_one': 'id + 1'}).values('id', 'id_plus_two')
# If you don't specify field names to values(), all are returned. # If you don't specify field names to values(), all are returned.
self.assertSequenceEqual( self.assertSequenceEqual(
@ -733,11 +737,16 @@ class LookupTests(TestCase):
""" """
A lookup query containing non-fields raises the proper exception. A lookup query containing non-fields raises the proper exception.
""" """
with self.assertRaises(FieldError): msg = "Unsupported lookup 'blahblah' for CharField or join on the field not permitted."
with self.assertRaisesMessage(FieldError, msg):
Article.objects.filter(headline__blahblah=99) Article.objects.filter(headline__blahblah=99)
with self.assertRaises(FieldError): with self.assertRaisesMessage(FieldError, msg):
Article.objects.filter(headline__blahblah__exact=99) Article.objects.filter(headline__blahblah__exact=99)
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'blahblah' into field. Choices are: "
"author, author_id, headline, id, pub_date, slug, tag"
)
with self.assertRaisesMessage(FieldError, msg):
Article.objects.filter(blahblah=99) Article.objects.filter(blahblah=99)
def test_lookup_collision(self): def test_lookup_collision(self):

View File

@ -102,7 +102,7 @@ class M2MRegressionTests(TestCase):
c1 = TagCollection.objects.create(name='c1') c1 = TagCollection.objects.create(name='c1')
c1.tags.set([t1, t2]) c1.tags.set([t1, t2])
with self.assertRaises(TypeError): with self.assertRaisesMessage(TypeError, "'int' object is not iterable"):
c1.tags.set(7) c1.tags.set(7)
c1.refresh_from_db() c1.refresh_from_db()

View File

@ -29,7 +29,11 @@ class ManyToManyTests(TestCase):
# Create an Article. # Create an Article.
a5 = Article(headline='Django lets you reate Web apps easily') a5 = Article(headline='Django lets you reate Web apps easily')
# You can't associate it with a Publication until it's been saved. # You can't associate it with a Publication until it's been saved.
with self.assertRaises(ValueError): msg = (
'"<Article: Django lets you reate Web apps easily>" needs to have '
'a value for field "id" before this many-to-many relationship can be used.'
)
with self.assertRaisesMessage(ValueError, msg):
getattr(a5, 'publications') getattr(a5, 'publications')
# Save it! # Save it!
a5.save() a5.save()

View File

@ -406,7 +406,8 @@ class ManyToOneTests(TestCase):
self.assertEqual(a3.reporter.id, self.r2.id) self.assertEqual(a3.reporter.id, self.r2.id)
# Get should respect explicit foreign keys as well. # Get should respect explicit foreign keys as well.
with self.assertRaises(MultipleObjectsReturned): msg = 'get() returned more than one Article -- it returned 2!'
with self.assertRaisesMessage(MultipleObjectsReturned, msg):
Article.objects.get(reporter_id=self.r.id) Article.objects.get(reporter_id=self.r.id)
self.assertEqual( self.assertEqual(
repr(a3), repr(a3),
@ -484,7 +485,11 @@ class ManyToOneTests(TestCase):
setattr(c, "parent", None) setattr(c, "parent", None)
# You also can't assign an object of the wrong type here # You also can't assign an object of the wrong type here
with self.assertRaises(ValueError): msg = (
'Cannot assign "<First: First object (1)>": "Child.parent" must '
'be a "Parent" instance.'
)
with self.assertRaisesMessage(ValueError, msg):
setattr(c, "parent", First(id=1, second=1)) setattr(c, "parent", First(id=1, second=1))
# You can assign None to Child.parent during object creation. # You can assign None to Child.parent during object creation.
@ -550,7 +555,8 @@ class ManyToOneTests(TestCase):
p = Parent.objects.create(name="Parent") p = Parent.objects.create(name="Parent")
c = Child.objects.create(name="Child", parent=p) c = Child.objects.create(name="Child", parent=p)
with self.assertRaises(ValueError): msg = 'Cannot assign "%r": "Child.parent" must be a "Parent" instance.' % c
with self.assertRaisesMessage(ValueError, msg):
Child.objects.create(name="Grandchild", parent=c) Child.objects.create(name="Grandchild", parent=c)
def test_fk_instantiation_outside_model(self): def test_fk_instantiation_outside_model(self):

View File

@ -757,8 +757,18 @@ class MakeMigrationsTests(MigrationTestBase):
makemigrations exits if it detects a conflict. makemigrations exits if it detects a conflict.
""" """
with self.temporary_migration_module(module="migrations.test_migrations_conflict"): with self.temporary_migration_module(module="migrations.test_migrations_conflict"):
with self.assertRaises(CommandError): with self.assertRaises(CommandError) as context:
call_command("makemigrations") call_command("makemigrations")
exception_message = str(context.exception)
self.assertIn(
'Conflicting migrations detected; multiple leaf nodes '
'in the migration graph:',
exception_message
)
self.assertIn('0002_second', exception_message)
self.assertIn('0002_conflicting_second', exception_message)
self.assertIn('in migrations', exception_message)
self.assertIn("To fix them run 'python manage.py makemigrations --merge'", exception_message)
def test_makemigrations_merge_no_conflict(self): def test_makemigrations_merge_no_conflict(self):
""" """
@ -780,7 +790,8 @@ class MakeMigrationsTests(MigrationTestBase):
""" """
makemigrations exits if no app is specified with 'empty' mode. makemigrations exits if no app is specified with 'empty' mode.
""" """
with self.assertRaises(CommandError): msg = 'You must supply at least one app label when using --empty.'
with self.assertRaisesMessage(CommandError, msg):
call_command("makemigrations", empty=True) call_command("makemigrations", empty=True)
def test_makemigrations_empty_migration(self): def test_makemigrations_empty_migration(self):

View File

@ -1945,7 +1945,7 @@ class OperationTests(OperationTestBase):
operation.database_backwards("test_runpython", editor, project_state, new_state) operation.database_backwards("test_runpython", editor, project_state, new_state)
self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0) self.assertEqual(project_state.apps.get_model("test_runpython", "Pony").objects.count(), 0)
# Now test we can't use a string # Now test we can't use a string
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, 'RunPython must be supplied with a callable'):
migrations.RunPython("print 'ahahaha'") migrations.RunPython("print 'ahahaha'")
# And deconstruction # And deconstruction
definition = operation.deconstruct() definition = operation.deconstruct()

View File

@ -21,7 +21,8 @@ class DecimalFieldTests(TestCase):
# Uses default rounding of ROUND_HALF_EVEN. # Uses default rounding of ROUND_HALF_EVEN.
self.assertEqual(f.to_python(2.0625), Decimal('2.062')) self.assertEqual(f.to_python(2.0625), Decimal('2.062'))
self.assertEqual(f.to_python(2.1875), Decimal('2.188')) self.assertEqual(f.to_python(2.1875), Decimal('2.188'))
with self.assertRaises(ValidationError): msg = "'abc' value must be a decimal number."
with self.assertRaisesMessage(ValidationError, msg):
f.to_python('abc') f.to_python('abc')
def test_default(self): def test_default(self):

View File

@ -21,8 +21,7 @@ class TestFloatField(TestCase):
instance.size = instance instance.size = instance
msg = ( msg = (
'Tried to update field model_fields.FloatModel.size with a model ' 'Tried to update field model_fields.FloatModel.size with a model '
'instance, %r. Use a value ' 'instance, %r. Use a value compatible with FloatField.'
'compatible with FloatField.'
) % instance ) % instance
with transaction.atomic(): with transaction.atomic():
with self.assertRaisesMessage(TypeError, msg): with self.assertRaisesMessage(TypeError, msg):
@ -30,5 +29,5 @@ class TestFloatField(TestCase):
# Try setting field to object on retrieved object # Try setting field to object on retrieved object
obj = FloatModel.objects.get(pk=instance.id) obj = FloatModel.objects.get(pk=instance.id)
obj.size = obj obj.size = obj
with self.assertRaises(TypeError): with self.assertRaisesMessage(TypeError, msg):
obj.save() obj.save()

View File

@ -180,7 +180,7 @@ class ModelFormBaseTest(TestCase):
def test_no_model_class(self): def test_no_model_class(self):
class NoModelModelForm(forms.ModelForm): class NoModelModelForm(forms.ModelForm):
pass pass
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, 'ModelForm has no model class specified.'):
NoModelModelForm() NoModelModelForm()
def test_empty_fields_to_fields_for_model(self): def test_empty_fields_to_fields_for_model(self):
@ -326,7 +326,7 @@ class ModelFormBaseTest(TestCase):
fields = ('name', 'age') fields = ('name', 'age')
def test_extra_field_modelform_factory(self): def test_extra_field_modelform_factory(self):
with self.assertRaises(FieldError): with self.assertRaisesMessage(FieldError, 'Unknown field(s) (no-field) specified for Person'):
modelform_factory(Person, fields=['no-field', 'name']) modelform_factory(Person, fields=['no-field', 'name'])
def test_replace_field(self): def test_replace_field(self):
@ -426,7 +426,8 @@ class ModelFormBaseTest(TestCase):
form = PriceFormWithoutQuantity({'price': '6.00'}) form = PriceFormWithoutQuantity({'price': '6.00'})
self.assertTrue(form.is_valid()) self.assertTrue(form.is_valid())
price = form.save(commit=False) price = form.save(commit=False)
with self.assertRaises(ValidationError): msg = "{'quantity': ['This field cannot be null.']}"
with self.assertRaisesMessage(ValidationError, msg):
price.full_clean() price.full_clean()
# The form should not validate fields that it doesn't contain even if they are # The form should not validate fields that it doesn't contain even if they are
@ -498,11 +499,12 @@ class ModelFormBaseTest(TestCase):
pass # no model pass # no model
# Can't create new form # Can't create new form
with self.assertRaises(ValueError): msg = 'ModelForm has no model class specified.'
with self.assertRaisesMessage(ValueError, msg):
InvalidModelForm() InvalidModelForm()
# Even if you provide a model instance # Even if you provide a model instance
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
InvalidModelForm(instance=Category) InvalidModelForm(instance=Category)
def test_subcategory_form(self): def test_subcategory_form(self):
@ -1301,10 +1303,11 @@ class ModelFormBasicTests(TestCase):
["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."] ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]
) )
self.assertEqual(f.cleaned_data, {'url': 'foo'}) self.assertEqual(f.cleaned_data, {'url': 'foo'})
with self.assertRaises(ValueError): msg = "The Category could not be created because the data didn't validate."
with self.assertRaisesMessage(ValueError, msg):
f.save() f.save()
f = BaseCategoryForm({'name': '', 'slug': '', 'url': 'foo'}) f = BaseCategoryForm({'name': '', 'slug': '', 'url': 'foo'})
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
f.save() f.save()
def test_multi_fields(self): def test_multi_fields(self):
@ -1597,7 +1600,8 @@ class ModelChoiceFieldTests(TestCase):
# instantiated. This proves clean() checks the database during clean() rather # instantiated. This proves clean() checks the database during clean() rather
# than caching it at time of instantiation. # than caching it at time of instantiation.
Category.objects.get(url='4th').delete() Category.objects.get(url='4th').delete()
with self.assertRaises(ValidationError): msg = "['Select a valid choice. That choice is not one of the available choices.']"
with self.assertRaisesMessage(ValidationError, msg):
f.clean(c4.id) f.clean(c4.id)
def test_modelchoicefield_choices(self): def test_modelchoicefield_choices(self):
@ -3045,7 +3049,11 @@ class LocalizedModelFormTest(TestCase):
self.assertTrue(f.fields['right'].localize) self.assertTrue(f.fields['right'].localize)
def test_model_form_refuses_arbitrary_string(self): def test_model_form_refuses_arbitrary_string(self):
with self.assertRaises(TypeError): msg = (
"BrokenLocalizedTripleForm.Meta.localized_fields "
"cannot be a string. Did you mean to type: ('foo',)?"
)
with self.assertRaisesMessage(TypeError, msg):
class BrokenLocalizedTripleForm(forms.ModelForm): class BrokenLocalizedTripleForm(forms.ModelForm):
class Meta: class Meta:
model = Triple model = Triple

View File

@ -150,10 +150,11 @@ class AbstractInheritanceTests(TestCase):
def full_name(self): def full_name(self):
return self.first_name + self.last_name return self.first_name + self.last_name
with self.assertRaises(FieldDoesNotExist): msg = "Descendant has no field named %r"
with self.assertRaisesMessage(FieldDoesNotExist, msg % 'middle_name'):
Descendant._meta.get_field('middle_name') Descendant._meta.get_field('middle_name')
with self.assertRaises(FieldDoesNotExist): with self.assertRaisesMessage(FieldDoesNotExist, msg % 'full_name'):
Descendant._meta.get_field('full_name') Descendant._meta.get_field('full_name')
def test_overriding_field_removed_by_concrete_model(self): def test_overriding_field_removed_by_concrete_model(self):

View File

@ -43,7 +43,7 @@ class ModelInheritanceTests(TestCase):
# However, the CommonInfo class cannot be used as a normal model (it # However, the CommonInfo class cannot be used as a normal model (it
# doesn't exist as a model). # doesn't exist as a model).
with self.assertRaises(AttributeError): with self.assertRaisesMessage(AttributeError, "'CommonInfo' has no attribute 'objects'"):
CommonInfo.objects.all() CommonInfo.objects.all()
def test_reverse_relation_for_different_hierarchy_tree(self): def test_reverse_relation_for_different_hierarchy_tree(self):
@ -51,7 +51,12 @@ class ModelInheritanceTests(TestCase):
# Restaurant object cannot access that reverse relation, since it's not # Restaurant object cannot access that reverse relation, since it's not
# part of the Place-Supplier Hierarchy. # part of the Place-Supplier Hierarchy.
self.assertQuerysetEqual(Place.objects.filter(supplier__name="foo"), []) self.assertQuerysetEqual(Place.objects.filter(supplier__name="foo"), [])
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'supplier' into field. Choices are: "
"address, chef, chef_id, id, italianrestaurant, lot, name, "
"place_ptr, place_ptr_id, provider, rating, serves_hot_dogs, serves_pizza"
)
with self.assertRaisesMessage(FieldError, msg):
Restaurant.objects.filter(supplier__name="foo") Restaurant.objects.filter(supplier__name="foo")
def test_model_with_distinct_accessors(self): def test_model_with_distinct_accessors(self):
@ -65,7 +70,8 @@ class ModelInheritanceTests(TestCase):
# The Post model doesn't have an attribute called # The Post model doesn't have an attribute called
# 'attached_%(class)s_set'. # 'attached_%(class)s_set'.
with self.assertRaises(AttributeError): msg = "'Post' object has no attribute 'attached_%(class)s_set'"
with self.assertRaisesMessage(AttributeError, msg):
getattr(post, "attached_%(class)s_set") getattr(post, "attached_%(class)s_set")
def test_model_with_distinct_related_query_name(self): def test_model_with_distinct_related_query_name(self):

View File

@ -321,27 +321,39 @@ class QueryTestCase(TestCase):
mark = Person.objects.using('other').create(name="Mark Pilgrim") mark = Person.objects.using('other').create(name="Mark Pilgrim")
# Set a foreign key set with an object from a different database # Set a foreign key set with an object from a different database
with self.assertRaises(ValueError): msg = (
'Cannot assign "<Person: Marty Alchin>": the current database '
'router prevents this relation.'
)
with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
marty.edited.set([pro, dive]) marty.edited.set([pro, dive])
# Add to an m2m with an object from a different database # Add to an m2m with an object from a different database
with self.assertRaises(ValueError): msg = (
'Cannot add "<Book: Dive into Python>": instance is on '
'database "default", value is on database "other"'
)
with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
marty.book_set.add(dive) marty.book_set.add(dive)
# Set a m2m with an object from a different database # Set a m2m with an object from a different database
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
marty.book_set.set([pro, dive]) marty.book_set.set([pro, dive])
# Add to a reverse m2m with an object from a different database # Add to a reverse m2m with an object from a different database
with self.assertRaises(ValueError): msg = (
'Cannot add "<Person: Marty Alchin>": instance is on '
'database "other", value is on database "default"'
)
with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='other'): with transaction.atomic(using='other'):
dive.authors.add(marty) dive.authors.add(marty)
# Set a reverse m2m with an object from a different database # Set a reverse m2m with an object from a different database
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='other'): with transaction.atomic(using='other'):
dive.authors.set([mark, marty]) dive.authors.set([mark, marty])
@ -537,16 +549,20 @@ class QueryTestCase(TestCase):
dive = Book.objects.using('other').create(title="Dive into Python", published=datetime.date(2009, 5, 4)) dive = Book.objects.using('other').create(title="Dive into Python", published=datetime.date(2009, 5, 4))
# Set a foreign key with an object from a different database # Set a foreign key with an object from a different database
with self.assertRaises(ValueError): msg = (
'Cannot assign "<Person: Marty Alchin>": the current database '
'router prevents this relation.'
)
with self.assertRaisesMessage(ValueError, msg):
dive.editor = marty dive.editor = marty
# Set a foreign key set with an object from a different database # Set a foreign key set with an object from a different database
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
marty.edited.set([pro, dive]) marty.edited.set([pro, dive])
# Add to a foreign key set with an object from a different database # Add to a foreign key set with an object from a different database
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='default'): with transaction.atomic(using='default'):
marty.edited.add(dive) marty.edited.add(dive)
@ -655,7 +671,11 @@ class QueryTestCase(TestCase):
# Set a one-to-one relation with an object from a different database # Set a one-to-one relation with an object from a different database
alice_profile = UserProfile.objects.using('default').create(user=alice, flavor='chocolate') alice_profile = UserProfile.objects.using('default').create(user=alice, flavor='chocolate')
with self.assertRaises(ValueError): msg = (
'Cannot assign "<UserProfile: UserProfile object (1)>": the '
'current database router prevents this relation.'
)
with self.assertRaisesMessage(ValueError, msg):
bob.userprofile = alice_profile bob.userprofile = alice_profile
# BUT! if you assign a FK object when the base object hasn't # BUT! if you assign a FK object when the base object hasn't
@ -810,11 +830,19 @@ class QueryTestCase(TestCase):
Review.objects.using('other').create(source="Python Weekly", content_object=dive) Review.objects.using('other').create(source="Python Weekly", content_object=dive)
# Set a foreign key with an object from a different database # Set a foreign key with an object from a different database
with self.assertRaises(ValueError): msg = (
'Cannot assign "<ContentType: book>": the current database router '
'prevents this relation.'
)
with self.assertRaisesMessage(ValueError, msg):
review1.content_object = dive review1.content_object = dive
# Add to a foreign key set with an object from a different database # Add to a foreign key set with an object from a different database
with self.assertRaises(ValueError): msg = (
"<Review: Python Monthly> instance isn't saved. "
"Use bulk=False or save the object first."
)
with self.assertRaisesMessage(ValueError, msg):
with transaction.atomic(using='other'): with transaction.atomic(using='other'):
dive.reviews.add(review1) dive.reviews.add(review1)
@ -913,11 +941,15 @@ class QueryTestCase(TestCase):
# When you call __str__ on the query object, it doesn't know about using # When you call __str__ on the query object, it doesn't know about using
# so it falls back to the default. If the subquery explicitly uses a # so it falls back to the default. If the subquery explicitly uses a
# different database, an error should be raised. # different database, an error should be raised.
with self.assertRaises(ValueError): msg = (
"Subqueries aren't allowed across different databases. Force the "
"inner query to be evaluated using `list(inner_query)`."
)
with self.assertRaisesMessage(ValueError, msg):
str(qs.query) str(qs.query)
# Evaluating the query shouldn't work, either # Evaluating the query shouldn't work, either
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
for obj in qs: for obj in qs:
pass pass

View File

@ -32,11 +32,12 @@ class NullQueriesTests(TestCase):
self.assertSequenceEqual(Choice.objects.exclude(choice=None).order_by('id'), [c1, c2]) self.assertSequenceEqual(Choice.objects.exclude(choice=None).order_by('id'), [c1, c2])
# Valid query, but fails because foo isn't a keyword # Valid query, but fails because foo isn't a keyword
with self.assertRaises(FieldError): msg = "Cannot resolve keyword 'foo' into field. Choices are: choice, id, poll, poll_id"
with self.assertRaisesMessage(FieldError, msg):
Choice.objects.filter(foo__exact=None) Choice.objects.filter(foo__exact=None)
# Can't use None on anything other than __exact and __iexact # Can't use None on anything other than __exact and __iexact
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, 'Cannot use None as a query value'):
Choice.objects.filter(id__gt=None) Choice.objects.filter(id__gt=None)
# Related managers use __exact=None implicitly if the object hasn't been saved. # Related managers use __exact=None implicitly if the object hasn't been saved.

View File

@ -226,7 +226,11 @@ class OneToOneTests(TestCase):
setattr(p, 'restaurant', None) setattr(p, 'restaurant', None)
# You also can't assign an object of the wrong type here # You also can't assign an object of the wrong type here
with self.assertRaises(ValueError): msg = (
'Cannot assign "<Place: Demon Dogs the place>": '
'"Place.restaurant" must be a "Restaurant" instance.'
)
with self.assertRaisesMessage(ValueError, msg):
setattr(p, 'restaurant', p) setattr(p, 'restaurant', p)
# Creation using keyword argument should cache the related object. # Creation using keyword argument should cache the related object.

View File

@ -199,14 +199,22 @@ class PrefetchRelatedTests(TestCase):
def test_attribute_error(self): def test_attribute_error(self):
qs = Reader.objects.all().prefetch_related('books_read__xyz') qs = Reader.objects.all().prefetch_related('books_read__xyz')
with self.assertRaises(AttributeError) as cm: msg = (
"Cannot find 'xyz' on Book object, 'books_read__xyz' "
"is an invalid parameter to prefetch_related()"
)
with self.assertRaisesMessage(AttributeError, msg) as cm:
list(qs) list(qs)
self.assertIn('prefetch_related', str(cm.exception)) self.assertIn('prefetch_related', str(cm.exception))
def test_invalid_final_lookup(self): def test_invalid_final_lookup(self):
qs = Book.objects.prefetch_related('authors__name') qs = Book.objects.prefetch_related('authors__name')
with self.assertRaises(ValueError) as cm: msg = (
"'authors__name' does not resolve to an item that supports "
"prefetching - this is an invalid parameter to prefetch_related()."
)
with self.assertRaisesMessage(ValueError, msg) as cm:
list(qs) list(qs)
self.assertIn('prefetch_related', str(cm.exception)) self.assertIn('prefetch_related', str(cm.exception))
@ -337,14 +345,22 @@ class CustomPrefetchTests(TestCase):
def test_ambiguous(self): def test_ambiguous(self):
# Ambiguous: Lookup was already seen with a different queryset. # Ambiguous: Lookup was already seen with a different queryset.
with self.assertRaises(ValueError): msg = (
"'houses' lookup was already seen with a different queryset. You "
"may need to adjust the ordering of your lookups."
)
with self.assertRaisesMessage(ValueError, msg):
self.traverse_qs( self.traverse_qs(
Person.objects.prefetch_related('houses__rooms', Prefetch('houses', queryset=House.objects.all())), Person.objects.prefetch_related('houses__rooms', Prefetch('houses', queryset=House.objects.all())),
[['houses', 'rooms']] [['houses', 'rooms']]
) )
# Ambiguous: Lookup houses_lst doesn't yet exist when performing houses_lst__rooms. # Ambiguous: Lookup houses_lst doesn't yet exist when performing houses_lst__rooms.
with self.assertRaises(AttributeError): msg = (
"Cannot find 'houses_lst' on Person object, 'houses_lst__rooms' is "
"an invalid parameter to prefetch_related()"
)
with self.assertRaisesMessage(AttributeError, msg):
self.traverse_qs( self.traverse_qs(
Person.objects.prefetch_related( Person.objects.prefetch_related(
'houses_lst__rooms', 'houses_lst__rooms',

View File

@ -2957,7 +2957,8 @@ class WhereNodeTest(TestCase):
class QuerySetExceptionTests(TestCase): class QuerySetExceptionTests(TestCase):
def test_iter_exceptions(self): def test_iter_exceptions(self):
qs = ExtraInfo.objects.only('author') qs = ExtraInfo.objects.only('author')
with self.assertRaises(AttributeError): msg = "'ManyToOneRel' object has no attribute 'attname'"
with self.assertRaisesMessage(AttributeError, msg):
list(qs) list(qs)
def test_invalid_qs_list(self): def test_invalid_qs_list(self):
@ -3735,9 +3736,10 @@ class TestTicket24279(TestCase):
class TestInvalidValuesRelation(TestCase): class TestInvalidValuesRelation(TestCase):
def test_invalid_values(self): def test_invalid_values(self):
with self.assertRaises(ValueError): msg = "invalid literal for int() with base 10: 'abc'"
with self.assertRaisesMessage(ValueError, msg):
Annotation.objects.filter(tag='abc') Annotation.objects.filter(tag='abc')
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, msg):
Annotation.objects.filter(tag__in=[123, 'abc']) Annotation.objects.filter(tag__in=[123, 'abc'])

View File

@ -57,7 +57,11 @@ class RedirectTests(TestCase):
@modify_settings(INSTALLED_APPS={'remove': 'django.contrib.sites'}) @modify_settings(INSTALLED_APPS={'remove': 'django.contrib.sites'})
def test_sites_not_installed(self): def test_sites_not_installed(self):
with self.assertRaises(ImproperlyConfigured): msg = (
'You cannot use RedirectFallbackMiddleware when '
'django.contrib.sites is not installed.'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
RedirectFallbackMiddleware() RedirectFallbackMiddleware()

View File

@ -46,5 +46,9 @@ class ReverseLookupTests(TestCase):
""" """
If a related_name is given you can't use the field name instead If a related_name is given you can't use the field name instead
""" """
with self.assertRaises(FieldError): msg = (
"Cannot resolve keyword 'choice' into field. Choices are: "
"creator, creator_id, id, poll_choice, question, related_choice"
)
with self.assertRaisesMessage(FieldError, msg):
Poll.objects.get(choice__name__exact="This is the answer") Poll.objects.get(choice__name__exact="This is the answer")

View File

@ -246,7 +246,8 @@ class SelectForUpdateTests(TransactionTestCase):
A TransactionManagementError is raised A TransactionManagementError is raised
when a select_for_update query is executed outside of a transaction. when a select_for_update query is executed outside of a transaction.
""" """
with self.assertRaises(transaction.TransactionManagementError): msg = 'select_for_update cannot be used outside of a transaction.'
with self.assertRaisesMessage(transaction.TransactionManagementError, msg):
list(Person.objects.all().select_for_update()) list(Person.objects.all().select_for_update())
@skipUnlessDBFeature('has_select_for_update') @skipUnlessDBFeature('has_select_for_update')
@ -257,7 +258,8 @@ class SelectForUpdateTests(TransactionTestCase):
only when the query is executed. only when the query is executed.
""" """
people = Person.objects.all().select_for_update() people = Person.objects.all().select_for_update()
with self.assertRaises(transaction.TransactionManagementError): msg = 'select_for_update cannot be used outside of a transaction.'
with self.assertRaisesMessage(transaction.TransactionManagementError, msg):
list(people) list(people)
@skipUnlessDBFeature('supports_select_for_update_with_limit') @skipUnlessDBFeature('supports_select_for_update_with_limit')

View File

@ -137,10 +137,6 @@ class SelectRelatedTests(TestCase):
.order_by('id')[0:1].get().genus.family.order.name) .order_by('id')[0:1].get().genus.family.order.name)
self.assertEqual(s, 'Diptera') self.assertEqual(s, 'Diptera')
def test_depth_fields_fails(self):
with self.assertRaises(TypeError):
Species.objects.select_related('genus__family__order', depth=4)
def test_none_clears_list(self): def test_none_clears_list(self):
queryset = Species.objects.select_related('genus').select_related(None) queryset = Species.objects.select_related('genus').select_related(None)
self.assertIs(queryset.query.select_related, False) self.assertIs(queryset.query.select_related, False)

View File

@ -238,7 +238,7 @@ class SettingsTests(SimpleTestCase):
getattr(settings, 'TEST') getattr(settings, 'TEST')
def test_settings_delete_wrapped(self): def test_settings_delete_wrapped(self):
with self.assertRaises(TypeError): with self.assertRaisesMessage(TypeError, "can't delete _wrapped."):
delattr(settings, '_wrapped') delattr(settings, '_wrapped')
def test_override_settings_delete(self): def test_override_settings_delete(self):

View File

@ -16,6 +16,10 @@ from .models import TestModel
class HTTPSitemapTests(SitemapTestsBase): class HTTPSitemapTests(SitemapTestsBase):
use_sitemap_err_msg = (
'To use sitemaps, either enable the sites framework or pass a '
'Site/RequestSite object in your view.'
)
def test_simple_sitemap_index(self): def test_simple_sitemap_index(self):
"A simple sitemap index can be rendered" "A simple sitemap index can be rendered"
@ -207,7 +211,7 @@ class HTTPSitemapTests(SitemapTestsBase):
Sitemap.get_urls and no Site objects exist Sitemap.get_urls and no Site objects exist
""" """
Site.objects.all().delete() Site.objects.all().delete()
with self.assertRaises(ImproperlyConfigured): with self.assertRaisesMessage(ImproperlyConfigured, self.use_sitemap_err_msg):
Sitemap().get_urls() Sitemap().get_urls()
@modify_settings(INSTALLED_APPS={'remove': 'django.contrib.sites'}) @modify_settings(INSTALLED_APPS={'remove': 'django.contrib.sites'})
@ -217,7 +221,7 @@ class HTTPSitemapTests(SitemapTestsBase):
Sitemap.get_urls if Site objects exists, but the sites framework is not Sitemap.get_urls if Site objects exists, but the sites framework is not
actually installed. actually installed.
""" """
with self.assertRaises(ImproperlyConfigured): with self.assertRaisesMessage(ImproperlyConfigured, self.use_sitemap_err_msg):
Sitemap().get_urls() Sitemap().get_urls()
def test_sitemap_item(self): def test_sitemap_item(self):

View File

@ -105,5 +105,10 @@ class TestMiscFinder(SimpleTestCase):
@override_settings(MEDIA_ROOT='') @override_settings(MEDIA_ROOT='')
def test_location_empty(self): def test_location_empty(self):
with self.assertRaises(ImproperlyConfigured): msg = (
"The storage backend of the staticfiles finder "
"<class 'django.contrib.staticfiles.finders.DefaultStorageFinder'> "
"doesn't have a valid location."
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
finders.DefaultStorageFinder() finders.DefaultStorageFinder()

View File

@ -452,7 +452,11 @@ class SyndicationFeedTest(FeedTestCase):
An ImproperlyConfigured is raised if no link could be found for the An ImproperlyConfigured is raised if no link could be found for the
item(s). item(s).
""" """
with self.assertRaises(ImproperlyConfigured): msg = (
'Give your Article class a get_absolute_url() method, or define '
'an item_link() method in your Feed class.'
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/syndication/articles/') self.client.get('/syndication/articles/')
def test_template_feed(self): def test_template_feed(self):

View File

@ -332,11 +332,13 @@ class TranslationBlockTransTagTests(SimpleTestCase):
self.assertEqual(rendered, '2 andere Super-Ergebnisse') self.assertEqual(rendered, '2 andere Super-Ergebnisse')
# Misuses # Misuses
with self.assertRaises(TemplateSyntaxError): msg = "Unknown argument for 'blocktrans' tag: %r."
with self.assertRaisesMessage(TemplateSyntaxError, msg % 'month="May"'):
Template('{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}') Template('{% load i18n %}{% blocktrans context with month="May" %}{{ month }}{% endblocktrans %}')
with self.assertRaises(TemplateSyntaxError): msg = '"context" in %r tag expected exactly one argument.' % 'blocktrans'
with self.assertRaisesMessage(TemplateSyntaxError, msg):
Template('{% load i18n %}{% blocktrans context %}{% endblocktrans %}') Template('{% load i18n %}{% blocktrans context %}{% endblocktrans %}')
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, msg):
Template( Template(
'{% load i18n %}{% blocktrans count number=2 context %}' '{% load i18n %}{% blocktrans count number=2 context %}'
'{{ number }} super result{% plural %}{{ number }}' '{{ number }} super result{% plural %}{{ number }}'

View File

@ -43,7 +43,8 @@ class FilterSyntaxTests(SimpleTestCase):
""" """
Raise TemplateSyntaxError for a nonexistent filter Raise TemplateSyntaxError for a nonexistent filter
""" """
with self.assertRaises(TemplateSyntaxError): msg = "Invalid filter: 'does_not_exist'"
with self.assertRaisesMessage(TemplateSyntaxError, msg):
self.engine.get_template('filter-syntax05') self.engine.get_template('filter-syntax05')
@setup({'filter-syntax06': '{{ var|fil(ter) }}'}) @setup({'filter-syntax06': '{{ var|fil(ter) }}'})
@ -52,7 +53,7 @@ class FilterSyntaxTests(SimpleTestCase):
Raise TemplateSyntaxError when trying to access a filter containing Raise TemplateSyntaxError when trying to access a filter containing
an illegal character an illegal character
""" """
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, "Invalid filter: 'fil'"):
self.engine.get_template('filter-syntax06') self.engine.get_template('filter-syntax06')
@setup({'filter-syntax07': "{% nothing_to_see_here %}"}) @setup({'filter-syntax07': "{% nothing_to_see_here %}"})
@ -60,7 +61,11 @@ class FilterSyntaxTests(SimpleTestCase):
""" """
Raise TemplateSyntaxError for invalid block tags Raise TemplateSyntaxError for invalid block tags
""" """
with self.assertRaises(TemplateSyntaxError): msg = (
"Invalid block tag on line 1: 'nothing_to_see_here'. Did you "
"forget to register or load this tag?"
)
with self.assertRaisesMessage(TemplateSyntaxError, msg):
self.engine.get_template('filter-syntax07') self.engine.get_template('filter-syntax07')
@setup({'filter-syntax08': "{% %}"}) @setup({'filter-syntax08': "{% %}"})

View File

@ -6,6 +6,7 @@ from ..utils import setup
class WithTagTests(SimpleTestCase): class WithTagTests(SimpleTestCase):
at_least_with_one_msg = "'with' expected at least one variable assignment"
@setup({'with01': '{% with key=dict.key %}{{ key }}{% endwith %}'}) @setup({'with01': '{% with key=dict.key %}{{ key }}{% endwith %}'})
def test_with01(self): def test_with01(self):
@ -44,12 +45,12 @@ class WithTagTests(SimpleTestCase):
@setup({'with-error01': '{% with dict.key xx key %}{{ key }}{% endwith %}'}) @setup({'with-error01': '{% with dict.key xx key %}{{ key }}{% endwith %}'})
def test_with_error01(self): def test_with_error01(self):
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, self.at_least_with_one_msg):
self.engine.render_to_string('with-error01', {'dict': {'key': 50}}) self.engine.render_to_string('with-error01', {'dict': {'key': 50}})
@setup({'with-error02': '{% with dict.key as %}{{ key }}{% endwith %}'}) @setup({'with-error02': '{% with dict.key as %}{{ key }}{% endwith %}'})
def test_with_error02(self): def test_with_error02(self):
with self.assertRaises(TemplateSyntaxError): with self.assertRaisesMessage(TemplateSyntaxError, self.at_least_with_one_msg):
self.engine.render_to_string('with-error02', {'dict': {'key': 50}}) self.engine.render_to_string('with-error02', {'dict': {'key': 50}})

View File

@ -40,7 +40,8 @@ class ParserTests(SimpleTestCase):
# Filtered variables should reject access of attributes beginning with # Filtered variables should reject access of attributes beginning with
# underscores. # underscores.
with self.assertRaises(TemplateSyntaxError): msg = "Variables and attributes may not begin with underscores: 'article._hidden'"
with self.assertRaisesMessage(TemplateSyntaxError, msg):
FilterExpression("article._hidden|upper", p) FilterExpression("article._hidden|upper", p)
def test_variable_parsing(self): def test_variable_parsing(self):
@ -64,7 +65,8 @@ class ParserTests(SimpleTestCase):
# Variables should reject access of attributes beginning with # Variables should reject access of attributes beginning with
# underscores. # underscores.
with self.assertRaises(TemplateSyntaxError): msg = "Variables and attributes may not begin with underscores: 'article._hidden'"
with self.assertRaisesMessage(TemplateSyntaxError, msg):
Variable("article._hidden") Variable("article._hidden")
# Variables should raise on non string type # Variables should raise on non string type

View File

@ -212,7 +212,8 @@ class AssertQuerysetEqualTests(TestCase):
def test_undefined_order(self): def test_undefined_order(self):
# Using an unordered queryset with more than one ordered value # Using an unordered queryset with more than one ordered value
# is an error. # is an error.
with self.assertRaises(ValueError): msg = 'Trying to compare non-ordered queryset against more than one ordered values'
with self.assertRaisesMessage(ValueError, msg):
self.assertQuerysetEqual( self.assertQuerysetEqual(
Person.objects.all(), Person.objects.all(),
[repr(self.p1), repr(self.p2)] [repr(self.p1), repr(self.p2)]
@ -415,23 +416,29 @@ class AssertTemplateUsedContextManagerTests(SimpleTestCase):
self.assertTemplateUsed(response, 'template_used/base.html') self.assertTemplateUsed(response, 'template_used/base.html')
def test_failure(self): def test_failure(self):
with self.assertRaises(TypeError): msg = 'response and/or template_name argument must be provided'
with self.assertRaisesMessage(TypeError, msg):
with self.assertTemplateUsed(): with self.assertTemplateUsed():
pass pass
with self.assertRaises(AssertionError): msg = 'No templates used to render the response'
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed(''): with self.assertTemplateUsed(''):
pass pass
with self.assertRaises(AssertionError): with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed(''): with self.assertTemplateUsed(''):
render_to_string('template_used/base.html') render_to_string('template_used/base.html')
with self.assertRaises(AssertionError): with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed(template_name=''): with self.assertTemplateUsed(template_name=''):
pass pass
with self.assertRaises(AssertionError): msg = (
'template_used/base.html was not rendered. Following '
'templates were rendered: template_used/alternative.html'
)
with self.assertRaisesMessage(AssertionError, msg):
with self.assertTemplateUsed('template_used/base.html'): with self.assertTemplateUsed('template_used/base.html'):
render_to_string('template_used/alternative.html') render_to_string('template_used/alternative.html')

View File

@ -123,7 +123,8 @@ class LegacyDatabaseTests(TestCase):
@skipIfDBFeature('supports_timezones') @skipIfDBFeature('supports_timezones')
def test_aware_datetime_unsupported(self): def test_aware_datetime_unsupported(self):
dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT) dt = datetime.datetime(2011, 9, 1, 13, 20, 30, tzinfo=EAT)
with self.assertRaises(ValueError): msg = 'backend does not support timezone-aware datetimes when USE_TZ is False.'
with self.assertRaisesMessage(ValueError, msg):
Event.objects.create(dt=dt) Event.objects.create(dt=dt)
def test_auto_now_and_auto_now_add(self): def test_auto_now_and_auto_now_add(self):
@ -647,7 +648,11 @@ class UnsupportedTimeZoneDatabaseTests(TestCase):
connections.databases['tz']['TIME_ZONE'] = 'Asia/Bangkok' connections.databases['tz']['TIME_ZONE'] = 'Asia/Bangkok'
tz_conn = connections['tz'] tz_conn = connections['tz']
try: try:
with self.assertRaises(ImproperlyConfigured): msg = (
"Connection 'tz' cannot set TIME_ZONE because its engine "
"handles time zones conversions natively."
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
tz_conn.cursor() tz_conn.cursor()
finally: finally:
connections['tz'].close() # in case the test fails connections['tz'].close() # in case the test fails
@ -1033,7 +1038,8 @@ class TemplateTests(SimpleTestCase):
self.assertEqual(tpl.render(Context()), "Europe/Paris") self.assertEqual(tpl.render(Context()), "Europe/Paris")
def test_get_current_timezone_templatetag_invalid_argument(self): def test_get_current_timezone_templatetag_invalid_argument(self):
with self.assertRaises(TemplateSyntaxError): msg = "'get_current_timezone' requires 'as variable' (got ['get_current_timezone'])"
with self.assertRaisesMessage(TemplateSyntaxError, msg):
Template("{% load tz %}{% get_current_timezone %}").render() Template("{% load tz %}{% get_current_timezone %}").render()
@skipIf(sys.platform.startswith('win'), "Windows uses non-standard time zone names") @skipIf(sys.platform.startswith('win'), "Windows uses non-standard time zone names")

View File

@ -214,7 +214,8 @@ class TestConnectionOnCommit(TransactionTestCase):
try: try:
connection.set_autocommit(False) connection.set_autocommit(False)
with self.assertRaises(transaction.TransactionManagementError): msg = 'on_commit() cannot be used in manual transaction management'
with self.assertRaisesMessage(transaction.TransactionManagementError, msg):
transaction.on_commit(should_never_be_called) transaction.on_commit(should_never_be_called)
finally: finally:
connection.set_autocommit(True) connection.set_autocommit(True)

View File

@ -299,20 +299,21 @@ class AtomicMergeTests(TransactionTestCase):
class AtomicErrorsTests(TransactionTestCase): class AtomicErrorsTests(TransactionTestCase):
available_apps = ['transactions'] available_apps = ['transactions']
forbidden_atomic_msg = "This is forbidden when an 'atomic' block is active."
def test_atomic_prevents_setting_autocommit(self): def test_atomic_prevents_setting_autocommit(self):
autocommit = transaction.get_autocommit() autocommit = transaction.get_autocommit()
with transaction.atomic(): with transaction.atomic():
with self.assertRaises(transaction.TransactionManagementError): with self.assertRaisesMessage(transaction.TransactionManagementError, self.forbidden_atomic_msg):
transaction.set_autocommit(not autocommit) transaction.set_autocommit(not autocommit)
# Make sure autocommit wasn't changed. # Make sure autocommit wasn't changed.
self.assertEqual(connection.autocommit, autocommit) self.assertEqual(connection.autocommit, autocommit)
def test_atomic_prevents_calling_transaction_methods(self): def test_atomic_prevents_calling_transaction_methods(self):
with transaction.atomic(): with transaction.atomic():
with self.assertRaises(transaction.TransactionManagementError): with self.assertRaisesMessage(transaction.TransactionManagementError, self.forbidden_atomic_msg):
transaction.commit() transaction.commit()
with self.assertRaises(transaction.TransactionManagementError): with self.assertRaisesMessage(transaction.TransactionManagementError, self.forbidden_atomic_msg):
transaction.rollback() transaction.rollback()
def test_atomic_prevents_queries_in_broken_transaction(self): def test_atomic_prevents_queries_in_broken_transaction(self):
@ -322,7 +323,11 @@ class AtomicErrorsTests(TransactionTestCase):
with self.assertRaises(IntegrityError): with self.assertRaises(IntegrityError):
r2.save(force_insert=True) r2.save(force_insert=True)
# The transaction is marked as needing rollback. # The transaction is marked as needing rollback.
with self.assertRaises(transaction.TransactionManagementError): msg = (
"An error occurred in the current transaction. You can't "
"execute queries until the end of the 'atomic' block."
)
with self.assertRaisesMessage(transaction.TransactionManagementError, msg):
r2.save(force_update=True) r2.save(force_update=True)
self.assertEqual(Reporter.objects.get(pk=r1.pk).last_name, "Haddock") self.assertEqual(Reporter.objects.get(pk=r1.pk).last_name, "Haddock")

View File

@ -123,7 +123,8 @@ class AdvancedTests(TestCase):
We do not support update on already sliced query sets. We do not support update on already sliced query sets.
""" """
method = DataPoint.objects.all()[:2].update method = DataPoint.objects.all()[:2].update
with self.assertRaises(AssertionError): msg = 'Cannot update a query once a slice has been taken.'
with self.assertRaisesMessage(AssertionError, msg):
method(another_value='another thing') method(another_value='another thing')
def test_update_respects_to_field(self): def test_update_respects_to_field(self):

View File

@ -5,6 +5,8 @@ from .models import Account, Employee, Person, Profile, ProxyEmployee
class UpdateOnlyFieldsTests(TestCase): class UpdateOnlyFieldsTests(TestCase):
msg = 'The following fields do not exist in this model or are m2m fields: %s'
def test_update_fields_basic(self): def test_update_fields_basic(self):
s = Person.objects.create(name='Sara', gender='F') s = Person.objects.create(name='Sara', gender='F')
self.assertEqual(s.gender, 'F') self.assertEqual(s.gender, 'F')
@ -120,7 +122,7 @@ class UpdateOnlyFieldsTests(TestCase):
a2 = Account.objects.create(num=2) a2 = Account.objects.create(num=2)
e1.accounts.set([a1, a2]) e1.accounts.set([a1, a2])
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, self.msg % 'accounts'):
e1.save(update_fields=['accounts']) e1.save(update_fields=['accounts'])
def test_update_fields_inheritance(self): def test_update_fields_inheritance(self):
@ -201,10 +203,12 @@ class UpdateOnlyFieldsTests(TestCase):
def test_update_fields_incorrect_params(self): def test_update_fields_incorrect_params(self):
s = Person.objects.create(name='Sara', gender='F') s = Person.objects.create(name='Sara', gender='F')
with self.assertRaises(ValueError): with self.assertRaisesMessage(ValueError, self.msg % 'first_name'):
s.save(update_fields=['first_name']) s.save(update_fields=['first_name'])
with self.assertRaises(ValueError): # "name" is treated as an iterable so the output is something like
# "n, a, m, e" but the order isn't deterministic.
with self.assertRaisesMessage(ValueError, self.msg % ''):
s.save(update_fields="name") s.save(update_fields="name")
def test_empty_update_fields(self): def test_empty_update_fields(self):

View File

@ -1067,7 +1067,12 @@ class NoRootUrlConfTests(SimpleTestCase):
"""Tests for handler404 and handler500 if ROOT_URLCONF is None""" """Tests for handler404 and handler500 if ROOT_URLCONF is None"""
def test_no_handler_exception(self): def test_no_handler_exception(self):
with self.assertRaises(ImproperlyConfigured): msg = (
"The included URLconf 'None' does not appear to have any patterns "
"in it. If you see valid patterns in the file then the issue is "
"probably caused by a circular import."
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.client.get('/test/me/') self.client.get('/test/me/')

View File

@ -46,7 +46,7 @@ class CommandTests(SimpleTestCase):
def test_explode(self): def test_explode(self):
""" An unknown command raises CommandError """ """ An unknown command raises CommandError """
with self.assertRaises(CommandError): with self.assertRaisesMessage(CommandError, "Unknown command: 'explode'"):
management.call_command(('explode',)) management.call_command(('explode',))
def test_system_exit(self): def test_system_exit(self):
@ -215,5 +215,6 @@ class CommandRunTests(AdminScriptTestCase):
class UtilsTests(SimpleTestCase): class UtilsTests(SimpleTestCase):
def test_no_existent_external_program(self): def test_no_existent_external_program(self):
with self.assertRaises(CommandError): msg = 'Error executing a_42_command_that_doesnt_exist_42'
with self.assertRaisesMessage(CommandError, msg):
popen_wrapper(['a_42_command_that_doesnt_exist_42']) popen_wrapper(['a_42_command_that_doesnt_exist_42'])

View File

@ -334,7 +334,8 @@ class TestSimpleValidators(SimpleTestCase):
self.assertEqual(repr(v), "ValidationError({'first': ['First Problem']})") self.assertEqual(repr(v), "ValidationError({'first': ['First Problem']})")
def test_regex_validator_flags(self): def test_regex_validator_flags(self):
with self.assertRaises(TypeError): msg = 'If the flags are set, regex must be a regular expression string.'
with self.assertRaisesMessage(TypeError, msg):
RegexValidator(re.compile('a'), flags=re.IGNORECASE) RegexValidator(re.compile('a'), flags=re.IGNORECASE)
def test_max_length_validator_message(self): def test_max_length_validator_message(self):