如何在一个Ruby模块中包含单元测试?

6

我正在尝试将一个模块的单元测试包含在与模块本身相同的源文件中,遵循 Perl modulino 模型。

#! /usr/bin/env ruby

require 'test/unit'

module Modulino
    def modulino_function
        return 0
    end
end

class ModulinoTest < Test::Unit::TestCase
    include Modulino
    def test_modulino_function
        assert_equal(0, modulino_function)
    end
end

现在,我可以运行该源文件以执行单元测试。
但是,当我从另一个脚本中require/load它们时,它们也会被运行。如何避免这种情况?
除非不建议这种做法,否则是否有更符合Ruby习惯的方法来实现这一点?
4个回答

13

就我个人而言,我从未听说过有任何人试图在Ruby中做到这一点。 这绝对不是标准的做法。 话虽如此,您可能可以利用这个技巧:

if __FILE__ == $0
  # Do something.. run tests, call a method, etc. We're direct.
end

如果文件是直接执行的,而不是被另一个库或应用程序所需要,那么在if块中的代码才会执行。

更多Ruby技巧请参见:http://www.rubyinside.com/21-ruby-tricks-902.html


我发现在(通常是)小的独立模块还“年轻”的时候,在编辑器内能够立即执行(如SciTE)是一种方便的工作方式。当然,如果你拥有更大的代码体系和/或AutoTest,则这显然不是一个问题。但我并不生活在那个世界中;-) - Mike Woodhouse
谢谢,这可以使用标准(普通?)模块运行,但对于单元测试来说不起作用,因为它们是自动执行的。对于提供的链接点赞。 - philant
1
你可以将 require 'test/unit' 和测试用例定义放在 if 语句内部,这样它们只会在当前文件被执行时运行。 - BaroqueBobcat
1
我曾经认为你可以像 @BaroqueBobcat 建议的那样做。这将防止在你不运行测试时 test/unit 成为一个依赖项。 - samg

3

您可以使用minitest在模块源代码内部包含单元测试。

试试这个例子:

class Foo < String
end

if $0 == __FILE__
    require 'minitest/autorun'
    require 'minitest/pride'

    class FooTest < MiniTest::Unit::TestCase
        def test_foo_instantiation
            foo = Foo.new()
            assert_instance_of Foo, foo
        end

        def test_foo_parent_class
            foo = Foo.new()
            assert_kind_of String, foo
        end
    end
end

这里我创建了一个名为Foo的类,它继承自String类。 然后我创建了两个单元测试。第一次测试中,我检查是否可以实例化Foo类的对象。 在第二个测试中,我检查Foo类的实例化对象是否属于String类型。

如果将此代码写入名为foo.rb的文件中,我只需使用以下命令运行测试:

ruby foo.rb

Minitest执行速度快。 "pride"模块允许您以彩色字体输出测试结果,这对眼睛很好。


3

在Ruby中,这并不罕见,尽管在Rails中并不是常见做法。

你可能会遇到的一个问题与这篇文章相同,即模块应该被包含在类中进行测试。当然,通过将模块包含在测试用例中,可以对模块进行测试,但这只能测试模块在混合到Test::Unit::TestCase时是否有效,而不能测试它在混合到更实用的东西时是否有效。

因此,单元测试应该放在类文件中,或者如果您只想使用通用方法,则使用类函数而不是模块。


1

刚刚找到了一种方法,可以防止在从脚本中要求模块时执行单元测试。在 .../lib/ruby/1.8/test/ 中的 unit.rb 中有一个标志可以设置为 true。

结合 samg 的技巧(再次感谢),我们可以这样写:

if (__FILE__ != $0)
    Test::Unit.run = true  ### do not run the unit tests
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接