[Django]-Testing admin.ModelAdmin in django

62👍

Check out Django’s ModelAdminTests for examples.

👤Udi

81👍

As suggested in Udi’s answer, we can study Django’s own ModelAdmin tests, to determine the basic ingredients for a ModelAdmin test. Here’s a summary:

Basic ingredients

In addition to the Django TestCase stuff, the basic ingredients are:

  1. An instance of AdminSite:

     from django.contrib.admin.sites import AdminSite
    
  2. Your model class and corresponding ModelAdmin (sub)class:

     from my_app.models import MyModel
     from my_app.admin import MyModelAdmin
    
  3. Optionally, depending on your needs, a (mock) request and/or form.

Recipe

The first two ingredients are required to create an instance of your (custom) ModelAdmin:

my_model_admin = MyModelAdmin(model=MyModel, admin_site=AdminSite())

Based on the ModelAdmin source, the default save_model implementation only requires an instance of your model, so it can be called, for example, as follows:

my_model_admin.save_model(obj=MyModel(), request=None, form=None, change=None)
# some test assertions here

It all depends on what your save_model does, and what you want to test.
Suppose your save_model checks user permissions, then you would need to provide a request (i.e. the third ingredient) with a valid user, in addition to the model instance:

from unittest.mock import Mock

...

my_user = User.objects.create(...)
my_model_admin.save_model(
    obj=MyModel(), request=Mock(user=my_user), form=None, change=None
)
# some test assertions here

Here we use unittest.mock.Mock to create a mock-request. Based on the Django test source, a minimal request consists of a Python object with a user attribute.
The user attribute may refer to a mock user, or an actual instance of your AUTH_USER_MODEL, depending on your needs. An alternative would be to use django.test.RequestFactory.

This basic approach applies to the other ModelAdmin methods as well.

👤djvg

6👍

You can specify custom modelform for modeladmin then simply test this modelform 😉

https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form

forms

class SomeModelForm(forms.ModelForm):
    class Meta:
        model = SomeModel

admin

class SomeModelAdmin(admin.ModelAdmin):
    form = SomeModelForm


admin.site.register(SomeModel, SomeModelAdmin)

tests

class TestSomeModel(TestCase):
    def test_form(self):
        form = SomeModelForm(**kwargs)
        self.assertTrue(form.is_valid())
        # ...

0👍

To test if the search does not lead to server errors (i.e. because search_fields are not correct) you can use the following code:

from django.contrib import admin
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse


class TestModelAdmins(TestCase):
    def test_search_fields(self):
        user_1 = User(
            username="user1",
            first_name="User",
            last_name="One",
            email="user1@example.org",
            password="superSecurePasswordFromStackoverflow",
            is_superuser=True,
            is_staff=True,
        )
        user_1.full_clean()
        user_1.save()
        self.client.force_login(user_1)
        for model_class, admin_class in admin.site._registry.items():
            with self.subTest(model_class._meta.model_name):
                path = reverse("admin:%s_%s_changelist" % (model_class._meta.app_label, model_class._meta.model_name))
                response = self.client.get(path + "?q=blub")
                self.assertEqual(response.status_code, 200)

Leave a comment