1

我有一个两部分的问题:

第1部分

我有一个模块,它有一个公共类方法,它依赖于模块中的一些私有帮助方法。测试这些私有辅助方法的最佳方法是什么?它们包含需要测试的复杂逻辑,但不应公开调用它们,因为它们本身并没有提供任何有用的东西。

我在this stackoverflow post上读到约定是:

module GTranslate
  class Translator
    def perform( text ); 'hola munda'; end
  end

  def self.translate( text )
    t = Translator.new
    t.perform( text )
  end
end

然后在 class 的公共方法上编写测试GTranslate::Translator。但是,我不希望此类能够实例化或调用它们的方法。

第2部分

看到模块上的公共方法定义为self.someMethodName,这是否意味着辅助方法必须定义为self.helperName

将没有模块的实例(如果您甚至可以创建模块的实例(我是 Ruby 新手)),所以我不能使用send实例上定义的方法从我的测试中调用该方法?

有任何想法吗?

4

3 回答 3

6

正如您将在其他答案中看到的那样,关于测试私有方法存在一些争论。在测试它们之前,您应该考虑它是否是最佳选择。David Brady与 Robert C.(鲍勃叔叔)Martin进行了一次精彩的播客,他们在其中讨论了这个问题以及一些可能的解决方案,包括通过公共接口进行测试,以及重构为一个单独的类。

话虽如此,这就是Ruby。如果您想测试私有方法,请使用instance_eval(或class_eval用于类方法)在模块的上下文中运行您的测试。

编辑: 经过一些快速的 IRB 工作模块需要更多的工作

鉴于:

module Foo
  class << self
    private
    def bar
      ...
    end
  end
end

要测试 Foo.bar 放入您的测试文件:

Module Foo
  class << self
    puiblic :bar
  end
end

在您的测试期间,您的测试bar将是公开且可见的。

结束编辑

也可以看看:

于 2011-04-18T05:45:54.277 回答
2

我会说你有三个选择。

  1. 找到一种使用类的公共方法来测试功能的方法。所有类的功能通常都应该通过它的公共方法公开。如果您不能仅通过使用它的公共方法来测试一个类,这可能表明设计存在更深层次的问题。

  2. 如果选项 1 不起作用(有时确实不起作用),请将私有功能重构为一个单独的类,其中这些方法是公共的。这似乎是您的建议,我认为这没有问题。测试是您正在构建的系统的一个组成部分,应该这样对待。在我看来,将功能公开“仅用于测试”是完全有效的。

  3. 公开这些功能并对其进行测试。这在技术上是最简单的,但不如选项 2 干净。

于 2011-04-17T23:16:04.040 回答
2

有两种情况:

  1. 私有方法被公共方法调用,或者被公共方法调用的私有方法,或者被公共方法调用的私有方法调用的私有方法,或者......(你明白了)。在这种情况下,您不需要测试私有方法,因为它已经通过公共方法进行了测试。
  2. 私有方法永远不会被公共方法调用。在这种情况下,您也不需要测试它,您可以简单地删除它,因为它永远不会被调用。

因此,在这两种情况下,您根本不需要首先对其进行测试。

(请注意,它比这更复杂一些,因为私有方法可能通过反射或其他方式调用。但要点是:要么某个地方的某个人调用私有方法,在这种情况下,它通过那个人进行测试,或者没有人调用私有方法,在这种情况下它是死代码。)

如果我可以为测试驱动开发打一个小广告:在TDD中,未经测试的私有方法实际上是不可能存在的。将私有方法引入系统的唯一方法是从已经测试过的公共方法中提取。(实际上,在 TDD 中,任何未经测试的代码都不可能存在,因此未经测试的私有方法不可能存在的说法是微不足道的。)

通常,私有方法通常是通过从变得太大或太复杂的公共方法中提取它们来创建的。这样做的好处是 Extract Method Refactoring 有一个非常方便的属性:与所有其他 Refactoring 一样,它不会改变外部可观察的行为,但许多其他 Refactoring 不同,后者需要对内部逻辑进行相当大的更改(例如空对象重构或用多态重构替换条件),它改变内部逻辑,要么。它只是随机播放代码。(事实上​​,使用像 Rubinius、IronRuby 或 JRuby 这样的优秀优化编译器,对私有方法的调用可能会被内联,因此实际执行的代码在提取方法之前和之后都是 100% 相同的.)

因此,如果您的代码在您移入私有方法之前已经过测试,那么在您移入私有方法之后,它保证仍会被测试。

于 2011-04-18T01:40:48.520 回答