thoughtbot/shoulda

Shoulda destroys rake tasks (in test environment) with ruby 1.9.3

jarl-dk opened this issue · 9 comments

The following series of commands reproduces the problem from scratch:

$ ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
$ rails --version
Rails 3.2.8
$rails new basic_app/
$cd basic_app/
$echo "gem 'shoulda'" >> Gemfile
$echo "gem 'therubyracer', :platforms => :ruby" >> Gemfile
$bundle update
$RAILS_ENV=test rake db:create

The last command results in the following stacktrace:

/home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:167:in `block in non_options': file not found: db:create (ArgumentError)
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:146:in `map!'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:146:in `non_options'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:207:in `non_options'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:52:in `process_args'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/minitest/unit.rb:891:in `_run'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/minitest/unit.rb:884:in `run'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:21:in `run'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:326:in `block (2 levels) in autorun'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:27:in `run_once'
        from /home/jarl/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/test/unit.rb:325:in `block in autorun'

This does not happen without the shoulda gem.

Related bug reports:
#207
jimweirich/rake#51

This should be resolved in 3.3.2 due to a fix in shoulda-context.

I still experience this with shoulda 3.3.2 (sholda-context 1.0.1 and shoulda-matchers 1.4.1). Please reopen...

I can reproduce this.

Here's what I did on my local machine:

$ rails -v
Rails 3.2.8
$ ruby -v
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.2.0]
$ rails new app-for-shoulda-223
$ cd app-for-shoulda-223
$ <edit Gemfile to look like below>
$ bundle
$ rake db:create:all
db/development.sqlite3 already exists
/Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:167:in `block in non_options': file not found: db:create:all (ArgumentError)
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:146:in `map!'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:146:in `non_options'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:207:in `non_options'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:52:in `process_args'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/minitest/unit.rb:891:in `_run'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/minitest/unit.rb:884:in `run'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:21:in `run'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:326:in `block (2 levels) in autorun'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:27:in `run_once'
        from /Users/gabe/.rbenv/versions/1.9.3-p125/lib/ruby/1.9.1/test/unit.rb:325:in `block in autorun'

Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.8'
gem 'sqlite3'

gem 'shoulda-context', '1.0.1'

Nothing else is changed from a vanilla Rails 3.2.8 install.

I've tracked this down to Test::Unit's at_exit hook, in test/unit.rb:

@@stop_auto_run = false
def self.autorun
  at_exit {
    Test::Unit::RunCount.run_once {
      exit(Test::Unit::Runner.new.run(ARGV) || true)
    } unless @@stop_auto_run
  } unless @@installed_at_exit
  @@installed_at_exit = true
end

The ARGV part means that it treats db:create:all as an argument to the test runner. As proof, adding this to the Rakefile fixes the error:

class Test::Unit::Runner
  @@stop_auto_run = true
end

I'm not sure why including shoulda-context makes it think that db:create:all should be passed to Test::Unit though.

Aha, found it. shoulda-context has this line:

require "test/unit"

which causes the autorunning to kick in. If I change it to require "test/unit/testcase", the error disappears.

The pull request referenced above, thoughtbot/shoulda-context#17, fixes the issue. Once that's in a released version, it should fix your problem.

@jarl-dk the fix is released in shoulda-context v1.0.2.

👍

I have verified it...