Django 模型单元测试:对新手的帮助

Django Models Unit Tests: Help for a newbie

是的,这是我最后想问的地方,因为问题非常模糊,但我很茫然。

基本上,我正在尝试学习如何编码,目前我正在使用 Django 来帮助我掌握后端的东西。我一直被提醒单元测试的重要性,所以我想将它们包含在我正在从事的虚拟项目中,这样我就可以在我的编程之旅中尽早开始理解它们……只是……它们看起来很容易表面上看,但对于初学者来说显然比我认为的要复杂。

我不完全确定哪里/如果我在这里出错了,所以请随时戳我并取笑我,但请尝试为我指明正确的方向,或一些初学者友好的资源(搜索互联网和没有大量的信息)。

我的项目是一个与警务相关的虚拟 GUI(希望将来在我的作品集中使用它)

这是模型 class 我需要测试方面的帮助。还有其他的,但我想自己做,一旦我知道更多:

class Warrant(models.Model):
"""
"""
name = models.CharField(max_length=50)
WARRANT_TYPE_CHOICES = (
    ('ARREST', 'Arrest'),
    ('SEARCH', 'Search'),
)
warrant_type = models.CharField(max_length=10, choices=WARRANT_TYPE_CHOICES, default='ARREST')
start_date = models.DateTimeField(auto_now=True, null=True)
expiry_date = models.DateTimeField(auto_now_add=True, null=True)
renewal_date = models.DateTimeField(auto_now_add=True, null=True)

如您所见,模型相当简单。

以下是我目前漫无目的地摆弄的测试:

def test_model_creation(self):
    object = Warrant.objects.create()
    self.assertIsNotNone(object)

def test_warrant_str(self):
    warrant = Warrant.objects.create(
        name="Warrant Name",
    )
    self.assertEqual(str(warrant), "Warrant Name")

def test_datetime_model(self):
    start_date = Warrant.objects.create(start_date=datetime.now())
    expiry_date = Warrant.objects.create(expiry_date=datetime.now())
    renewal_date = Warrant.objects.create(renewal_date=datetime.now())

对我来说,这读起来很好,而且所有测试 return OK。但是,我不确定这是否是最佳做法,或者是否真的做了我认为应该做的事情。

此外,我也不确定如何测试 warrant_type / WARRANT_TYPE_CHOICES 字段。

我知道这通常不是应该在这里问的问题类型,但我基本上只是随机输入我从教程中学到的东西,甚至不知道它是否正确。

谢谢

我认为您的测试实际上没有做任何有用的事情,但有一种方法可以做我认为您正在寻找的事情。如果我想编写测试以确保模型正确创建对象,我会这样做:

from django.test import TestCase

class WarrantTestCase(TestCase):
    def setUp(self):
        self.warrant = Warrant.objects.create(name="Warrant Name", warrant_type="SEARCH")

    def test_warrant_create(self):
        warrant = Warrant.objects.get(name="Warrant Name")
        self.assertEqual(warrant.type, "SEARCH")

设置首先创建一个示例对象,然后我的测试获取该对象并检查保证金类型是否与我期望的类型相同。

有关 Django 单元测试的更多信息,请参阅文档:https://docs.djangoproject.com/en/3.1/topics/testing/overview/

你想先考就好!您测试的通常不是模型,而是行为,或者换句话说,方法。如果您向模型中添加了一个方法,其中包含一些实际逻辑,那么就是开始对其进行测试的好时机。例如:

class Warrant(models.Model):
    name = models.CharField(max_length=50)
    WARRANT_TYPE_CHOICES = (
        ('ARREST', 'Arrest'),
        ('SEARCH', 'Search'),
    )
    warrant_type = models.CharField(max_length=10, choices=WARRANT_TYPE_CHOICES, default='ARREST')
    start_date = models.DateTimeField(auto_now=True, null=True)
    expiry_date = models.DateTimeField(null=True)
    renewal_date = models.DateTimeField(null=True)

    @property
    def is_expired(self):
        return self.expiry_date < timezone.now()

作为测试用例:

import datetime
from .models import Warrant
from django.test import TestCase
from django.utils import timezone


class WarrantTestCase(TestCase):
    def test_is_expired_returns_true_if_expiry_date_before_now(self):
        now = timezone.now()
        hour_ago = now - datetime.timedelta(hours=1)
        warrant = Warrant.objects.create(expiry_date=hour_ago)
        self.assertTrue(warrant.is_expired)

    def test_is_expired_returns_false_if_expiry_date_after_now(self):
        now = timezone.now()
        in_an_hour = now + datetime.timedelta(hours=1)
        warrant = Warrant.objects.create(expiry_date=in_an_hour)
        self.assertFalse(warrant.is_expired)

请注意,我确实从字段 expiry_daterenewal_date 中删除了属性 auto_now_add=True。这可能是您不想要的行为。我通过编写这个测试用例来解决这个问题,因为当我没有删除它时,其中一个测试用例失败了。测试万岁!