使用Django进行测试驱动的开发

时间:2018-09-18 14:44:39

标签: python django testing tdd

我有一个关于使用Django进行测试驱动开发的概念性问题,也可能适用于其他框架。

TDD指出,开发周期中的第一步是编写失败的测试。

假设进行单元测试,我想验证在请求到达时是否确实创建了一个项目。为了测试该功能,我想向测试客户端发出一个请求,并与db检查该对象是否已正确创建。为此,我需要在测试文件中导入相关模型,但是在编写此测试的第一步时,我什至没有模型。因此,我将无法运行测试以查看它们是否失败。

这里建议的方法是什么?也许先写一个简单的测试,然后在实现足够水平的生产代码之后修改测试?

2 个答案:

答案 0 :(得分:1)

重要提示:您所描述的不是单元测试。它不测试一个单元。它测试从django url接线,视图到模型的整个过程。这是集成测试。其次,不要创建使用外部API(或大多数相同的测试客户端)来创建数据的测试,而是通过直接进入数据库来检查是否创建了实体。这个不好。如果通过某些API创建数据,则应使用相同级别的API来检查数据是否已创建。所以我的解释将讨论这种方法。

从TDD开始时,您描述的是一个常见问题。

关于TDD的重要事项是您:

  1. 迈出小步
  2. 测试后重构为绿色(包括测试重构)

这听起来很简单,您很可能已经阅读并知道,但是对您的工作结构的影响可能并不那么明显。

主要结果是,在实现功能之前,您不会从头开始编写完整的测试。首先,您可以进行最简单的测试,使其工作(通过实现某些功能),然后进行重构。然后,您可以通过添加更多要检查的内容来更改测试,实施该测试以使测试变为绿色,重构等。

其结果是,您需要拆分工作(或通过简单的步骤计划如何实现)才能在此模式下工作。这需要一些实践,我想这是采用TDD的主要障碍之一。

它与您写的内容相似(但有重要区别)

  

也许首先编写一个简单的测试,然后在实现足够水平的生产代码之后修改测试?

首先需要进行简单的测试,然后以较小的步骤进行迭代修改,但是在之前而不是在之后实现生产代码。

在这种情况下,您可以按照以下步骤进行实施:

1创建使用测试客户端的测试

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

您的测试失败,但是没有编写任何代码行。 请注意,尚未传递任何数据,并且检查是非常基本的。

2创建url连线并清空视图

这样做以便测试通过。您只需要很少的代码更改,并且视图将不会返回太多(如果有的话)。此时,View可以返回一些硬编码的json / dict。

3.1检查是否已生成实体的ID

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来使此测试有效。

3.1检查是否已生成实体的唯一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)))

4仅添加ID的模型

添加仅具有ID的模型并从视图中添加其创建和检索并不难。不要添加所有需要的字段,稍后将逐步进行。

5向您的测试添加一个字段

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

在模型中添加一个字段并通过测试。

6继续进行TDD

添加更多测试和生产代码。

更多想法

对于一个TDD周期,步骤4可能太大。它至少需要对三件事进行更改:

  1. 后视图处理程序
  2. 获取视图处理程序
  3. 模型

在许多情况下,通过首先为模型本身创建测试来拆分它是有意义的。不能与测试客户端一起使用的测试,如下所示:

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中,方法始终是重新创建用于测试和登台的工作环境。在测试中数据是伪造的,在分期中数据是“旧的”或与生产非常相似。