19

So I'm writing some rspec tests and I'm embarrassed at my lack of Ruby understanding.

I have a file structure that looks like the following:

  • GUI_Tests/Tests/test_spec.rb
  • GUI_Tests/windows_gui.rb
  • GUI_Tests/upload_tool.rb

when I run spec for the test_spec.rb file, I require the upload_tool file to be included like so:

spec -r ../upload_tool -fs test_spec.rb

Then, the upload_tool requires windows_gui.rb, like so:

require '../windows_gui'

My question is, why so I have to reference windows_gui.rb relative to test_spec.rb (requiring the ../) rather than the upload_tool.rb? This feels wrong to me, I'll want to use the upload_tool.rb out of context of the test specs, which means changing the requires each time.

Clearly I'm missing something, but if I don't reference relative to the test spec I get a file not found error.

Sorry for being so ignorant here, but I'm coming up empty handed. Any thoughts appreciated.

BB

Michael Durrant
  • 84,444
  • 83
  • 284
  • 429
Bobby B
  • 2,232
  • 3
  • 24
  • 31
  • 2
    Don't feel bad - I find dealing with relative paths one of the most annoying things about ruby. I've listed it in [what are the things you would like improved in the ruby language](http://stackoverflow.com/questions/585457/what-are-the-things-you-would-like-improved-in-the-ruby-language/3261063#3261063) – Andrew Grimm Jul 16 '10 at 00:24
  • August 2012 - Note that this post is now two years old. Most folks are now on 1.9.2. See this post http://stackoverflow.com/questions/9345412/relative-file-path-in-rspec also for the best solution (Feb 2012) – Michael Durrant Aug 26 '12 at 14:20

1 Answers1

20

You don't. requires are relative to the current directory, which in your case was GUI_Tests/Tests. If you did this instead:

cd ..
spec -r upload_tool -fs Test/test_spec.rb

You would have to use this:

require 'windows_gui' # without '../'

The most common way to get around that problem is using File.dirname(__FILE__):

require File.join(File.dirname(__FILE__), '..', 'windows_gui')

NOTE: in Ruby 1.9.2 require changed it's defaults: Ruby: require vs require_relative - best practice to workaround running in both Ruby <1.9.2 and >=1.9.2

Community
  • 1
  • 1
Adrian
  • 14,018
  • 7
  • 41
  • 67
  • 1
    Perfect - like I said, I was embarrassed for even having to ask, but I'm glad I did. That makes perfect sense. – Bobby B Jul 15 '10 at 17:51
  • 19
    Actually, `require` is *not* relative to the current directory, it is relative to the *search path* (i.e. the special constant `$LOAD_PATH` or its alias `$:` ). It just so happens that on older versions of Ruby (i.e. all except the not-yet-but-soon released 1.9.2), the current directory ( `.` ) is in the search path by default: `p $:.include?('.') # => true` . However, as of Ruby 1.9.2 that is no longer the case and shouldn't be relied upon. In Ruby 1.9, you could use `require_relative` which works relative to the source file it is called from instead of the search path. – Jörg W Mittag Jul 15 '10 at 18:10
  • @Jorg: But if I run this in 1.9: `$:.replace []; require '../somefile'`, it works. – Adrian Jul 15 '10 at 18:56