我有一个关于使用Django进行测试驱动开发的概念性问题,也可能适用于其他框架。
TDD指出,开发周期中的第一步是编写失败的测试。
假设进行单元测试,我想验证在请求到达时是否确实创建了一个项目。为了测试该功能,我想向测试客户端发出一个请求,并与db检查该对象是否已正确创建。为此,我需要在测试文件中导入相关模型,但是在编写此测试的第一步时,我什至没有模型。因此,我将无法运行测试以查看它们是否失败。
这里建议的方法是什么?也许先写一个简单的测试,然后在实现足够水平的生产代码之后修改测试?
答案 0 :(得分:1)
重要提示:您所描述的不是单元测试。它不测试一个单元。它测试从django url接线,视图到模型的整个过程。这是集成测试。其次,不要创建使用外部API(或大多数相同的测试客户端)来创建数据的测试,而是通过直接进入数据库来检查是否创建了实体。这个不好。如果通过某些API创建数据,则应使用相同级别的API来检查数据是否已创建。所以我的解释将讨论这种方法。
从TDD开始时,您描述的是一个常见问题。
关于TDD的重要事项是您:
这听起来很简单,您很可能已经阅读并知道,但是对您的工作结构的影响可能并不那么明显。
主要结果是,在实现功能之前,您不会从头开始编写完整的测试。首先,您可以进行最简单的测试,使其工作(通过实现某些功能),然后进行重构。然后,您可以通过添加更多要检查的内容来更改测试,实施该测试以使测试变为绿色,重构等。
其结果是,您需要拆分工作(或通过简单的步骤计划如何实现)才能在此模式下工作。这需要一些实践,我想这是采用TDD的主要障碍之一。
它与您写的内容相似(但有重要区别)
也许首先编写一个简单的测试,然后在实现足够水平的生产代码之后修改测试?
首先需要进行简单的测试,然后以较小的步骤进行迭代修改,但是在之前而不是在之后实现生产代码。
在这种情况下,您可以按照以下步骤进行实施:
def test_entity_creation(self):
post_result = test_client.post(POST_URL, {})
get_result = test_client.get(get_entity_url_from(post_result))
assert_that(get_result, not_none())
您的测试失败,但是没有编写任何代码行。 请注意,尚未传递任何数据,并且检查是非常基本的。
这样做以便测试通过。您只需要很少的代码更改,并且视图将不会返回太多(如果有的话)。此时,View可以返回一些硬编码的json / dict。
def test_entity_creation(self):
post_result = test_client.post(POST_URL, {})
get_result = test_client.get(get_entity_url_from(post_result))
assert_that(get_result, not_none())
assert_that(get_result, has_field('id', not_none()))
您可以通过在硬编码字典上添加id来使此测试有效。
添加一个新的测试来检查ID是否唯一:
def test_create_generates_unique_id(self):
post_result1 = test_client.post(POST_URL, {})
post_result2 = test_client.post(POST_URL, {})
assert_that(get_id(post_result1), not_(equal_to(get_id(post_result2)))
添加仅具有ID的模型并从视图中添加其创建和检索并不难。不要添加所有需要的字段,稍后将逐步进行。
def test_entity_creation(self):
post_result = test_client.post(POST_URL, {'field': 'value'})
get_result = test_client.get(get_entity_url_from(post_result))
assert_that(get_result, not_none())
assert_that(get_result, has_field('field', 'value'))
在模型中添加一个字段并通过测试。
添加更多测试和生产代码。
对于一个TDD周期,步骤4可能太大。它至少需要对三件事进行更改:
在许多情况下,通过首先为模型本身创建测试来拆分它是有意义的。不能与测试客户端一起使用的测试,如下所示:
def test_entity(self):
entity = Entity.objects.create()
entity = Entity.objects.get(entity.id)
assert_that(entity.id, not_none())
然后添加一个模型。确保test_entity
通过,并且只有在修改视图之后才能使用您(已经测试)的模型。
我希望这能为解决这个问题提供思路。
答案 1 :(得分:0)
在Django中,方法始终是重新创建用于测试和登台的工作环境。在测试中数据是伪造的,在分期中数据是“旧的”或与生产非常相似。