Chris LaBarge
Chris LaBarge

Reputation: 196

How do I load order dependent support files in Rspec without explicitly requiring the dependencies?

In my Ruby on Rails project I have some files in spec/support that are dependent on other files within the same directory.

#spec/support/page_objects/foo.rb

class Foo
  include Bar
end

#spec/support/page_objects/bar/bar.rb

module Bar
  def hello_world
    "Hello World"
  end
end

In order for Foo.new.hello_world to work in a spec, I must explicitly prefix the dependent file with require_relative("bar/bar").

#spec/support/page_objects/foo.rb

require_relative("bar/bar")

class Foo
  include Bar
end

I would prefer not to have to explicitly call require in all of my dependent files.

All of my spec/support files are loaded per this line of the spec/rails_helper.rb.

#spec/rails_helper.rb

Dir[Rails.root.join("spec", "support", "**", "*.rb")].sort.each { |f| require f }

I have determined that changing this line and explicitly loading dependencies first, will work.. But I am looking for a cleaner more long term solution.

I do not want to have to explicitly call require in all of my dependent files, nor do I want to have to name all of my dependencies in the above block for the sake of load order.

I just want it to work typical to how app/models works when using dependencies in development.

Is there a way to accomplish this?

Upvotes: 1

Views: 1019

Answers (1)

max
max

Reputation: 102218

You can use the auto-loader to load constants:

# config/environments/test.rb
config.autoload_paths << Rails.root.join('spec/support')

Its behavior differs slightly if we are talking about Zeitwerk or the classic autoloader. But adding a path to the autoloader paths means that the auto loader will look for Foo in spec/support/foo.rb as well as app/**/foo.rb.

But the real question is why your using classes/modules so extensively instead of RSpec's higher level constructs such as shared contexts or factories.

Upvotes: 2

Related Questions