Automatic testing of add and changelist admin views

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/usr/bin/env python
# -*- coding: utf-8 -
#
# @contact: marcoberi@gmail.com
# @version: 1.0
# @license: MIT http://www.opensource.org/licenses/mit-license.php
#

from django.db.models.base import ModelBase
from django.core.urlresolvers import reverse, NoReverseMatch
from django.contrib import admin
from django.contrib.auth.models import User

def adminviews_test(self, user=None, password=None):
    if user is None:
        if password is None:
            password = "test"
        user = User.objects.create_superuser('test', 'test@test.com', password)
    self.client.login(username = user.username, password = password)
    pkg = self.__module__.rpartition('.')[0]
    if pkg.endswith(".tests"):
        pkg = pkg[:-6]
    models_mod = __import__(pkg + ".models")
    if not getattr(models_mod, "models", None):
        return
    for id_ in dir(models_mod.models):
        model = getattr(models_mod.models, id_)
        # Get ModelAdmin for this Model
        if isinstance(model, ModelBase) and model._meta.app_label == pkg and model in admin.site._registry:
            try:
                # Prevent error 405 if model_admin.has_add_permission always return False
                if admin.site._registry[model].has_add_permission(type("request", (), {"user": user})):
                    url = reverse("admin:%s_%s_add" % (model._meta.app_label, model._meta.module_name))
                    response = self.client.get(url, follow = True)
                    self.failUnlessEqual(response.status_code, 200,
                         "%s != %s -> %s, url: %s" % (response.status_code, 200, repr(model), url))
                    self.assertFalse("this_is_the_login_form" in response.content,
                         "login requested for %s" % str(model))
                url = reverse("admin:%s_%s_changelist" %
                        (model._meta.app_label, model._meta.module_name))
                response = self.client.get(url, follow = True)
                self.failUnlessEqual(response.status_code, 200,
                     "%s != %s -> %s, url: %s" % (response.status_code, 200, repr(model), url))
                self.assertFalse("this_is_the_login_form" in response.content,
                     "login requested for %s" % str(model))
            except NoReverseMatch:
                continue

More like this

  1. Modify requests in your unit tests (improvement on RequestFactory) by vaughnkoch 3 years, 6 months ago
  2. Decorator and context manager to override settings by jezdez 2 years, 11 months ago
  3. Deep package test runner by eternicode 3 years, 1 month ago
  4. change settings locally in an individual test by akaihola 3 years, 8 months ago
  5. Testrunner with testmodels by nfg 4 years, 2 months ago

Comments

moreno (on August 2, 2013):

It doesn't work at django 1.4.5 :(

At the top instructions it's missing a 's' at admintests:

from admintests import adminviews_test

#

bufke (on November 14, 2013):

I was able to get it working in 1.6.

You must call admin.autodiscover()

It does not support app names like "foo.bar" but you can hack on it to make it work.

#

brigantino (on March 4, 2014):

It's necessary to call admin.autodiscover() to populate admin.site._registry. There's also an easier way to retrieve models, using

for model in models.get_models(include_auto_created=True):

instead of:

models_mod = __import__(pkg + ".models")
if not getattr(models_mod, "models", None):
    return
for id_ in dir(models_mod.models):
    model = getattr(models_mod.models, id_)

you might also need to check that pkg value is ok for this check: model._meta.app_label == pkg

#

(Forgotten your password?)