Vaughan Vaughan - 7 months ago 16
Python Question

Unit testing a Django query set

I'm trying to learn unit testing with Django/unittest.

These are simple versions of my models:

class Device(models.Model):
name = models.CharField(max_length=100)

def get_ips(self):
return DeviceIP.objects.filter(device=self.id)


class DeviceIP(models.Model):
ip = models.GenericIPAddressField()
device = models.ForeignKey(Device)


And this is the test code I've come up with:

from django.test import TestCase

class DeviceTest(TestCase):

def test_get_ips(self):
device = Device()
device.name = 'My Device'

ip1 = DeviceIP()
ip1.ip = '127.0.0.1'
ip1.device = device
ip1.save()

ip2 = DeviceIP()
ip2.ip = '127.0.0.2'
ip2.device = device
ip2.save()

ip3 = DeviceIP()
ip3.ip = '127.0.0.3'
ip3.device = device
ip3.save()

self.assertEqual(device.get_ips(), [ip1, ip2, ip3])


The test results fails because on an
AssertionError
even though the string representations of
device.get_ips()
and
[ip1, ip2, ip3]
are identical.

If I try using
self.assertListEqual
I get an error because
device.get_ips()
is a QuerySet and not a list.

If I try
self.assertQuerySetEqual
I get an error saying "
DeviceTest object has no attribute assertQuerySetEqual
" but I'm not sure why because
DeviceTest
extends
django.test
's TestCase.

How should I be doing a test like this?

Also, in a "real" project would it make sense to do such a simple test?

Answer

The call device.get_ips() returns a QuerySet whereas [ip1, ip2, ip3] is a list. Hence they're currently not equal.

Given that you don't want to test things that may not matter (order in which rows are returned in .filter() from the database), I suggest testing as follows:

results = device.get_ips()
result_ips = [ip.ip for ip in results]
self.assertEqual(len(results), 3)
self.assertTrue(ip1.ip in result_ips)
self.assertTrue(ip2.ip in result_ips)
self.assertTrue(ip3.ip in result_ips)

This tests: three results and IPs are the same. This should give reasonable confidence that you're getting the same objects (although you can add more assertions as desired).

Comments