What's `rspec/autorun` for? - ruby-on-rails

I was having some problem with zeus + rspec and the solution I found says that I must to delete require 'rspec/autorun' from spec_helper.rb.
That worked great, but I was wondering what's the utility of rspec/autorun? It comes in spec_helper.rb by default, but the specs works anyway with or without it.

As far as i understand, you would need rspec/autorun if you want to run specs using "ruby" command.
From RSpec docs:
Generally, life is simpler if you just use the rspec command. If you must use the ruby command, however, you’ll want to do the following:
require 'rspec/autorun'

rspec/autorun installs an at_exit hook that runs your tests. That way you can simply execute your testfiles directly rather than passing them to the rspec command (and a few other tricks, like having tests run automatically when you execute a library file).
Most setups don't need it.

Related

Tests that don't include spec_helper being ignored in rspec runs

When testing lib code there is rarely any need to require spec_helper and load all of rails. This is why I have been removing require "spec_helper" in favour of require_relative "../../lib/my_lib.rb".
These tests pass when called directly (rspec spec/lib/my_lib.rb) and are blazingly fast. Winner.
My issue comes when I try and run these tests as a group.
When I call rspec spec/lib it runs any lib specs that have a require "spec_helper" line but not any tests that don't.
I have played with spec_helper.rb to load in these tests, and that kind of works only it means that when I run rspec spec/models/blah.rb it will also run these lib tests, which obviously isn't what I want.
Is there a different way I should be calling my tests? Or is there a way I can get them added to the test run?
Notes
My spec_helper is configured to run the tests in a random order, I wonder if this has anything to do with it?
You should add _spec to your files:
spec/lib/my_lib_spec.rb
Rspec rake task will look only for files which end in _spec.

Selenium Can't Find 'spec' Folder

