﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
27266	assertFormError fails when trying to check a custom validation in an Admin form	Diego Andrés Sanabria Martín	nobody	"When using the assertFormError in a unittest to check a custome validation in an admin form the assertion fails because apparently the form in the admin view behaviours slightly different from a normal view.

Create a project 'what' with an app 'why' (I used 1.8.4 but it was tested with master branch):

django-admin startproject what
cd what
python manage.py startapp why

Use this files to check the bug:

what/settings.py
{{{
...
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'why',
)
...
}}}

why/models.py
{{{
from django.db import models

# Create your models here.
class WhyMe(models.Model):
    name = models.CharField(max_length=255)
}}}

why/admin.py
{{{
from django.contrib import admin
from django.core.exceptions import ValidationError
from django.forms import ModelForm

from why.models import WhyMe

class WhyMeAdminForm(ModelForm):
    def clean_name(self):
        name = self.cleaned_data['name']
        if name.startswith('xxx'):
            raise ValidationError('don\'t use xxx!', code='invalid')
        return name

@admin.register(WhyMe)
class WhyMeAdmin(admin.ModelAdmin):
    form = WhyMeAdminForm
}}}

why/tests.py
{{{
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.test import TestCase

class WhyMeAdminTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_superuser(username='chuck', email='chuck@internet.com', password='no')
        self.client.login(username='chuck', password='no')

    def test_custome_validation(self):
        url = reverse('admin:why_whyme_add')
        data = {
            'name': 'xxxDiegueus9'
        }
        response = self.client.post(url, data, follow=True)

        self.assertEqual(response.status_code, 200)
        self.assertFormError(response, 'adminform', 'name', ['don\'t use xxx!'])
}}}

Finally run the tests and the result would be something like:
{{{
Creating test database for alias 'default'...
E
======================================================================
ERROR: test_custome_validation (why.tests.WhyMeAdminTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ""/Users/diegueus9/.virtualenvs/django1.8/what/why/tests.py"", line 18, in test_custome_validation
    self.assertFormError(response, 'adminform', 'name', ['don\'t use xxx!'])
  File ""/Users/diegueus9/.virtualenvs/django1.8/lib/python2.7/site-packages/Django-1.11.dev20160923192832-py2.7.egg/django/test/testcases.py"", line 428, in assertFormError
    if field in context[form].errors:
AttributeError: 'AdminForm' object has no attribute 'errors'

----------------------------------------------------------------------
Ran 1 test in 0.771s

FAILED (errors=1)
Destroying test database for alias 'default'...
}}}

In the attached file I show that the validation works fine in the admin.
I did a little of debug using ipdb and noticed that the errors are in 'AdminForm.form.errors', perhaps it should be added a property to the AdminForm?
This also fails using django 1.8.x, 1.9.x, 1.10.x
"	Bug	closed	contrib.admin	dev	Normal	fixed	unittest, admin, modelform, adminform, test		Accepted	1	0	0	0	0	0
