I'm trying to do something seemingly simple but it's proven rather hard.
I want to write tests using RSpec for classes that I've put in the lib directory of a Rails Engine.
Here are exactly the steps I'm using:
rails plugin new mygem -T --mountable --full --dummy-path=spec/dummy
Then I cd mygem; vim mygem.gemspec
I add the following line to mygem.gemspec:
s.add_development_dependency "rspec-rails"
I run bundle install; rails generate rspec:install
Then I edit ~/mygem/lib/mygem/engine.rb adding the following:
module Mygem
class Engine < ::Rails::Engine
isolate_namespace Mygem
config.generators do |g|
g.test_framework :rspec
end
end
end
I create a very simple class in the lib directory, ~/mygem/lib/mygem/something.rb
and add the following:
module Mygem
class Something
def hi
"hi"
end
end
end
Create a test file ~/mygem/spec/something_spec.rb
then add the following:
require 'rails_helper'
describe Mygem::Something do
it 'says hi' do
s = Mygem::Something.new
expect(s.hi).to eq('hi')
end
end
And boom, I get the following output:
rspec
~/Documents/mygem/spec/rails_helper.rb:3:in `require': cannot load such file -- ~/Documents/mygem/config/environment (LoadError)
from ~/Documents/mygem/spec/rails_helper.rb:3:in `<top (required)>'
from ~/Documents/mygem/spec/something_spec.rb:1:in `require'
from ~/Documents/mygem/spec/something_spec.rb:1:in `<top (required)>'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1327:in `load' from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1327:in `block in load_spec_files'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1325:in `each'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb:1325:in `load_spec_files'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:102:in `setup'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:88:in `run'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:73:in `run'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb:41:in `invoke'
from ~/.rvm/gems/ruby-2.2.2/gems/rspec-core-3.3.2/exe/rspec:4:in `<top (required)>'
from ~/.rvm/gems/ruby-2.2.2/bin/rspec:23:in `load'
from ~/.rvm/gems/ruby-2.2.2/bin/rspec:23:in `<main>'
from ~/.rvm/gems/ruby-2.2.2/bin/ruby_executable_hooks:15:in `eval'
from ~/.rvm/gems/ruby-2.2.2/bin/ruby_executable_hooks:15:in `<main>'
Any tips as to what I may be doing incorrectly?
Thanks in advance!
It looks like your rails_helper is looking for an environment.rb file to load, which doesn't exist in a Rails engine. It does, however, exist in your dummy app, which is what RSpec is run against.
Try adding this into the top of your rails_helper file:
require File.expand_path("../dummy/config/environment.rb", __FILE__)
Finally got it working after the following steps (thanks ccai for the suggestion):
in rails_helper.rb:
# Comment this line:
# require File.expand_path('../../config/environment', __FILE__)
require File.expand_path("../dummy/config/environment.rb", __FILE__)
then in lib/mygem.rb
require "mygem/something"
Works!
Related
How do you test gem functionality? I'm trying to figure out why something isn't working the way the docs suggest, and set up my own version of these. Yet my test fail:
19: ...
18: ...
#...etc....
5: from /Users/me/code/project/test/shrine_test.rb:5:in `<top (required)>'
4: from /Users/me/code/project/test/shrine_test.rb:5:in `require'
3: from /Users/me/.rvm/gems/ruby-2.5.0/gems/lockbox-0.4.8/lib/lockbox.rb:20:in `<top (required)>'
2: from /Users/me/.rvm/gems/ruby-2.5.0/gems/lockbox-0.4.8/lib/lockbox.rb:20:in `require'
1: from /Users/me/.rvm/gems/ruby-2.5.0/gems/lockbox-0.4.8/lib/lockbox/railtie.rb:1:in `<top (required)>'
/Users/me/.rvm/gems/ruby-2.5.0/gems/lockbox-0.4.8/lib/lockbox/railtie.rb:2:in `<module:Lockbox>': uninitialized constant Rails::Railtie (NameError)
Did you mean? Rails
This is my test file, shrine_test.rb:
require "bundler/setup"
Bundler.setup
require "minitest/autorun"
require "minitest/pride"
require "lockbox" #this is the line 5 from above
$logger = ActiveSupport::Logger.new(ENV["VERBOSE"] ? STDOUT : nil)
require_relative "support/shrine"
require_relative "support/active_record"
Lockbox.master_key = SecureRandom.random_bytes(32)
class ShrineTest < Minitest::Test
#tests here
end
Assuming the gem in your Gemfile is in the default group (not in any group :environment do block), replace the Bundler.setup with
Bundler.require(:default)
I would be very grateful for some advice on the following.
Below I have a simplified example for our setup.
I have defined some Helper modules on our RSpec test suite:
## spec/rails_helper.rb
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
config.include ViewHelpers
end
### spec/support/view_helpers/base.rb
# frozen_string_literal: true
module ViewHelpers
class Base
# class content
end
end
### spec/support/view_helpers/admins/payments/new.rb
# frozen_string_literal: true
module ViewHelpers
module Admins
module Payments
class New < Base
# class content
end
end
end
end
With this setup the specs run perfectly locally; the sub-class New inherits from Base as expected. However, when the tests are running on Travis CI, we get the following error:
NameError:
1433 uninitialized constant ViewHelpers::Admins::Payments::Base
1434# ./spec/support/view_helpers/admins/payments/new.rb:6:in `<module:Payments>'
1435# ./spec/support/view_helpers/admins/payments/new.rb:5:in `<module:Admins>'
1436# ./spec/support/view_helpers/admins/payments/new.rb:4:in `<module:ViewHelpers>'
1437# ./spec/support/view_helpers/admins/payments/new.rb:3:in `<top (required)>'
1438# ./spec/rails_helper.rb:34:in `block in <top (required)>'
1439# ./spec/rails_helper.rb:34:in `each'
1440# ./spec/rails_helper.rb:34:in `<top (required)>'
1441# ./spec/controllers/admins/billpayers_controller_spec.rb:3:in `<top (required)>'
I have also tried inheriting with explicit namespacing:
# frozen_string_literal: true
module ViewHelpers
module Admins
module Payments
class New < ViewHelpers::Base
# class content
end
end
end
end
Again, this runs successfully locally but Travis CI errors:
NameError:
1433 uninitialized constant ViewHelpers::Base
1434# ./spec/support/view_helpers/admins/payments/new.rb:6:in `<module:Payments>'
1435# ./spec/support/view_helpers/admins/payments/new.rb:5:in `<module:Admins>'
1436# ./spec/support/view_helpers/admins/payments/new.rb:4:in `<module:ViewHelpers>'
1437# ./spec/support/view_helpers/admins/payments/new.rb:3:in `<top (required)>'
1438# ./spec/rails_helper.rb:34:in `block in <top (required)>'
1439# ./spec/rails_helper.rb:34:in `each'
1440# ./spec/rails_helper.rb:34:in `<top (required)>'
1441# ./spec/controllers/admins/billpayers_controller_spec.rb:3:in `<top (required)>'
I am rather stumped as to why this works locally but not on CI.
Would be very grateful for any support and insight.
Thanks
Sam
Hi did you double checked your autoload configurations? (https://guides.rubyonrails.org/autoloading_and_reloading_constants.html)
Autoload and cache classes may be configured differently based on your environment configs:
├── config/environments
├── development.rb
├── production.rb
└── test.rb
It turns out the ordering of
Dir[Rails.root.join("spec/support/**/*.rb")]
depends on the OS and filesystem.
This means the sub-classes were getting required before the super-class.
Solution:
Dir[Rails.root.join("spec/support/**/*.rb")].sort
I've been using cucumber in my app, which is a rails 2.2.2 app running in ruby 1.8.6 (upgrading isn't an option right now). Cucumber's been fine, now i'm trying to use Capybara. I've installed the capybara (1.1.1) gem and put the line require 'capybara/rails' in my features/support/env.rb file.
Now, when i run cucumber, i get this error:
Using the default profile...
uninitialized constant Rack::Builder (NameError)
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:445:in `load_missing_constant'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:77:in `const_missing'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/capybara-1.1.1/lib/capybara/rails.rb:4
/home/max/.rvm/rubies/ruby-1.8.6-p420/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `gem_original_require'
/home/max/.rvm/rubies/ruby-1.8.6-p420/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36:in `require'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:155:in `require'
/home/max/work/charanga/elearn_container/elearn/features/support/env.rb:10
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/rb_support/rb_language.rb:143:in `load'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/rb_support/rb_language.rb:143:in `load_code_file'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime/support_code.rb:171:in `load_file'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime/support_code.rb:83:in `load_files!'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime/support_code.rb:82:in `each'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime/support_code.rb:82:in `load_files!'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime.rb:137:in `load_step_definitions'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/runtime.rb:39:in `run!'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/cli/main.rb:43:in `execute!'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/../lib/cucumber/cli/main.rb:20:in `execute'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/cucumber-1.1.1/bin/cucumber:14
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/bin/cucumber:19:in `load'
/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/bin/cucumber:19
Here's the erroring file:
#/home/max/.rvm/gems/ruby-1.8.6-p420#elearning-resource/gems/capybara-1.1.1/lib/capybara/rails.rb
require 'capybara'
require 'capybara/dsl'
Capybara.app = Rack::Builder.new do
map "/" do
if Rails.version.to_f >= 3.0
run Rails.application
else # Rails 2
use Rails::Rack::Static
run ActionController::Dispatcher.new
end
end
end.to_app
Capybara.asset_root = Rails.root.join('public')
Capybara.save_and_open_page_path = Rails.root.join('tmp/capybara')
So, line 4 is creating the error with the Rack::Builder.new line. But, why? Any ideas? I have the Rack gem installed already.
thanks, max
Try adding require 'rack/builder' before the require 'capybara/rails'in features/support/env.rb. Rails versions lower than 2.3 don't use Rack internally and thus Rack::Builder will not be loaded like capybara seems to be assuming.
Did you use the cucumber-rails gem?
https://github.com/jnicklas/capybara says, either use the gem or, if your're not using rails, put both these lines in:
require 'capybara/cucumber'
Capybara.app = MyRackApp
try this out
gem install rack
require 'rack' # in features/support/env.rb before every require
Rack::Builder is defined in rack library.
I'm trying to install this as a plugin:
https://github.com/phatworx/rack_ip_restrictor
So I run:
$ rails plugin install git://github.com/phatworx/rack_ip_restrictor.git
This errors with:
/Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/railties-3.0.5/lib/rails/commands/plugin.rb:277:in `<top (required)>': Commands is not a module (TypeError)
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:239:in `require'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:239:in `block in require'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:225:in `block in load_dependency'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:596:in `new_constants_in'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:225:in `load_dependency'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:239:in `require'
from /Users/userme/.rvm/gems/ruby-1.9.2-p180#andyw/gems/railties-3.0.5/lib/rails/commands.rb:17:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Suggestions, ideas? Thanks
There's a solution out on GitHub - check the comments.
#acconrad is correct. the concrete solution is ( If you use rails 3.0.9- with rake 0.9.2, you should add include Rake::DSL to Rakefile just after require 'rake'.
Then add module Commands; end to script/rails just before require 'rails/commands', you will not get 'Commands is not a module (TypeError)' error message any more.) :
1.in Rakefile,
require File.expand_path('../config/application', __FILE__)
require 'rake'
# add this line of code
include Rake::DSL
2.in script/rails:
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
# add this line of code
module Commands; end
require 'rails/commands'
3.then run this command:
$ bundle exec rails plugin install git://github.com/sbecker/asset_packager.git
the plugin will be installed.
Have you tried with rails 3.0.10. It should work with 3.0.10 actually!
When I run:
ruby -I test test/unit/job_test.rb
from the application root directory, I got the following error:
.../app/models/name_position.rb:9:in `<class:NamePosition>':
uninitialized constant NamePosition::PositionManager (NameError)
from .../app/models/name_position.rb:1:in `<top (required)>'
from .../app/models/ac_buyer.rb:1:in `<top (required)>'
...
Here is the relevant code:
# app/models/ac_buyer.rb
class AcBuyer < NamePosition
end
# app/models/name_position.rb
class NamePosition < ActiveRecord::Base
...
include PositionManager
end
# lib/position_manager.rb
module PositionManager
...
end
It looks like when running tests, the files from the lib directory are not loaded automatically.
Any suggestions ?
Try putting this in your application.rb
config.autoload_paths += %W(#{config.root}/lib)