如何在Ruby中从内存中完全删除类?
我有两个我正在使用的文件:
# foo.rb
require 'expensive_library'
class Foo < ExpensiveLibrary::Plugin
...
end
和
# foo_tests.rb
require 'foo'
require 'test/unit'
class foo_tests < Test::Unit::TestCase
def test_foo_meets_spec_1
...
end
def test_foo_meets_deprecated_spec
...
end
end
昂贵的图书馆很贵;加载需要15秒以上。这在开发过程中反复运行测试的时间太长(测试套件的其余部分不到1秒)。
我通过启动Pry并编写一个加载两个文件并调用Test::Unit:Autorunner.run
的函数来解决昂贵库的加载时间问题。在第一次测试中,这仍然有15秒的暂停,但后续的测试运行时间不到1秒。
然而,有两个问题:
根据其他Stack Overflow问题(例如“How to undefine class in Ruby?”),我尝试调用Object.constants.remove(:Foo)
和Object.constants.remove(:Foo_tests)
。我不再获得方法重新定义的错误,但现在自动运行器多次运行测试,包括删除测试。
我想要的是在不重新加载ExpensiveLibrary的情况下运行修改后的测试。取消定义测试类是我看到的方式,但我不知道如何。其他解决方案可能会更好。
答案 0 :(得分:1)
在我看来,您正在寻找的是Spork之类的预加载器,甚至是rspec-preloader之类的更具体的预加载器。使用预加载器时,您必须要求使用“foo”。文件在${variable}
文件中,您可能已经拥有该文件:
spec/spec_helper.rb
# spec/spec_helper.rb
require 'foo'
# ...
应加载整个应用环境。可以说,在一次运行一个测试时,它的成本更高。但是通过使用预加载器,您只需要一次所有代码。
答案 1 :(得分:0)
好的,只是在这里吐痰,因为我不确定你到底想要什么,但你尝试过undef
还是undef_method
?它们不能直接在类上工作,但是如果你取消调用你不想做的测试的方法,它可能对你有用吗?
答案 2 :(得分:0)
您可以破解加载路径(Adding a directory to $LOAD_PATH (Ruby))。
./tests/fake_implementations/
expensive_library.rb
ExpensiveLibrary
require 'expensinsive_library'
将加载此文件而不是原始文件。