So I'm attempting to set up my local system to help finish off an existing project from an employer who uses only rails. They want me to primarily focus on rspec testing as the project is nearly functional and I need to flesh out the things they've missed. However, I cannot get 'rake spec' to build my test folder. As it is, the test folder contains a few basic user login tests using Selenium (I didn't write them). Here is the trace from the error:
/opt/local/lib/ruby/gems/1.8/gems/selenium-client-1.2.18/lib/selenium/rspec/spec_helper.rb:2:in 'require': no such file to load -- spec (LoadError)
from /opt/local/lib/ruby/gems/1.8/gems/selenium-client-1.2.18/lib/selenium/rspec/spec_helper.rb:2
from /Users/cliffhess/ampms/spec/integration/user_registration_name_not_blank_spec.rb:5:in 'require'
from /Users/cliffhess/ampms/spec/integration/user_registration_name_not_blank_spec.rb:5
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in 'load'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in 'load_spec_files'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in 'map'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/configuration.rb:386:in 'load_spec_files'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/command_line.rb:18:in 'run'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:55:in 'run_in_process'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:46:in 'run'
from /opt/local/lib/ruby/gems/1.8/gems/rspec-core-2.5.1/lib/rspec/core/runner.rb:10:in 'autorun'
from /opt/local/lib/ruby/gems/1.8/bin/rspec:19
rake aborted!
As it is, I'm pretty sure I understand the problem(maybe?). Line 2 in selenium-clients's spec_helper.rb says require 'spec' which, if I'm not mistaken, is saying that selenium-client should contain a folder called spec which contains all of its rspec stuff. selenium-client does not have this folder, so I'm a little bit confused as to how its supposed to require the folder in the first place. If I change the line to require 'rspec', there are numerous other references to things within this imaginary spec folder that will also cause rake to abort.
I'm running Ruby 1.8.7, Rails 3.0.3, and the latest version of selenium. Any help would be amazing, I've been stuck googling this problem for over a day now and haven't been able to come up with a fix.
I had the same issue you had, and I tried a few things to make it runnable, so I'm just copy my answers from my question - LoadError when using Selenium: no such file to load -- spec
First I found Cucumber + Webrat + Selenium guide which is really useful
Second, I removed
require "selenium/rspec/spec_helper"
require "spec/test/unit"
And added
require 'spec_helper'
Where spec_helper is the contained in the spec folder
I also removed all the methods that is append_after
Basically now the test cases runnable, this is not the best solution, but it is what I did do so far.
P.S: need to download the Selenium server from http://seleniumhq.org/download/ and run the server with java -jar selenium-server-standalone-2.0b2.jar

Expose Rails App Environment to Ruby Script

Out of pure curiosity, I am wondering if it's possible (no doubt it is) to 'hook into' a Rails Application's environment. So for example, say I want to create a cron script (I don't) that operates some sort of maintenance on a Rails app, and I want to write it in Ruby and using all of the nice code that I already have, for example, User.find etc.
Is this possible, and if so, how?
I'm just curious, as I feel I would eventually want to do this for some reason or other.
I'm currently on Rails 3 with Ruby 1.9.1, in case it matters.
This is certainly possible. Here is a good writeup on how to do that: How to run a rake task from cron
Take a look at the Rails::Railtie class. If you need to run code code when you start up your app, this is a way to do it. Here's a very simple example.
From the beginning of Rails there is ./script/runner, designed exactly for such kind of problems.
In Rails 3 you call it as: ./script/rails runner "puts User.find(:all).map(&:inspect)"
Try ./script/runner --help or ./script/rails runner --help
As the argument to the runner you provide a filename or just a code.
It's often more useful than preparing a Rake task, because you can execute just one-time actions:
ssh prod#example.com "cd rails/app && ./script/runner -e production 'puts User.count'"
You could either use script/rails runner as suggested by Arsen7 or you could write your own script in which you load the app environment in the beginning:
require 'config/environment'
is actually everything you need.
To have your script working in a cron job, make sure that it is executable (chmod u+x) and that it starts with a correct shebang line (#!/usr/bin/env ruby or whatever is appropriate for your situation).
yeah just require these file at top of your script file
require 'config/boot.rb'
require 'config/application.rb'
Rails.application.require_environment!
Now you'll have access to your models

How can I set the Rails environment for my somewhat stand alone Ruby script?

I have a Ruby script in my Rails app that I use to load some data from Twitter.
In the future I will make it an automatic background process, but for now I run it manually like:
ruby /lib/twitter/twitterLoad.rb
In order to use the Rails model classes and such, I have the following as the top line of the script:
require "#{File.dirname(__FILE__)}/../../config/environment.rb"
By default, the development environment is used. But, I'd like to be able to choose the production environment at some point.
Update #1: The RAILS_ENV constant is getting set in the environment.rb file. So, I was able to put ENV['RAILS_ENV'] = 'production' at the very top (before the environment.rb) line and solve my problem somewhat. So, my new question is, can do pass in env vars through the command line?
If you're going to be using the rails environment, your best bet would be to make this a rake script. To do this, put a twitter.rake file into lib/tasks and begin and end it like this:
task(:twitter_load => :environment) do
# your code goes here
end
That way, you're doing it by "following conventions" and it doesn't have that 'orrible smell associated with it.
I currently use the following method, and I know the environment doesn't have the rb extension, it's not needed. You can also set it before running it to overwrite the ENV["RAILS_ENV"].
#!/usr/bin/env ruby
# Set your environment here.
ENV["RAILS_ENV"] ||= "production"
require File.dirname(__FILE__) + "/../../config/environment"
puts "Rails was loaded!"
Then to change the environment, just run it with:
rb /lib/tasks/file.rb RAILS_ENV=development
Don't forget script/runner.
Set your environment variable from the command line and
ruby script/runner your_script_here.rb
The accepted answer to use rake is well-taken, but you may still want to manually set the environment for testing utility classes.
Here's what I use to set up the test environment for utility classes in /lib. For these I tend to use the Ruby convention of making my class file execute its tests when it gets run from the command line. This way I can do TDD outside of Rails' web-centric test harnesses, but still use the class within rake without affecting the environment that it sets.
This goes at the top:
if (__FILE__ == $0)
ENV['RAILS_ENV'] ||= 'test'
require File.join(File.dirname(__FILE__),'../config/environment.rb')
end
and this goes at the bottom:
if (__FILE__ == $0)
require 'test/unit/ui/console/testrunner'
Test::Unit::UI::Console::TestRunner.run(MyClassTest)
end
You can also do
script/console development < path/to/your/script.rb
Admiteddly cumbersome -and will spit out lots of irb garbage after evaluating each and every line of your script- but works for quickies and you dont have to remember that damned require line.
And don't forget that maybe the most elegant way to extend your app with scripts that do useful things is writing Rake tasks!
add the line:
RAILS_ENV = '<your environment of choice>'
http://wiki.rubyonrails.org/rails/pages/Environments#script
pantulis: It's cool that that works, but for quickies I just use RAILS_ENV = '<your environment of choice>' ruby path/to/script.rb. This is how you set environment variables in the console.
require 'bundler'
require 'bundler/setup'
ENV['RAILS_ENV'] ||= 'development'
RAILS_ROOT = Pathname.new(File.expand_path('~/path/to/root'))
puts "Loading Rails Environment from #{RAILS_ROOT}..."
require RAILS_ROOT.join('config/environment').to_s
This works but only if the Gemfile of your script contains all the dependencies of your rails app. You might be able to load one Gemfile from another, e.g just eval it, to overcome this copy/paste.

Why is RSpec so slow under Rails?

Whenever I run rspec tests for my Rails application it takes forever and a day of overhead before it actually starts running tests. Why is rspec so slow? Is there a way to speed up Rails' initial load or single out the part of my Rails app I need (e.g. ActiveRecord stuff only) so it doesn't load absolutely everything to run a few tests?
I definitely suggest checking out spork.
http://spork.rubyforge.org/
The railstutorial specifically addresses this, and gives a workaround to get spork running nicely in rails 3.0 (as of this moment, spork is not rails 3 ready out of the box). Of course, if you're not on rails 3.0, then you should be good to go.
The part of the tutorial showing how to get spork running in rails 3.0
http://railstutorial.org/chapters/static-pages#sec:spork
Checking when spork is rails 3.0 ready
http://www.railsplugins.org/plugins/440-spork
You should be able to to speed up your script/spec calls by running script/spec_server in a separate terminal window, then adding the additional -X parameter to your spec calls.
Why is rspec so slow? because it loads all the environement, loads fixtures and all that jazz.
Is there a way to speed up Rails' initial load you could try using mocks instead of relying on the database, this is actually correct for unit testing and will definitly speed up your unit tests. Additionnaly using the spec server as mentionned by #Scott Matthewman can help, same with the autotest from zentest mentionned by #Marc-Andre Lafortune
Is there a way to single out the part of my Rails app I need (e.g. ActiveRecord stuff only) so it doesn't load absolutely everything to run a few tests? what about this
rake test:recent
I am not sure how the rspec task integrate with this but you could definitely use the test:recent task as a template to do the same with rspec tests if the.
rake test:rspec:recent
doesn't exist yet
because it loads all the environement, loads fixtures and all that jazz.
The real culprit is if you run it using rake spec, it runs the db:test:prepare task.
This task drops your entire test database and re-creates it from scratch. This seems ridiculous to me, but that's what it does (the same thing happens when you run rake:test:units etc).
You can easily work around this using the spec application which rspec installs as part of the rspec gem.
Like this:
cd railsapp
spec spec # run all specs without rebuilding the whole damn database
spec spec/models # run model specs only
cd spec
spec controllers/user* # run specs for controllers that start with user
I think the "zen" experience you're looking for is to run spec_server and autospec in the background, with the result being near-instant tests when you save a file.
However, I'm having problems getting these two programs to communicate.
I found an explanation here:
I've noticed that autotest doesn't send commands to the spec_server.
Instead it reloads the entire Rails environment and your application's
plugins everytime it executes. This causes autotest to run
significantly slower than script server, because when you run the
script/spec command the specs are sent to the spec_server which
already has your Rails environment fired up and ready to go. If you
happen to install a new plugin or something like that, then you'll
have to restart the spec_server.
But, how do we fix this issue? I'm guessing it would involve downloading ZenTest and changing code for the autotest program, but don't have time to try it out right now.
Are you running this over Rails? If so, it's not RSpec's initialization that's slow, it's Rails'. Rails has to initialize the entire codebase and yours before running the specs. Well, it doesn't have to, but it does. RSpec runs pretty fast for me under my small non-rails projects.
Running tests can be really slow because the whole rails environment has to load (try script/console) and only then can all tests run. You should use autotest which keeps the environment loaded and will check which files you edit. When you edit and save a file, only the tests that depend on these will run automatically and quickly.
If you're using a Mac I recommend using Rspactor over autotest as it uses a lot fewer resources for polling changed files than autotest. There is both a full Cocoa version
RSpactor.app
or the gem version that I maintain at Github
sudo gem install pelle-rspactor
While these don't speed up individual rspec tests, they feel much faster as they auto run the affected spec's within a second of you hitting save.
As of rspec-rails-1.2.7, spec_server is deprecated in favor of the spork gem.
The main reason is that require takes forever on windows, for some reason.
Tips for speedup:
spork now works with windows, I believe.
You can try "faster_require" which caches locations:
http://github.com/rdp/faster_require
GL.
-rp
If you are on a Windows environment then there is probably little you can do as Rails seems to startup really slowly under Windows. I had the same experience on Windows and had to move my setup to a Linux VM to make it really zippy (I was also using autotest).

Resources