rspec-preload is a short script that does the easy 70% of tools like spring and zeus. In addition to that, it runs before(:suite)
hooks once.
I've tried spring before. For some reason it sometimes failed to pick up file changes, and at other times consumed 100% CPU, even when sleeping. For all I know, these problems could be solved by now but were serious enough back then.
In addition, I worked on projects that performed slow DB cleanup tasks on startup. Even spring could not help with those (could it?).
And so I thought "how hard can it be" and scratched my own itch.
This is a hack, for many reasons:
- It peeks deep into RSpec internals. Those could change at any time. Works only on RSpec 3.
- It preloads
spec_helper.rb
andrails_helper.rb
. Whatever files get required will never be reloaded. Gems, Rails configuration, initializers, and whatever they require will not be reloaded, and you will get no warnings. If you change those files you'll have to restart the preloader to pick the changes up. That said, most of the things in Rails are auto-loaded. Since specs are run in a subprocess, spec code and anything it depends on gets thrown away after each run, to be loaded on the next again. - Only FactoryBot factories get reloaded. Because that was easy.
- I've had crashes when forking on newer Macs and Rails.
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
helped.
It is not meant to be installed in the normal sense. Copy bin/rspec_preload.rb
to your scripts folder. Or clone this repo.
$ bundle exec ruby ./path/to/rspec_preload.rb
(rspec_preload) $
Now you can type in your rspec command as usual:
$ bundle exec ruby ./path/to/rspec_preload.rb
(rspec_preload) $ rspec spec/my_spec.rb
....
Finished in ... seconds ()
One caveat: bare rspec
picks up no specs rather than all specs. You can pass the spec folder as a parameter to run all specs:
$ bundle exec ruby ./path/to/rspec_preload.rb
(rspec_preload) $ rspec
No examples found.
(rspec_preload) $ rspec spec
....
Finished in ... seconds ()
You can prepend it with bundle exec
, or anything else really; anything before the first rspec
will be thrown away:
$ bundle exec ruby ./path/to/rspec_preload.rb
(rspec_preload) $ bundle exec rspec spec/my_spec.rb
....
Finished in ... seconds ()
The command input uses Ruby gets
which is not human friendly. You can use rlwrap
to add normal input navigation, history, etc:
$ rlwrap bundle exec ruby ./path/to/rspec_preload.rb
(rspec_preload) $ rspec spec/my_spec.rb
....
Finished in ... seconds ()
No guarantees. It might break, it might lie to you (it probably will!), it might brick your computer. Use at your own risk.
In any case, if you use it do first understand what it does. You have been warned.
I found rspec-preloader. I should have searched earlier. It is neat; it tracks file changes and reloads them. But it does not load rails_helper.rb
nor run before(:suite)
hooks. Alternatives FTW!