我有一个单元测试的现有代码库,其中为每个测试定义了相同的类,以及一个迭代它们的程序。像这样:
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解释器并再次require
所有库会产生相当大的开销。此外,跨平台兼容性还需要一些额外的工作。
答案 0 :(得分:2)
首先,我想提出以下解决方案:
#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)
所以使用反引号可能是更好的解决方案,但我希望我的回答对其他类似情况有帮助。