Unit Testing Forms in Django

This is a subject that doesn’t seem to be covered well by other sources, so I am recording my notes on testing a Django form. Credit to “fRui Apps” for this post that gives an example. (See the section Testing Forms)

My goal is to get the test as close to the code as possible. Rather than using the view test, or even Selenium, this approach will isolate the form’s functions without going through all of Django’s URL routing, middleware, etc. Save that for the functional tests.

In this first example, my form will pad the entered number with left hand zeroes. This is the quick test:

def test_id_format(self):  
    ## Use factoryboy to create a model instance  
    e = EndowmentFactory.create()
    ## Instantiate form  
    form = EndowmentEntityForm(data={'endowment': e.pk,  
                                     'id_number': '528989',  
                                     'entity_type': EntityType.ORIGINATOR,})
    ## call is_valid() to create cleaned_data  
    self.assertTrue(form.is_valid())  
    ## Test away!  
    self.assertEqual(form.clean_id_number(),'0000528989')

Note that I’m using factoryboy to create a model instance to work with. The form data includes an id_number of fewer than 10 characters. After I call is_valid() to populate cleaned_data, I can test the cleaned id_number for the proper format.

In this next example, I am testing for valid and invalid data. My application allows changing the status of an object, but certain rules apply. Here is a test confirming that a valid change is allowed to continue:

##  Test for valid action types
def test_action_type_valid(self):
    ## Use factoryboy to create a model instance
    e = EndowmentFactory.create(status='E')        
    ## Instantiate form
    form = UserActionForm(data={'endowment': e.pk,
                                'username': 'dgentry',
                                'action_type': 'A',})
    ## is_valid() should return True if no errors are found
    self.assertTrue(form.is_valid())

And this will test for an invalid status change:

##  Test for valid action types
def test_action_type_valid(self):
    ## Use factoryboy to create a model instance
    e = EndowmentFactory.create(status='A')        
    ## Instantiate form
    form = UserActionForm(data={'endowment': e.pk,
                                'username': 'dgentry',
                                'action_type': 'E',})
    ## We run is_valid() and expect False
    self.failIf(form.is_valid())
    ## check for the error
    self.assertIn(u'Invalid Action',form.errors['__all__'])

I’m sure that I will learn more about testing forms as I go. Stay tuned…