I'm finally getting around to learning Ruby using Programming Ruby 1.9. I have installed Ruby using Brew on OS X and it installed Ruby 2.0.
Most of the exercises have worked fine in Eclipse, but when I got to the first example that creates a unit test I started running into trouble.
In Eclipse, I created a test case like:
require_relative 'WordsFromString'
require 'minitest/autorun'
class TestWordsFromString < Test::Unit::TestCase
...
end
When I run it as a Ruby Test, I get the following output:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- test/unit/ui/console/testrunner (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Applications/Eclipse.app/Contents/Eclipse/configuration/org.eclipse.osgi/1276/0/.cp/testing/dltk-testunit-runner.rb:1:in `<top (required)>'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
I think there might be something wrong with my basic Ruby installation because if I try and run it from the command line I get:
Asok:work_freq jeff$ ruby TestWordsFromString.rb
TestWordsFromString.rb:4:in `<main>': uninitialized constant Test (NameError)
EDIT: With the help of Ursus I have figured out that as long as the require and base class are consistent the command line works.
So either of the following allow the command-line to successfully execute the test case.
require 'minitest/autorun'
class TestWordsFromString < MiniTest::Unit::TestCase
or
require 'test/unit'
class TestWordsFromString < Test::Unit::TestCase
So now I just need to get this working inside Eclipse.
Try
class TestWordsFromString < Minitest::Test
In searching around for a answer, I came across this Ruby issue
that seems to be relevant. Since I'm new to Ruby I'm not sure I fully understood it, but what I got out of it was that there was an unexpected behavior related to installing the gem test-unit that existed in Ruby 1.9. I hadn't installed any gems, so I tried:
gem install test-unit
after which the unit test executed successfully in Eclipse and on the command-line.
Related
TL;DR
I'm trying to load a gem from the Ruby Standard Library from inside a bundle, but am unable to do it when the REPL is invoked with bundle exec. However, it works when the REPL is invoked outside the bundle, and then Bundler required later. This makes testing of gems/apps that leverage require 'bundler/setup' difficult, especially since I don't want to interfere with the remaining test suites if I'm excluding the :development group from the Bundler install.
This is possibly an X/Y problem, but the goal is to exclude the :development group for a single test suite within a larger group of tests. I've outlined what I've tried, what doesn't work, what does, and why what sort-of works feels wrong to me. The underlying question is really about testing whether gem groups have interdependencies that aren't obvious without tests.
My Problem
I'm trying to run a unit test that validates that an application runs normally without gems defined in its Gemfile's :development group, one item of which is Minitest. The relevant section of the Gemfile currently says:
group :development do
gem "minitest"
gem "minitest-reporters"
gem "minitest-shared_description"
gem "minitest-stub_any_instance"
gem "rake"
gem "rubocop"
end
In order to perform this validation, I'm attempting to load 'test/unit' rather than Minitest from outside the bundle for a single test file since, according to the Bundler documentation, it should be available from the Ruby Standard Library even if not explicitly declared in the Gemfile. For example:
# install the bundle without the :development group
bundle install --without development
bundle exec irb
require 'test/unit'
Bundler.setup :default
However, this raises a LoadError exception as follows:
irb(main):001:0> require 'test/unit'
Traceback (most recent call last):
16: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/exe/bundle:48:in `block in <top (required)>'
15: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli.rb:25:in `start'
14: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
13: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli.rb:31:in `dispatch'
12: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
11: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
10: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
9: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli.rb:484:in `exec'
8: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli/exec.rb:23:in `run'
7: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli/exec.rb:58:in `kernel_load'
6: from /Users/foo/.gem/ruby/2.7.5/gems/bundler-2.3.7/lib/bundler/cli/exec.rb:58:in `load'
5: from /Users/foo/.rubies/ruby-2.7.5/bin/irb:23:in `<top (required)>'
4: from /Users/foo/.rubies/ruby-2.7.5/bin/irb:23:in `load'
3: from /Users/foo/.rubies/ruby-2.7.5/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
2: from (irb):1
1: from (irb):1:in `require'
LoadError (cannot load such file -- test/unit)
I get similar issues with Ruby 3.1.0, so it doesn't seem to be specific to a given RUBY_VERSION. I'm also using the latest version of Bundler, which is currently 2.3.7.
Bundler Documentation
The documentation for Bundler#setup currently says:
setup(*groups) click to toggle source
Turns on the Bundler runtime. After Bundler.setup call, all load or require of the gems would be allowed only if they are part of the Gemfile or Ruby’s standard library. If the versions specified in Gemfile, only those versions would be loaded.
To me, this seems to mean that I should be able to call require 'test/unit' even after I've required all the gems in the default group with Bundler.setup :default. However, this clearly doesn't work.
What Works, But I'm Unsure Why
As a work-around, I tried loading my irb session from outside the bundle, and then requiring gems from outside the bundle before calling Bundler#setup or Bundler#require. This seems to work:
# note the lack of `bundle exec` when calling irb
irb
require 'test/unit'
#=> true
require 'bundler'
Bundler.require :default
defined? Test::Unit
#=> "constant"
While this seems like an acceptable work-around, I'm not sure I understand why this problem exists. Since irb itself is not defined in the bundle, why doesn't bundle exec irb fail if it's not allowed to call global gems? More importantly, why would bundle exec (which simply calls a gem's executable within the bundle) prevent the loading of global gems?
My educated guess is that bundle exec irb executes an implicit set of require statements after invoking the irb executable, such as:
require 'bundler'
require 'bundler/setup'
which would then preclude the loading of libraries from outside the bundle. I know I could call Bundler.reset!, but that might impact other tests in the test suite that rely on Minitest. The next section explains why I think that.
What Potentially Breaks Other Tests
The following also works, but is likely to break other test suites:
# after using `bundle install --with development`
Bundler.with_unbundled_env do
Bundler.reset!
require 'test/unit'
Bundler.require :default
end
defined? Test::Unit
#=> "constant"
defined? MiniTest
#=> nil
Bundler.require :development
defined? MiniTest
#=> "constant"
This seems problematic because I suspect I now have Test::Unit in scope throughout all my test suites, and might have to wrap the entire suite above in a block with an ensure clause so that a failing test here doesn't break the rest of the test suites if the test runner fails to restore the :development group environment. In other words, my current solution just feels wrong, but is the best I have come up with so far.
The Search for a Better Solution, Summarized
Is there a better way to do what I'm trying to do, perhaps by using refinements or otherwise unloading Minitest for a single test (or group of tests) within a larger test suite? I'm really just trying to validate that none of the :development group gems are note actually required by the :default group for the gem to function properly.
The question has broader applicability than just to the question of Test::Unit and MiniTest. That just happens to be the example I'm currently working with, so please don't focus over-much on the specific gems in question. The underlying question is really about testing whether gem groups have interdependencies.
I'm learning Ruby from "Beginning Ruby from Novice to Professional" by Peter Cooper. I am on Chapter 7. I have ruby 2.0 installed. I am facing this error:
C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- 2.0/redcloth_scan (LoadError)
When trying to run this code:
require 'rubygems'
require 'RedCloth'
r = RedCloth.new("This is a *test* of _using RedCloth_")
puts r.to_html
I'm getting this result:
ruby redcloth.rb
C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- 2.0/redcloth_scan (LoadError)
Couldn't load 2.0/redcloth_scan
The $LOAD_PATH was:
C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/lib
C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/lib/case_sensitive_require
C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/ext
C:/Ruby200/lib/ruby/site_ruby/2.0.0
C:/Ruby200/lib/ruby/site_ruby/2.0.0/i386-msvcrt
C:/Ruby200/lib/ruby/site_ruby
C:/Ruby200/lib/ruby/vendor_ruby/2.0.0
C:/Ruby200/lib/ruby/vendor_ruby/2.0.0/i386-msvcrt
C:/Ruby200/lib/ruby/vendor_ruby
C:/Ruby200/lib/ruby/2.0.0
C:/Ruby200/lib/ruby/2.0.0/i386-mingw32
from C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/lib/RedCloth.rb:13:in `<top (required)>'
from C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:135:in `require'
from C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:135:in `rescue in require'
from C:/Ruby200/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:144:in `require'
from redcloth.rb:2:in `<main>'
Exit code: 1
I already installed ruby gems and RedCloth. They didn't give me an errors. If somebody could shed some light on this topic it would be greatly appreciated.
try this:
goto into C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/lib
and create a dir named '2.0'.
Then copy redcloth_scan.so from 'C:/Ruby200/lib/ruby/gems/2.0.0/gems/RedCloth-4.2.9-x86-mingw32/lib' into '2.0' dir.
I installed in past RedCloth with Ruby 1.9.1.
Actually I suspect that RedCloth doesn't work with Ruby 2.0.
On ruby 2.x.x you need to compile the gem.
For example for the windows ruby 2.2.4:
Setup the DevKit (https://github.com/oneclick/rubyinstaller/wiki/Development-Kit)
Run into command window:
gem install RedCloth --platform=ruby
Goto to your installed RedCloth path
lib\ruby\gems\2.2.0\gems\RedCloth-4.2.9\lib
Create there a new directory called "2.2" and copy the file redcloth_scan.so on it.
If you use the gem RedCloth-4.2.9-x86-mingw32, the redcloth_scan.so contains the ruby 1.9 dependency and it doesn't works with ruby 2.2.4.
I am sure this is a simple issue but since I have looked so long I cannot see it. So I am running ruby 1.9.3 with Sinatra, sqlite3, datamapper, dm-sqlite-adapter. When I try to run Sinatra, I get this:
/Users/XXX/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- datamapper (LoadError)
from /Users/XXX/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from app.rb:2:in `<main>'
Here are the first two lines:
require 'sinatra'
require 'datamapper'
The gem is installed. (datamapper (1.2.0))
You need to require data_mapper, not datamapper (note the underscore):
require 'data_mapper'
See the DataMapper getting started page.
This is my first program :
require 'rubygems'
require 'watir'
ie = Watir::IE.new
ie.goto("http://www.google.com")
ie.text_field(:name, "question").set("microsoft")
ie.button(:name, "btnG").click
When I run it,I get the following error, could you please help. I have installed watir-webdriver before running this
C:/Ruby200/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require': cannot load such file -- watir (LoadError)
from C:/Ruby200/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
from C:/Ruby200/lib/ruby/site_ruby/2.0.0/rubygems/FirstSample:2:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
Process finished with exit code 1
My guess is that the problem is caused by the fact that you have installed watir-webdriver gem but you are requiring watir gem.
Either install watir gem or require watir-webdriver gem in your code.
I've just replied to your other question with a sample project and instructions regarding DevKit installation.
Note that RubyMine needs a valid Gemfile to manage dependencies. All the gems that you are using should be specified in that file. bundle install should install the dependencies without errors.
If you have errors installing gems, post it as a separate question with more details, but before doing it verify that DevKit was installed properly and can build/run the sample gem from the installation guide.
Some gems may be not fully compatible with the recently released Ruby 2.0 version. If you have no luck getting it to work, try Ruby 1.9.3 instead.
I used Bundler to generate a Gem skeleton for me. Within lib/foo.rb, I have the following:
require 'foo/client'
require 'foo/other'
Those two lines are supposed to require lib/foo/client.rb and lib/foo/other.rb, respectively. It builds without a problem, but when I go to test it with irb, I get a file not found error.
ruby-1.9.2-head :003 > require 'foo'
LoadError: no such file to load -- foo/client
from /home/ethan/.rvm/rubies/ruby-1.9.2-head/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /home/ethan/.rvm/rubies/ruby-1.9.2-head/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /home/ethan/.rvm/gems/ruby-1.9.2-head/gems/foo-0.1.0/lib/foo.rb:3:in `<top (required)>'
from /home/ethan/.rvm/rubies/ruby-1.9.2-head/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /home/ethan/.rvm/rubies/ruby-1.9.2-head/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from (irb):3
from /home/ethan/.rvm/rubies/ruby-1.9.2-head/bin/irb:16:in `<main>'
ruby-1.9.2-head :004 >
What is the correct way to require files within the same Gem? There must be something simple that I'm overseeing...
If your gem is called 'foo', then all you need to do is use bundle exec:
bundle exec your-script.rb
Without bundle exec, the load paths are not set up correctly.
Using irb, you use the bundle command bundle console.
chris#chris:~/oss/pp-adaptive$ irb
irb(main):001:0> AdaptivePayments
NameError: uninitialized constant Object::AdaptivePayments
from (irb):1
from /home/chris/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'
irb(main):002:0>
chris#chris:~/oss/pp-adaptive$ bundle console
irb(main):001:0> AdaptivePayments
=> AdaptivePayments
irb(main):002:0>
Note that once the gem is installed on your system, you may use it without bundler.
The current directory is not in the load path in Ruby 1.9. Try one of these:
require './client'
or
require_relative 'client'
If you are in IRB itself you may have to
require "rubygems"
require "foo"
if the library is a gem. Alternatively you can require the full path of the gem, but I wouldn't advise it since rubygems does require magic so reload! works in irb ( at least it does for rails console ).