【问题标题】:How do I unit test the methods in a method object?如何对方法对象中的方法进行单元测试?
【发布时间】:2010-05-06 21:10:50
【问题描述】:

我已经执行了Beck 描述的“Replace Method with Method Object”重构。

现在,我有一个带有“run()”方法的类和一堆将计算分解为更小的单元的成员函数。如何测试这些成员函数?

我的第一个想法是,我的单元测试基本上是“run()”方法的副本(具有不同的初始化),但每次调用成员函数之间都有断言以检查计算状态。

(我正在使用 Python 和 unittest 模块。)

class Train: 

    def __init__(self, options, points): 
        self._options = options 
        self._points = points 
        # other initializations

    def run(self): 
        self._setup_mappings_dict() 
        self._setup_train_and_estimation_sets() 
        if self._options.estimate_method == 'per_class': 
            self._setup_priors() 
        self._estimate_all_mappings() 
        self._save_mappings() 

    def _estimate_all_mappings(): 
        # implementation, calls to methods in this class

    #other method definitions

对于作为run() 方法实现的一部分,在调用不同方法之前和之后成员属性的状态应该是什么,我绝对有期望。我应该对这些“私有”属性做出断言吗?我不知道如何对这些方法进行单元测试。

另一种选择是我真的不应该测试这些。

【问题讨论】:

  • 一些代码或伪代码将有助于理解您的问题。从您所写的内容来看,听起来您可能会从 unittest.TestCase.setUp() 方法中受益。 docs.python.org/library/unittest.html#unittest.TestCase.setUp
  • 我已经使用您提供的代码编辑了您的问题。能否检查缩进是否正确,必要时重新编辑?
  • @ire_and_curses。谢谢,修改了一下。

标签: python unit-testing refactoring tdd


【解决方案1】:

我会回答我自己的问题。经过一番阅读和思考,我相信我不应该对这些私有方法进行单元测试。我应该只测试公共接口。如果进行内部处理的私有方法足够重要,可以独立测试,并且不仅仅是当前实现的巧合,那么也许这表明它们应该被重构为一个单独的类。

【讨论】:

  • +1 用于自我回答,并且在这方面做得很好,如果它不适合单元测试,也许它不是一个“单元”。
  • 强烈反对。有很多理由将方法隐藏为私有方法,但这些方法具有有助于独立于公共 API 进行测试的重要功能。 Python 确实允许您测试受保护/私有方法 - 您只需要了解名称修改。
【解决方案2】:

我喜欢你的回答,但我不同意。

您将使用此设计模式的情况是进行相当复杂的操作。因此,我想说,能够验证此类操作的各个组件是非常可取的。

然后,您会遇到对其他资源的依赖问题(在这种情况下可能是这样,也可能不是)。

您需要能够使用某种形式的控制反转来注入某种形式的模拟来隔离类。

除了大多数模拟框架之外,还会为您提供访问私有成员的访问器。

【讨论】:

  • 感谢您提供此替代视图。当我问这个问题时,我并没有意识到要嘲讽。
  • 从那以后我也改变了主意,变成了一个像你一样的人。如果您需要测试私有,那么它可能应该移到另一个班级。不过,我认为我的想法仍然适用于应该是内部的——而不是私人的。
  • 我建议不要使用 Inversion-of-Control 构建您的类,尤其是在 Python 中,除非有明确的用例,例如决策引擎,您要包装在一个通用对象中.它可能会导致代码非常混乱,如果您这样做的唯一原因是为了测试,那么还有更直接的方法可以解决它(测试私有函数或猴子修补函数调用)。
【解决方案3】:

这里有两个原则在起作用。首先是公共方法应该是您想要公开的公共 API。在这种情况下,公开 run() 是合适的,而公开 estimate_all_mappings() 则不合适,因为您不希望其他人调用该函数。

第二个是单个函数应该只做一件事。在这种情况下,run() 组合了其他几个复杂操作的结果。 estimate_all_mappings() 正在执行其中一项复杂的操作。反过来,它可能会委托给其他一些函数 estimate_map(),该函数执行 estimate_all_mappings() 聚合的单一估计。

因此,进行这种职责委派是正确的。那么所需要的就是知道如何test a private method

拥有另一个类的唯一原因是,如果有一些功能子集构成它自己的行为单元。例如,您不会创建一些仅由 A 类调用/使用的 B 类,除非存在一些更容易作为对象传递的状态单元。

【讨论】:

    猜你喜欢
    • 2016-10-18
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 2011-10-18
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多