I am trying to run rspec only for Ruby (not Rails), for a simple Ruby file. I'm following Tut+ TDD Testing with Ruby.
I have a competition directory with a lib folder and spec folder.
├── lib
│ ├── competition.rb
│ └── team.rb
└── spec
└── competition_spec.rb
When I run rspec, I got this error. I could've sworn the rspec work before. I don't know what happened.
competition :> rspec spec
/Users/akh88/.rvm/gems/ruby-1.9.3-p547/gems/rspec-core-> 3.0.2/lib/rspec/core/formatters.rb:167:in `find_formatter': Formatter 'nested' unknown - maybe you meant 'documentation' or 'progress'?. (ArgumentError)
My competition_spec.rb
require_relative "../lib/competiiton.rb"
require_relative "../lib/team.rb"
describe Competition do
let(:competition) {Competition.new}
let(:team) {Team.new}
context "having no questions" do
before { competition.questions = [] }
it "doesn't accept any teams" do
expect do
team.enter_competition(competition)
end.to raise_error Competition::Closed
end
end
end
My rvm default Ruby version is 1.9.1 on Mac OSX 10.9.4.
The nested formatter was used in RSpec 1. This was renamed documentation in RSpec 2.
Maybe you have specified nested on the command line or in a .rspec file? Then you need to specify --format documentation instead.
Have you set config.formatter = nested somewhere, probably your spec_helper.rb file? Remove it.
You could have updated the RSpec gem from v1 (the command to run tests changed from spec to rspec though so that's hard to miss). You can check versions with gem list rspec.
Alternatively, you could be missing the load of a custom formatter you happened to call nested.
My .rspec file only had
--color
and I was still getting this error.
I explicitly set it to
--format documentation --color
And now it works.
Related
I was learning about the gem Rspec through a tutorial when this error came up.The last thing I typed in was
$ rspec spec spec\hello_world_spec.rb
I had only installed the Rspec gem and nothing else.
the output message from the cmd
Try to get rid of spec
rspec spec\hello_world_spec.rb
You're passing spec and spec\hello_world_spec.rb as arguments to rspec. These are interpreted as files to run, or directories to search through for files to run. Since you're already running in the spec\ directory, rspec is looking for spec\spec\ and spec\spec\hello_world_spec.rb, which don't exist. Try running that from one directory up (in a typical ruby project, the "root" of your project) and it should run.
i.e. Instead of:
\rspec_tutorial\spec>rspec spec spec\hello_world_spec.rb
try:
\rspec_tutorial>rspec spec spec\hello_world_spec.rb
Also, as #Ursus points out, running rspec spec spec\hello_world_spec.rb is redundant. Rspec will search through spec\ for files to run and will run hello_world_spec.rb automatically since it's under spec. If you only want to run hello_world_spec.rb–which seems to be your intent–then drop the spec from the command, per #Ursus' answer.
I'm working on a Ruby gem and I'm getting an odd error. I have previously released this gem without too much trouble. I added some methods / refactored some code and wanted to release a subsequent version (from 1.1 to 1.2).
For reference, the name of the gem is Intervallum, (the word 'interval' in Latin).
I'm getting a 'require' error that's been stumping me.
The folder tree is:
.
├── Gemfile
├── LICENSE
├── README.md
├── intervallum-[version].gem
├── intervallum.gemspec
└── lib
├── intervallum
│ ├── module.scroll.rb
│ └── module.spell.rb
└── intervallum.rb
In lib/intervallum.rb I tried Dir.glob, Dir['./lib/intervallum/*'] and require '../intervallum/lib/intervallum/module.spell.rb' and what happens for each one is:
Locally, after gem build intervallum.gemspec and gem install intervallum-[version].gem, I boot up irb and require intervallum and it works fine.
push to RubyGems
remove the local copy
install from RG
load up in irb I get load errors or it cannot find class of a helper class
I'm not sure why this keeps occurring, or if there's something that I'm missing as to why this keeps occurring but any advice would be much appreciated.
The problem is that you are not including those files in the gem when it gets packaged. Your gemspec specifies that only the lib/intervallum.rb file will be included in the gem:
s.files = ["./lib/intervallum.rb"]
Change that line to include all files in lib. It's also a good idea to include the gemspec.
s.files = Dir['lib/**/*', 'intervallum.gemspec']
I have a gem project with the following structure:
foo-bar
├── lib
│ └── foo
│ ├── bar
│ │ └── qux.rb
│ └── bar.rb
└── spec
├── spec_helper.rb
└── unit
├── baz_spec.rb
└── qux_spec.rb
In lib/foo, bar.rb defines a module Foo::Bar, and inside that, a class Foo::Bar::Baz. Inside lib/foo/bar, qux.rb defines a class Foo::Bar::Qux.
spec_helper.rb sets up RSpec and Simplecov, and finishes with require 'foo/bar'. Both baz_spec.rb and qux_spec.rb start with require 'spec_helper'.
baz_spec.rb has the specs for Foo::Bar::Baz, and it works fine. qux_spec.rb, however, which has the specs for Foo::Bar::Qux, fails with:
/Users/me/foo-bar/spec/unit/qux_spec.rb:6:in `<module:Bar>': uninitialized constant Foo::Bar::Qux (NameError)
from /Users/me/foo-bar/spec/unit/qux_spec.rb:4:in `<module:Foo>'
from /Users/me/foo-bar/spec/unit/qux_spec.rb:3:in `<top (required)>'
from /Users/me/.rvm/gems/ruby-2.2.0/gems/rspec-core-3.2.2/lib/rspec/core/configuration.rb:1226:in `load'
...
(etc.)
I've verified that it's not just a typo by moving the code for Foo::Bar::Baz out of lib/foo/bar.rb and into its own file, lib/foo/bar/baz.rb, after which baz_spec.rb also stops working.
It also doesn't seem to make a difference whether I declare the class as
class Foo::Bar::Qux
...
or as
module Foo
module Bar
class Qux
...
I'm using Ruby 2.2.0 with RSpec 3.2.2 on Mac OS X Yosemite.
Clearly there's something wrong with my requires, but as a Ruby novice I'm not seeing it. Any ideas?
you need to add foo.rb file under ./lib and add require statements for each file in order you want them to get loaded. You can look at sample gem for reference: dogeify and an article that walks you through gem creation build your first gem.
If you're using ActiveSupport a single line like this will help you:
ActiveSupport::Dependencies.autoload_paths << "./lib"
If you're now trying to use Foo::Bar::Qux, ActiveSupport will look for a file named foo/bar/qux.rb inside of the lib folder.
Solved: after taking a closer look at the other projects I was cargo-culting from, I realized I'd misunderstood require.
Unlike (apparently) its Rails equivalent, the out-of-the-box Kernel.require just loads .rb files (and extension libraries). So in the example above, require 'foo/bar' doesn't load files from the foo/bar directory, it just loads foo/bar.rb.
In order to load the files under foo/bar, including qux.rb, I had to go into bar.rb and explicitly load those files at the top of the module declaration:
module Foo
module Bar
Dir.glob(File.expand_path('../bar/*.rb', __FILE__), &method(:require))
# ...module declaration continues...
Just one of the many scripting-language-heritage pitfalls waiting for those who come to Ruby from other more heavyweight languages, I suppose.
Ruby Settings From terminal
% ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux]
=> ~/ruby/grounded/test
% where ruby
/home/mike/.rvm/rubies/ruby-1.9.2-p180/bin/ruby
/home/mike/.rvm/bin/ruby
/usr/local/bin/ruby
/usr/bin/ruby
=> ~/ruby/grounded/Person/test
% which ruby
/home/mike/.rvm/rubies/ruby-1.9.2-p180/bin/ruby
% rvm current
ruby-1.9.2-p180
Directory Structure
% tree
.
├── bowling.rb
└── bowling_spec.rb
File Contents
bowling.rb
class Bowling
end
bowling_spec.rb
require 'rubygems'
require 'rspec'
require 'bowling'
describe Bowling, "#score" do
it "returns 0 for all gutter game" do
bowling = Bowling.new
20.times { bowling.hit(0) }
bowling.score.should eq(0)
end
end
% ruby bowling_spec.rb
/home/mike/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': no such file to load -- bowling (LoadError)
from /home/mike/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from bowling_spec.rb:3:in `<main>'
Questions
Why am I getting a LoadError when bowling.rb and bowling_spec.rb
are in the same folder?
In the error what the heck is .../site_ruby/1.9.1/... when I am running ruby 1.9.2 then why would 1.9.1 even show up?
how do I get over this hump and start having fun with ruby.
When requiring files, the file must be in a list of directories called the $LOAD_PATH. The current directory used to be in this list, but as of 1.9.2, it has been removed for security reasons.
You have four options (listed in order of how good I think they are)
1 Change your directory structure to look like this
.
|-- lib
| `-- bowling.rb
`-- spec
`-- bowling_spec.rb
And then run as rspec spec instead of ruby bowling_spec.rb
This works because RSpec will see that lib is in your current directory, and then add it to the $LOAD_PATH for you.
If you do this, you also don't have to require 'rspec'.
2 Run with ruby -I . bowling_spec.rb
which will add the current directory to the $LOAD_PATH
3 Use require_relative 'bowling' instead of require 'bowling'.
This will look for the bowling.rb file relative to the current file being run (bowling_spec.rb)
4 Use require('../bowling', __FILE__) instead of require 'bowling'
This is basically the same as the above.
Other questions:
Q: Why am I getting a LoadError when bowling.rb and bowling_spec.rb are in the same folder?
A: Because the current directory (the directory you are running the script from, not the directory the files are located in) is not in the $LOAD_PATH.
Q: In the error what the heck is .../site_ruby/1.9.1/... when I am running ruby 1.9.2 then why would 1.9.1 even show up?
A: Hmm. Not sure I remember exactly, but IIRC, it was something like they're so similar that the interface hadn't changed, so they could be compatible with 1.9.1 from a system perspective.
Q: how do I get over this hump and start having fun with ruby.
A: I suppose that depends. If the issue is that you want to be able to run files that are in your CWD, then you can add the environment variable RUBYLIB to . to your .bash_profile (or whatever the equivalent is on your system) which will tell Ruby to look in the current directory for files. This is prone to bugs, though (and it could lead to unintentional execution of Ruby files, which is a security risk). If you just mean "how do I start learning" or whats a fun project? Then check out one of my projects, Ruby Kickstart which, in six sessions, will take you through a pretty big portion of Ruby, and have you write and deploy a simple web app by the end of it.
When you require a file and don't specify an absolutely path to the file, Ruby looks on its load path (accessed within ruby as $LOAD_PATH or $:) and checks each directory there for the file you want. You cannot load bowling.rb because it's not in a directory on your load path.
The solution is one of two things:
Put the current directory on the load path:
$:.unshift File.expand_path('.')
This puts the full path to the current working directory on the load path.
Use require with the absolute path to the file:
require File.expand_path('../bowling', __FILE__)
A little additional info: File.expand_path returns the absolute path to the first parameter from the current working directory, unless a second parameter is given; then it uses that as the starting point. So the whole line could be read:
require /home/mike/src/something/bowling_spec.rb/../bowling
I'm after an overview/clarification of the ideal project structure for a ruby (non-rails/merb/etc) project. I'm guessing it follows
app/
bin/ #Files for command-line execution
lib/
appname.rb
appname/ #Classes and so on
Rakefile #Running tests
README
test,spec,features/ #Whichever means of testing you go for
appname.gemspec #If it's a gem
Have I got something wrong? What parts have I missed out?
I think that is pretty much spot on. By default, Rubygems will add the lib directory to the loadpath, but you can push any directory you want onto that using the $: variable. i.e.
$:.push File.expand_path(File.dirname(__FILE__) + '/../surfcompstuff')
That means when you have say, surfer.rb in that dir, you can require "surfer" anywhere and the file will be found.
Also, as a convention, classes and singletons get a file and modules get a directory. For instance, if you had the LolCatz module and the LolCatz::Moar class that would look like:
lib/
appname.rb
lolcatz/
moar.rb
That is why there is an lib/appname folder because most libraries are in the appname namespace.
Additionally, if you try running the command newgem --simple [projectname] that'll quickly generate a scaffold for you with just the bare essentials for a Ruby project (and by extension a Ruby Gem). There are other tools which do this, I know, but newgem is pretty common. I usually get rid of the TODO file and all the script stuff.
See the following example from http://guides.rubygems.org/what-is-a-gem/
% tree freewill
freewill/
├── bin/
│ └── freewill
├── lib/
│ └── freewill.rb
├── test/
│ └── test_freewill.rb
├── README
├── Rakefile
└── freewill.gemspec
I attempt to mimic the Rails project structure because my team, which usually deals with Rails, will understand the structure better than another configuration. Convention over Configuration - bleeding over from Rails.
If you use bundler, running this command bundle gem app_name will give you the same directory structure.
If you want to use rspec instead of unit tests you can then run this command rspec --init
(Just make sure you cd app_name first)