【问题标题】:Django Models Unit Tests: Help for a newbieDjango 模型单元测试:对新手的帮助
【发布时间】:2020-10-28 14:16:11
【问题描述】:

是的,这是我最不想问的地方,因为这个问题非常模糊,但我不知所措。

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

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

我的项目是一个与警务相关的虚拟 GUI(希望将来在我的投资组合中使用它)

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

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())

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

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

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

谢谢

【问题讨论】:

    标签: django unit-testing django-models django-unittest


    【解决方案1】:

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

    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。这可能是您不想要的行为。我通过编写这个测试用例来解决这个问题,因为当我没有删除它时,其中一个测试用例失败了。测试万岁!

    【讨论】:

    • 谢谢!真的很有用。就这样我有一个明确的想法,我是不是也用这种方式测试 start_date 和renewal_date ?
    • 对于字段本身,没有什么要测试的。你可以相信 Django,如果你定义了一个字段,它就会在那里。但是,当您使用它作为逻辑基础时,换句话说,当您有使用它的方法时,您应该为该方法编写一个或多个测试用例。
    【解决方案2】:

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

    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/

    【讨论】:

    • 我同意,但有一个补充。由于您将对象存储在self.warrant中的setUp中,因此您不需要在测试用例本身中再次从数据库中获取它,而可以简单地测试:self.assertEqual(warrant.name, "Warrant Name")self.assertEqual(warrant.type, "SEARCH")
    猜你喜欢
    • 2017-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    相关资源
    最近更新 更多