Ruby 如何测试模块中的专用函数
Ruby 如何测试模块中的专用函数,ruby,unit-testing,ruby-1.9.2,Ruby,Unit Testing,Ruby 1.9.2,我有一个由两部分组成的问题:
第1部分
我有一个模块,它有一个公共类方法,它依赖于模块中的几个私有助手方法。测试这些私人助手方法的最佳方法是什么?它们包含需要测试的复杂逻辑,但是它们不应该被调用,因为它们本身没有提供任何有用的东西
我在stackoverflow post上读到,公约将:
module GTranslate
class Translator
def perform( text ); 'hola munda'; end
end
def self.transla
我有一个由两部分组成的问题:
第1部分
我有一个模块,它有一个公共类方法,它依赖于模块中的几个私有助手方法。测试这些私人助手方法的最佳方法是什么?它们包含需要测试的复杂逻辑,但是它们不应该被调用,因为它们本身没有提供任何有用的东西
我在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
然后对类GTranslate::Translator
的公共方法编写测试。但是,我不希望这个类能够实例化或调用其上的方法
第二部分
看到模块上的公共方法被定义为self.someMethodName
,这是否意味着助手方法必须被定义为self.helperName
没有模块的实例(如果您甚至可以创建模块的实例(我是Ruby新手)),因此我不能使用在实例上定义的send
方法从测试中调用该方法
有什么想法吗?我想你有三个选择
找到一种使用类的公共方法测试功能的方法。所有类功能通常都应该通过其公共方法公开。如果您不能仅通过使用类的公共方法来测试类,这可能表明设计中存在更深层次的问题
如果选项1不起作用(实际上有时也不起作用),则将私有功能重构到一个单独的类中,其中这些方法是公共的。这似乎是你的建议,我不认为有什么问题。测试是您正在构建的系统不可分割的一部分,应该这样对待。在我看来,将功能公开“只是为了测试”是完全正确的
将函数公开并测试它们。这在技术上是最简单的,但不如方案2干净
我想说你有三个选择
找到一种使用类的公共方法测试功能的方法。所有类功能通常都应该通过其公共方法公开。如果您不能仅通过使用类的公共方法来测试类,这可能表明设计中存在更深层次的问题
如果选项1不起作用(实际上有时也不起作用),则将私有功能重构到一个单独的类中,其中这些方法是公共的。这似乎是你的建议,我不认为有什么问题。测试是您正在构建的系统不可分割的一部分,应该这样对待。在我看来,将功能公开“只是为了测试”是完全正确的
将函数公开并测试它们。这在技术上是最简单的,但不如方案2干净
有两种情况:
私有方法被公共方法调用,或者被公共方法调用的私有方法调用,或者被被公共方法调用的私有方法调用的私有方法调用,或者…(你明白了)。在这种情况下,您不需要测试私有方法,因为它已经通过公共方法进行了测试
私有方法永远不会被公共方法调用。在这种情况下,您也不需要测试它,您可以简单地删除它,因为它从未被调用
因此,在这两种情况下,您根本不需要首先测试它
(请注意,它比这稍微复杂一点,因为私有方法可能通过反射或其他方式调用。但要点是:要么有人在某处调用私有方法,在这种情况下,它通过该人进行测试,要么没有人调用私有方法,在这种情况下,它是死代码。)
请允许我为测试驱动开发做一个小广告:在TDD中,未经测试的私有方法实际上不可能存在。将私有方法引入系统的唯一方法是从已经测试过的公共方法中提取。(实际上,在TDD中,任何未经测试的代码都不可能存在,因此未经测试的私有方法不可能存在的说法是非常正确的。)
一般来说,私有方法通常是通过从太大或太复杂的公共方法中提取它们来创建的。这一点的好处是提取方法重构有一个非常方便的特性:与所有其他重构一样,它不会改变外部可观察的行为,但与许多其他重构不同,其他重构需要对内部逻辑进行相当大的更改(例如Null对象重构或Replace-Conditional-With-polymorphics重构),它也不会改变内部逻辑,只是随意地修改代码。(事实上,使用Rubinius、IronRuby或JRuby中的优化编译器,对私有方法的调用可能是内联的,因此在提取方法之前和之后,实际执行的代码都是100%相同的。)
因此,如果您的代码在移动到私有方法之前已经过测试,那么保证在移动它之后仍然会进行测试。有两种情况:
私有方法被公共方法调用,或者被公共方法调用的私有方法调用,或者被被公共方法调用的私有方法调用的私有方法调用,或者…(你明白了)。在这种情况下,您不需要测试私有方法,因为它已经通过公共方法进行了测试
私有方法永远不会被公共方法调用。在这种情况下,您也不需要测试它,您可以简单地删除它,因为它永远不会被调用
因此,在这两种情况下,您根本不需要首先测试它
(注意,它比这稍微复杂一点,因为私有方法可能通过反射或其他方式调用
module Foo
class << self
private
def bar
...
end
end
end
Module Foo
class << self
puiblic :bar
end
end