diff --git a/django_admin_smoke_tests/tests.py b/django_admin_smoke_tests/tests.py index 5acead80..fc0f685b 100644 --- a/django_admin_smoke_tests/tests.py +++ b/django_admin_smoke_tests/tests.py @@ -4,6 +4,21 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.test import TestCase from django.test.client import RequestFactory +import sys + + +def for_all_model_admins(fn): + def test_deco(self): + for model, model_admin in self.modeladmins: + try: + fn(self, model, model_admin) + except Exception: + raise Exception( + "Above exception occured while running test '%s'" + "on modeladmin %s (%s)" % + (fn.__name__, model_admin, model.__name__)).\ + with_traceback(sys.exc_info()[2]) + return test_deco class AdminSiteSmokeTestMixin(object): @@ -95,93 +110,92 @@ def get_attr_set(self, model, model_admin): return attr_set - def test_specified_fields(self): - for model, model_admin in self.modeladmins: - attr_set = self.get_attr_set(model, model_admin) + @for_all_model_admins + def test_specified_fields(self, model, model_admin): + attr_set = self.get_attr_set(model, model_admin) + + # FIXME: not all attributes can be used everywhere (e.g. you can't + # use list_filter with a form field). This will have to be fixed + # later. + try: + model_field_names = frozenset(model._meta.get_fields()) + except AttributeError: # Django<1.10 + model_field_names = frozenset( + model._meta.get_all_field_names() + ) + form_field_names = frozenset(getattr(model_admin.form, + 'base_fields', [])) + + model_instance = model() + + for attr in attr_set: + # for now we'll just check attributes, not strings + if not isinstance(attr, six.string_types): + continue + + # don't split attributes that start with underscores (such as + # __str__) + if attr[0] != '_': + attr = attr.split('__')[0] + + has_model_field = attr in model_field_names + has_form_field = attr in form_field_names + has_model_class_attr = hasattr(model_instance.__class__, attr) + has_admin_attr = hasattr(model_admin, attr) - # FIXME: not all attributes can be used everywhere (e.g. you can't - # use list_filter with a form field). This will have to be fixed - # later. try: - model_field_names = frozenset(model._meta.get_fields()) - except AttributeError: # Django<1.10 - model_field_names = frozenset( - model._meta.get_all_field_names() - ) - form_field_names = frozenset(getattr(model_admin.form, - 'base_fields', [])) - - model_instance = model() - - for attr in attr_set: - # for now we'll just check attributes, not strings - if not isinstance(attr, six.string_types): - continue - - # don't split attributes that start with underscores (such as - # __str__) - if attr[0] != '_': - attr = attr.split('__')[0] - - has_model_field = attr in model_field_names - has_form_field = attr in form_field_names - has_model_class_attr = hasattr(model_instance.__class__, attr) - has_admin_attr = hasattr(model_admin, attr) - - try: - has_model_attr = hasattr(model_instance, attr) - except (ValueError, ObjectDoesNotExist): - has_model_attr = attr in model_instance.__dict__ - - has_field_or_attr = has_model_field or has_form_field or\ - has_model_attr or has_admin_attr or has_model_class_attr - - self.assertTrue(has_field_or_attr, '%s not found on %s (%s)' % - (attr, model, model_admin,)) - - def test_queryset(self): + has_model_attr = hasattr(model_instance, attr) + except (ValueError, ObjectDoesNotExist): + has_model_attr = attr in model_instance.__dict__ + + has_field_or_attr = has_model_field or has_form_field or\ + has_model_attr or has_admin_attr or has_model_class_attr + + self.assertTrue(has_field_or_attr, '%s not found on %s (%s)' % + (attr, model, model_admin,)) + + @for_all_model_admins + def test_queryset(self, model, model_admin): request = self.get_request() # TODO: use model_mommy to generate a few instances to query against - for model, model_admin in self.modeladmins: + # make sure no errors happen here + if hasattr(model_admin, 'queryset'): + list(model_admin.queryset(request)) + if hasattr(model_admin, 'get_queryset'): + list(model_admin.get_queryset(request)) + + @for_all_model_admins + def test_get_absolute_url(self, model, model_admin): + if hasattr(model, 'get_absolute_url'): + # Use fixture data if it exists + instance = model.objects.first() + # Otherwise create a minimal instance + if not instance: + instance = model(pk=1) # make sure no errors happen here - if hasattr(model_admin, 'queryset'): - list(model_admin.queryset(request)) - if hasattr(model_admin, 'get_queryset'): - list(model_admin.get_queryset(request)) + instance.get_absolute_url() - def test_get_absolute_url(self): - for model, model_admin in self.modeladmins: - if hasattr(model, 'get_absolute_url'): - # Use fixture data if it exists - instance = model.objects.first() - # Otherwise create a minimal instance - if not instance: - instance = model(pk=1) - - # make sure no errors happen here - instance.get_absolute_url() - - def test_changelist_view(self): + @for_all_model_admins + def test_changelist_view(self, model, model_admin): request = self.get_request() - for model, model_admin in self.modeladmins: - # make sure no errors happen here - response = model_admin.changelist_view(request) - self.assertEqual(response.status_code, 200) + # make sure no errors happen here + response = model_admin.changelist_view(request) + self.assertEqual(response.status_code, 200) - def test_add_view(self): + @for_all_model_admins + def test_add_view(self, model, model_admin): request = self.get_request() - for model, model_admin in self.modeladmins: - # make sure no errors happen here - try: - response = model_admin.add_view(request) - self.assertEqual(response.status_code, 200) - except PermissionDenied: - # this error is commonly raised by ModelAdmins that don't allow - # adding. - pass + # make sure no errors happen here + try: + response = model_admin.add_view(request) + self.assertEqual(response.status_code, 200) + except PermissionDenied: + # this error is commonly raised by ModelAdmins that don't allow + # adding. + pass class AdminSiteSmokeTest(AdminSiteSmokeTestMixin, TestCase):