如何使用Django模型应用测试驱动开发?

时间:2014-05-21 16:41:21

标签: django unit-testing testing tdd django-testing

我最近了解了测试驱动开发,并希望在我的Django项目中开发新应用时尝试一下。我一直在阅读Test-Driven Development with Python,这很棒。但是,我有时发现书中的示例(待办事项列表)过于简单 - 例如,当testing Models is introduced时,作者有一个测试创建对象,保存它们,然后拉动数据库中的对象检查其值。当然,当您的模型只有一个ModelField时,这很容易。

但是当你的模型有20个ModelFields时呢?您是否应该使用一个测试来创建一个具有所有Fields的对象,然后保存该对象,然后检查每个字段的值?为每个领域进行单独测试是否更好?

在我的具体情况中,我有一个包含大约五个必填字段的模型,然后还有大约十五个可选字段。我现在的想法是首先在我的TestCase类中创建一个函数,该函数使用默认字段创建此Model的对象。然后,我将进行测试以确保对象正常保存,然后对每个单独的可选字段进行另一次测试。看起来像很多测试,但是并不是比一次大型测试更好的小测试?

洞察力表示赞赏!

3 个答案:

答案 0 :(得分:4)

我是这本书的作者。我的意思是将测试更多地作为Django ORM的介绍,而不是作为最佳实践的演示,我试着在当时解释,但我想有些混乱是不可避免的。我会考虑如何以不同的方式呈现内容。

在任何情况下,如果您跳到本书中的a few chapters later,我将展示如何将测试简化为最佳实践。

你是否测试基本的Django模型取决于你 - 有些人会说测试声明性语法是顶部的,其他人会说短测试很适合作为占位符。这是您可以使用的一个:

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author)
    ISBN = models.CharField(max_length=35)
    abstract = models.TextField()


class BookTest(TestCase):

    def test_defaults(self):
        book = Book()
        self.assertEqual(book.title, '')
        self.assertEqual(book.author, None)
        self.assertEqual(book.ISBN, '')
        self.assertEqual(book.abstract, '')

这就是占位符。它鼓励您添加更多测试,如果您开始引入更复杂的字段,例如publication_date字段,其默认值为datetime.today() + one_month,这可能需要进行一些测试以确保您获得它对。占位符降低了后续测试的障碍。其他人会告诉你,这超过了顶部。你必须找到自己的平衡。

一个被广泛接受的事情是你绝对应该测试行为。因此,如果您的模型有自定义方法:

class Book(models.Model):
    # [...]

    def is_available(self):
        return self.pub_date < datetime.today() and Stock.objects.filter(book=self).count() > 0

然后对此进行某种测试绝对是一个好主意。

答案 1 :(得分:1)

这是模型工厂可以提供帮助的地方。有两个流行的模块提供它:

我个人使用factory_boy并发现它非常易于使用。

基本上,您使用默认字段值定义工厂:

class UserFactory(factory.Factory):
    class Meta:
        model = models.User

    first_name = 'John'
    last_name = 'Doe'
    admin = False

然后,您可以use the factory并覆盖字段值(如果需要)。它还支持SequencesLazy Attributes以及其他用于生成数据的有用功能。

谈到你的特定任务,尽量不要测试django实际上有什么测试。例如,不需要测试required参数是否有效。测试操作模型所涉及的自定义模型逻辑。

此外,A Guide to Testing in Django是一个很好的阅读。

希望有所帮助。

答案 2 :(得分:1)

为什么要测试保存和加载数据库的值?这是Django的责任。 Django有一整套测试,可以详细检查其数据库层是否正常工作。绝对没有理由检查任何字段的基本行为,更不用说所有字段了。

您的单元测试适用于您的逻辑:自定义方法,视图和模板标记。它们不适用于Django默认提供的逻辑。