Python 单元测试Django查询集
我正在尝试使用Django/unittest学习单元测试 以下是我的模型的简单版本:Python 单元测试Django查询集,python,django,django-unittest,python-unittest,Python,Django,Django Unittest,Python Unittest,我正在尝试使用Django/unittest学习单元测试 以下是我的模型的简单版本: 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.GenericI
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)
这是我想出的测试代码:
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])
测试结果失败,因为在断言错误上
,即使设备.get_ips()
和[ip1、ip2、ip3]
的字符串表示形式相同
如果我尝试使用self.assertListEqual
我会得到一个错误,因为device.get\u ips()
是一个查询集,而不是列表
如果我尝试self.assertquerystequal
我会得到一个错误,说“DeviceTest对象没有属性assertquerystequal
”,但我不确定为什么,因为DeviceTest
扩展了django.test
的测试用例
我应该怎么做这样的测试
另外,在一个“真正”的项目中,做这样一个简单的测试有意义吗?调用
设备。get_ips()
返回一个查询集,而[ip1,ip2,ip3]
是一个列表。因此,他们目前并不平等
考虑到您不想测试可能无关紧要的内容(从数据库返回.filter()
中的行的顺序),我建议按如下方式进行测试:
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)
此测试:三个结果和IPs相同。这应该可以让您合理地确信您得到的是相同的对象(尽管您可以根据需要添加更多断言)。实际上正确的方法,djangoproject建议:
self.assertEqual(list(device.get_ips()), [ip1, ip2, ip3])
在queryset和list上强制执行sorted
,将更改您的测试场景,您不需要它。您键入了self.AssertQuerySequal
,它应该是self.AssertQuerySequal
,请尝试:
self.assertQuerysetEqual(device.get_ips(), [repr(ip1), repr(ip2), repr(ip3)],
ordered=False)
或者,如果您仍要根据列表对其进行测试:
self.assertItemsEqual(device.get_ips(), [ip1, ip2, ip3])
您是否知道,使用device.deviceip\u set.all()
是Django的内置方法,可以完成您的get\u ips()
方法的功能?查看Django的文档以了解反向外键。你也不需要测试它,因为它是标准的Django行为。谢谢@Ben,我才刚刚开始学习Django,还没有意识到这一点。我将切换到使用这种方法。或者,由于输入是唯一的,只需在断言中应用排序,它将同时考虑列表长度和内容self.assertEqual(已排序(result_-ips),已排序([ip1,ip,ip2.ip,ip3.ip])
感谢您的回答和评论,这两个答案都对我有用。我将改为使用Ben在上面推荐的deviceip_set()
,但这正是我了解如何进行此类测试所需要的@AustinPhillips,轻微打字错误:ip1,ip
应该是ip1.ip