我最近了解了测试驱动开发,并希望在我的Django项目中开发新应用时尝试一下。我一直在阅读Test-Driven Development with Python,这很棒。但是,我有时发现书中的示例(待办事项列表)过于简单 - 例如,当testing Models is introduced时,作者有一个测试创建对象,保存它们,然后拉动数据库中的对象检查其值。当然,当您的模型只有一个ModelField时,这很容易。
但是当你的模型有20个ModelFields时呢?您是否应该使用一个测试来创建一个具有所有Fields的对象,然后保存该对象,然后检查每个字段的值?为每个领域进行单独测试是否更好?
在我的具体情况中,我有一个包含大约五个必填字段的模型,然后还有大约十五个可选字段。我现在的想法是首先在我的TestCase类中创建一个函数,该函数使用默认字段创建此Model的对象。然后,我将进行测试以确保对象正常保存,然后对每个单独的可选字段进行另一次测试。看起来像很多测试,但是并不是比一次大型测试更好的小测试?
洞察力表示赞赏!
答案 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并覆盖字段值(如果需要)。它还支持Sequences,Lazy Attributes以及其他用于生成数据的有用功能。
谈到你的特定任务,尽量不要测试django实际上有什么测试。例如,不需要测试required
参数是否有效。测试操作模型所涉及的自定义模型逻辑。
此外,A Guide to Testing in Django
是一个很好的阅读。
希望有所帮助。
答案 2 :(得分:1)
为什么要测试保存和加载数据库的值?这是Django的责任。 Django有一整套测试,可以详细检查其数据库层是否正常工作。绝对没有理由检查任何字段的基本行为,更不用说所有字段了。
您的单元测试适用于您的逻辑:自定义方法,视图和模板标记。它们不适用于Django默认提供的逻辑。