Opened 13 years ago

Closed 13 years ago

#15996 closed New feature (wontfix)

Form and Field comparison always fails

Reported by: gcc1 Owned by: nobody
Component: Forms Version: 1.3
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

It would be nice to be able to unit test that a particular view returns a correctly configured Form object in its response context. But this seems to be hard, because Form and Field objects don't compare properly.

For example, take the following view:

def decision_add_page(request):
    decision_form = DecisionForm()
        
    return render_to_response('decision_add.html',
        RequestContext(request,
            dict(decision_form=decision_form)))

I try to test it like this:

def get(self, view_function, **view_args):
    return self.client.get(reverse(view_function, kwargs=view_args))
    
def test_decision_add_page(self):
    response = self.client.get(reverse(openconsent.publicweb.views.decision_add_page))
    self.assertEqual(DecisionForm(),
        response.context['decision_form'])

And it fails because it can't compare the two objects:

File "/home/chris/projects/openconsent/django/openconsent/publicweb/tests.py", line 37, in test_decision_add_page
    self.assertEqual(DecisionForm(), response.context['decision_form'])
AssertionError: <openconsent.publicweb.forms.DecisionForm object at 0xa55cc4c> != <openconsent.publicweb.forms.DecisionForm object at 0xa55ce6c>

Then I tried to wrap both in list(), hoping that at least comparison on field objects was implemented:

    self.assertEqual(list(DecisionForm()),
        list(response.context['decision_form']))

But I get the same kind of error:

File "/home/chris/projects/openconsent/django/openconsent/publicweb/tests.py", line 38, in test_decision_add_page
    list(response.context['decision_form']))
AssertionError: Lists differ: [<django.forms.forms.BoundFiel... != [<django.forms.forms.BoundFiel...

First differing element 0:
<input id="id_short_name" type="text" name="short_name" maxlength="255" />
<input id="id_short_name" type="text" name="short_name" maxlength="255" />

Diff is 1761 characters long. Set self.maxDiff to None to see it.

How would one go about implementing equality sensibly for forms and fields?

Change History (1)

comment:1 by Luke Plant, 13 years ago

Component: UncategorizedForms
Resolution: wontfix
Status: newclosed
Triage Stage: UnreviewedAccepted
Type: UncategorizedNew feature

I was going to accept, but while thinking about implementing it, I persuaded myself that it isn't a great idea.

Could your test not be implemented very easily by just comparing string output of the form? After all, if two forms render identically, then they are identical, otherwise they are different. And in theory, any difference should be enough to mean that the forms are different - you might want a regression test to check that the correct widget is being used for a form etc.

This has the advantage that it is nice and explicit, and you don't have to worry about what form equality means. If equality is not obvious, perhaps it is better not to implement it, and we can also avoid different expectations over the semantics of form/field equality, and the need to document it etc. - the principle of least surprise here probably means that we should admit that we don't know what is meant by form equality, and not try to implement it.

Even just implementing __eq__ to do compare rendered forms is slightly problematic, since there is more than one way of rendering a form, and we'd have to choose one, and they might not necessarily give the same answer if one of the methods has been overridden to add some custom functionality.

For this reason I'm going to close WONTFIX. If there is a reason my solution won't work or is problematic, please re-open.

Note: See TracTickets for help on using tickets.
Back to Top