我有一个现有的单元测试代码库,其中为每个测试定义了相同的类,以及一个迭代它们的程序。像这样:
test_files.each do |tf|
load "tests/#{tf}/"+tf
test= ::Kernel.const_get("my_class")
Test::Unit::UI::Console::TestRunner.run( test )
在进行这些测试时,我意识到 ruby 允许您从不同的文件中require
具有相同名称的类,并且它合并了两者的方法。一旦类层次结构不相同,这就会导致问题:superclass mismatch for class ...
不幸的是,只是unloading the class这还不够,因为层次结构中还有许多其他类仍处于加载状态。
有没有办法在不同的全局命名空间中执行每个测试?
虽然我认为使用模块是可行的方法,但我对手动更改数百个现有文件的想法并不感到兴奋。
--编辑--
按照 Cary Swoveland 的建议,我已将测试运行代码移至单独的 .rb
文件并使用反引号运行它。虽然这似乎运行良好,但加载 ruby 解释器并再次要求
所有库会产生相当大的开销。此外,跨平台兼容性需要一些额外的工作。
最佳答案
首先我想提出以下解决方案:
#main.rb
modules = []
Dir.foreach('include') do |file|
if file =~ /\w/
new_module = Module.new
load "include/#{file}"
new_module.const_set("StandardClass", StandardClass)
Object.send(:remove_const, :StandardClass)
modules << new_module
end
end
modules.each do |my_module|
my_module::StandardClass.standard_method
end
#include/first.rb
class StandardClass
def self.standard_method
puts "first method"
end
end
#include/second.rb
class StandardClass
def self.standard_method
puts "second method"
end
end
这用它自己的模块包装每个类,并在它的模块中调用类:
$ruby main.rb
second method
first method
但是正如您所回答的那样,存在对其他类的引用,因此模块可以破坏它们。 我通过从一个包装类中调用第三个类来检查这一点并得到:
include/second.rb:5:in `standard_method': uninitialized constant StandardClass::Independent (NameError)
所以使用反引号可能是更好的解决方案,但我希望我的回答对其他类似情况有所帮助。
关于ruby - Ruby 中的多个同名类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21710017/