How can I completely remove a class from memory in Ruby?
I have two files I'm working with:
# foo.rb
require 'expensive_library'
class Foo < ExpensiveLibrary::Plugin
...
end
and:
# 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
ExpensiveLibrary is expensive; it takes over 15 seconds to load. This is way too long to repeatedly run the tests during development (the rest of the test suite takes less than 1 second).
I have worked around the load time of the expensive library by starting Pry and writing a function that loads the two files and calls Test::Unit:Autorunner.run
. This still has a 15 second pause in the first run of the tests, but subsequent test runs take less than 1 second each.
However, there are two problems:
Based on other Stack Overflow questions (like "How to undefine class in Ruby?"), I have tried calling Object.constants.remove(:Foo)
and Object.constants.remove(:Foo_tests)
. I no longer get the method redefined errors, but now the autorunner runs the tests multiple times, including removed tests.
What I want is to run the modified tests without reloading ExpensiveLibrary. Undefining the test classes is the way I see to do it, but I don't know how. Other solutions might be better.
It seems to me that what you're looking for is a preloader such as Spork, or even a more specific one like rspec-preloader. When using a preloader, you will have to require your 'foo' file in a spec/spec_helper.rb
file, which you probably already have:
# spec/spec_helper.rb
require 'foo'
# ...
The spec_helper
should load your entire app environment. Arguably, it's more expensive when running tests one at a time. But by using a preloader, you only have to require all the code once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With