How to specify current directory for specs?

Hello,

I’d like to know if it’s possible to specify what directory to use as
the current directory when executing the specifications. My specs are
in spec/ and I have some data in spec/data that I want to read from
one of the specs:

spec/book_spec.rb

require ‘book’

describe Book do
it “should read version” do
book = Book.new “data/JA_s12.book” # This should open the file
book.version.should == 1
end
end

Of course I can prepend spec/ to the path above, but I’d rather not. I
have created a rake task for running my specifications:

desc “Run all specs in the spec directory”
RSpec::Core::RakeTask.new(‘spec’) do |t|
t.rspec_opts = %w[–color]
end

Can I specify the spec/ directory as the current directory when
running this task? What is the expert recommendation? Is the data for
my specs malplaced, you think?
Thanks in advance!

Daniel

Hi Zach,

thanks for your detailed answer. I think I need some clarifications: I
am not using Rails, I have a regular ruby project. When I say I need
to read a file, I am talking about a binary file with Othello
positions, not a spec helper. It is not a file I can ‘require-in’.
Sorry for the confusion.

Daniel

On Tue, Nov 9, 2010 at 1:14 PM, Daniel L. [email protected]
wrote:

You can do this by ensuring the spec/ directory is at the front of your
load
path, ie:

$LOAD_PATH.unshift ‘spec’
or
$:.unshift ‘spec’

This will make it so when Ruby tries to require “book.rb” it looks in
the
spec directory first. I wouldn’t recommend this for loading spec helpers
as
it will take precedent over application code and you may run into
strange
issues.

desc “Run all specs in the spec directory”
RSpec::Core::RakeTask.new(‘spec’) do |t|
t.rspec_opts = %w[–color]
end

Can I specify the spec/ directory as the current directory when
running this task? What is the expert recommendation? Is the data for
my specs malplaced, you think?

Two things come to mind as how I might approach this: use spec_helper to
always load seed-data, or use a different mechanism to load your seed
data.
(well there’s a third, leave the require more verbose)

The first would be to open up spec_helper.rb and have it always load
seed
data when rspec runs:

Dir["#{File.dirname(__FILE__)}/data/**/*.rb"].each {|f| require f}

The second would be to create a custom method so in your spec you would
say:

seed_data ‘book’

And then you can have seed_data know about the full path to require the
data, ie:

def seed_data(name)
    require "spec/data/#{name}"
end

As much as I like removing unnecessary requires in specs I prefer
verbosity
over magic – anything that gives the code reader more clarity as to
what’s
necessary for a particular example group. A third option might be to
make
this work for both your rake task and when running specs individually:

require File.join(Rails.root, "spec/data/book")

Hope this helps,

Zach

Thanks in advance!

On 10 Nov, 22:50, Rhett S. [email protected] wrote:

Hi Daniel,

[…]

This has the benefit of being more explicit / less surprising to other
developers (including your future self), since the relative path for spec
execution is usually the project root.

Hi Rhett,

the above alternative looks very promising to me. Thanks for the
suggestion!

Daniel

Hi Daniel,

On Nov 10, 2010, at 2:59 PM, Daniel L. wrote:

Hi Zach,

thanks for your detailed answer. I think I need some clarifications: I
am not using Rails, I have a regular ruby project. When I say I need
to read a file, I am talking about a binary file with Othello
positions, not a spec helper. It is not a file I can ‘require-in’.

You can change the working directory for the process using FileUtils.cd.
If you want to change the directory for all your specs, you could do
something like:

In spec/spec_helper.rb

require ‘fileutils’

RSpec.configure do |config|
config.before
FileUtils.cd File.dirname(FILE)
end
end

You could do the same thing for particular specs if that works better
with what you want. Just adjust the path.

As an alternative, you might also consider having a helper like this:

again, in spec/spec_helper.rb

def spec_path(path)
File.expand_path("…/spec", FILE)
end

which you would use like so:

book = Book.new spec_path(“data/JA_s12.book”)

This has the benefit of being more explicit / less surprising to other
developers (including your future self), since the relative path for
spec execution is usually the project root.

Rhett