Simple trick for testing forms full of checkboxes with django
In late 2011 I hope we can all agree that unit testing is pretty important when creating websites or almost anything. Doesn't really matter whether you prefer a blackbox integration testing approach or a strict unit testing style. What matters is that you have tests.

But what do you do when you want to test a form with a bunch of checkboxes?
You want to make sure all combinations of on/off tests are working. But with even just 6 checkboxes that's 2^6=64 test and ... well nobody in their right mind is going to write that many tests are they?
Last weekend I came up with a simple solution to this problem, dare I say elegant.
The approach is to make a list of checkboxes, then generate binary numbers from 0 to 2^(length of list). Then simply iterate over the generated binary numbers, pick all the checkboxes with a corresponding true bit in the number and run its test - the tests are lambda functions in a dictionary.
My code was complicated slightly because I had two distinct sets of checkboxes that had to be tested separately-ish, but here's what this basically looks like in code.
_columns = ['job_code', 'location_in', 'location_out', 'shift_report']
def checkboxes(self):
checks = []
for i in range(2**len(self._columns):
column_switch = bin(j)[2:].rjust(4, '0')
checks.append([name for (yes, name) in
zip(column_switch, self._columns) if int(yes)])
return checks
You also need to define the actual tests for all the checkboxes, deciding how thorough to be is a matter of personal taste, I like to test for the smallest possible symptom.
_column_checks = {
'job_code': {True: lambda r:
self.assert_('Job Code' in r.content,
"no code column"),
False: lambda r:
self.assert_('Job Code' not in r.content,
"is code column")},
# and so on (this example has been violently snipped, likely missing a } or two
' in r.content, "no code column"), False: lambda r: self.assert_('Job Code
' not in r.content, "is code column")}, # and so on
And finally the whole thing becomes a simple loop
for checkboxes in self.checkboxes():
# do a bunch of posts to django to set everything up
for check in _column_checks.keys():
_column_checks[check][check in checkboxes['columns']](response)
And that's it. Simple easily modifiable code to test every possible combination of all checkboxes in a form.