我应该unittest private/protected方法吗

2024-05-26 17:43:12 发布

您现在位置:Python中文网/ 问答频道 /正文

这实际上是语言不可知论。但我将用python给出上下文。

我有这个家长班

class Mammal(object):
    def __init__(self):
        """ do some work """

    def eat(self, food):
        """Eat the food"""
        way_to_eat = self._eating_method()
        self._consume(food)

    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

这里eat是唯一的公共方法,而_consume_eating_method实际上是受保护的方法,将由子类实现。

当您只编写了Mammal类时,您将测试什么?

显然这四种方法。

现在让我们介绍一个孩子

class Tiger(Mammal):    
    def _eating_method(self):
        """Template method"""

    def _consume(self, food):
        """Template method"""

看看这个班。它只有2种保护方法。

我应该测试所有4个Tiger方法(包括2个继承的方法)还是只测试引入的更改(仅重写2个方法)?

理想情况是什么?


Tags: 方法self语言objectfooddeftemplatemethod
3条回答

从理论角度来看,您只需要测试可实例化类的公共方法(在标准OOP语言中)。测试内部行为是没有意义的,因为您只需要“该输入的输出”(针对特定方法或整个类)。您应该尽量尊重它,因为它会迫使您对类的encapsulation和提供的接口提出一些问题,这些问题可能对您的体系结构起决定性作用。

从实用的角度来看,有时您可能会有一些抽象的helper类,这些类没有实现的具体子类,或者抽象类分解了90%以上的子类,并且如果不插入受保护的方法就很难测试输出。在这种情况下,您可以mock一个子类。

在您的简单示例中,我建议您只测试类Tiger(并且只测试公共方法eat)。

Just a note for people thinking to TDD. In TDD, you shouldn't have started to code the class Mammal before the class Tiger because Mammal should be the result of a refactoring phase. So, you certainly woudn't have any specific test for Mammal.

我的方法是:

  • 创建Mammal的最小可测试子类,该子类提供两个受保护方法的最小实现,允许您对公共方法的行为进行单元测试。
  • 为每个子类编写单独的单元测试,这些子类再次在Mammal上测试公共方法,但断言特定于该子类的行为。

这将为您提供必要的测试覆盖率和最少的测试数量。

另一种方法是只测试子类,并且在其中一个子类单元测试中还断言特定于Mammal的特性。这避免了创建特定测试子类的需要,但是有两个缺点:

  • 您不再孤立地测试Mammal,因此对Mammal特定代码的测试很容易因为子类中的问题而失败。
  • 其他人可能不太清楚Mammal的属性是如何测试的,以及在哪里测试的。

在测试时,您应该关注代码的外部行为,而不是实现细节。我不知道背景,所以我在这里做一些大的假设。

你真的关心(潜在的抽象)哺乳动物超类的行为吗?通过继承关系的重用有那么重要吗?如果决定将继承关系替换为基于组合的策略呢?

我将重点测试你真正关心的课程的行为:“老虎是否按预期进食?”而不是测试一些只为代码重用而引入的抽象超类。

相关问题 更多 >

    热门问题