Django中的单元测试


12

我真的很难为一个大型Django项目编写有效的单元测试。我具有相当好的测试覆盖范围,但是我已经意识到,我一直在编写的测试绝对是集成/验收测试,而不是单元测试,而且我的应用程序中有关键部分没有得到有效测试。我想尽快解决此问题。

这是我的问题。我的模式是深层的关系,并且非常注重时间,这给我的模型对象带来了很高的内部耦合和很多状态。我的许多模型方法都是基于时间间隔进行查询的,而在带有auto_now_add时间戳的字段中,我有很多事情要做。因此,以如下所示的方法为例:

def summary(self, startTime=None, endTime=None):
    # ... logic to assign a proper start and end time 
    # if none was provided, probably using datetime.now()

    objects = self.related_model_set.manager_method.filter(...)

    return sum(object.key_method(startTime, endTime) for object in objects)

一种方法如何测试这样的东西?

这是我到目前为止的位置。在我看来,应该对单元测试目标的参数进行一些模拟行为by key_method,是否summary正确地过滤/聚合以产生正确的结果?

模拟datetime.now()很简单,但是我如何模拟其余的行为呢?

  • 我可以使用固定装置,但是我听说过使用固定装置构建数据的利弊(可维护性差是我的主意)。
  • 我也可以通过ORM设置数据,但这可能是有局限性的,因为那时我还必须创建相关的对象。而且ORM不允许您auto_now_add手动处理字段。
  • 模拟ORM是另一种选择,但是模拟深度嵌套的ORM方法不仅棘手,而且ORM代码中的逻辑也从测试中被模拟出来,而模拟似乎使测试真正依赖于内部和内部依赖。被测功能。

最难破解的螺母似乎是这样的功能,它们位于几层模型和较低级别的功能上,并且非常依赖于时间,即使这些功能可能并不十分复杂。我的总体问题是,无论我如何看待它,我的测试看起来都比它们要测试的功能复杂得多。


从现在开始,您应该首先编写单元测试,这可以帮助您在编写实际的生产代码之前发现设计中的可测试性问题。
2013年

2
这是有帮助的,但是并没有真正解决如何最好地测试内在有状态,ORM繁重的应用程序的问题。
2013年

您必须抽象掉持久层
Chedy2149

1
假设听起来很不错,但是在项目维护方面,我认为在业务逻辑和文档详尽的Django ORM之间插入定制的持久层不会有不小的代价。突然,这些类挤满了许多微小的中间方法,它们本身需要随着时间的推移而重构。但这也许在可测试性至关重要的地方是合理的。
2013年

检出此内容:vimeo.com/43612849,以及此内容:vimeo.com/15007792
Chedy2149

Answers:


6

我将继续并为到目前为止提出的答案注册一个答案。

我的假设是,对于具有深层耦合和状态的函数,现实情况是,它将仅需要花费很多行来控制其外部上下文。

这是我的测试用例的大致外观,它依赖于标准的Mock库:

  1. 我使用标准ORM设置事件顺序
  2. 我创建自己的起点datetime并颠覆auto_now_add时间以适应设计的固定时间表。我以为ORM不允许这样做,但是效果很好。
  3. 我确保使用被测函数,from datetime import datetime以便可以datetime.now()仅对该函数进行修补(如果我模拟整个datetime类,则ORM会适合)。
  4. 我创建了自己的替换项object.key_method(),具有简单但定义明确的功能,具体取决于参数。我希望它取决于参数,因为否则我可能不知道被测函数的逻辑是否正常工作。就我而言,它只是返回startTime和之间的秒数endTime。我通过将其包装在lambda中并直接object.key_method()使用的new_callablekwarg对其进行修补patch
  5. 最后,我对summary带有不同参数的各种调用运行一系列断言,以检查与预期的人工计算结果是否相等,从而说明了模拟的给定行为key_method

不用说,这比函数本身更长,更复杂。它取决于数据库,并没有真正的单元测试感觉。但是它也与函数的内部相当分离,只是它的签名和依赖关系。因此,我认为它实际上仍然是单元测试。

在我的应用程序中,该功能非常关键,可以对其进行重构以优化其性能。因此,尽管存在复杂性,但我认为麻烦是值得的。但是我仍然对如何解决这个问题有更好的想法。我朝着更受测试驱动的开发风格的漫长旅程的所有部分...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.