问题
I set up my guard-rspec environment using the techniques described in this tutorial. I'm also practicing namespacing as described in Programing Ruby starting on page 240. My current project directory is on github in the stack-overflow-post branch.
I'm using:
❯ ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin15.0]
❯ rbenv -v
rbenv 1.0.0
❯ rbenv versions
system
* 2.1.1 (set by /Users/max/Google Drive/devbootcamp/phase-0-ruby-bulletin-board/.ruby-version)
2.1.5
2.2.3
2.3.1
❯ bundle exec guard -v
Guard version 2.3.0
I'm running a test in spec/thread_spec.rb:
require 'spec_helper'
describe 'RubyBulletinBoard::Thread' do
let (:thread) { RubyBulletinBoard::Thread.new }
it { expect(thread).to be_kind_of(RubyBulletinBoard::Thread) }
# it 'has a valid uuid' do
# p thread.uuid
# expect(thread.uuid).to be_kind_of(String)
# end
# it 'has editable title' do
# default_title = thread.title
# thread.title = "#{default_title} something different"
# new_title = thread.title
# expect(default_title == new_title).to eq(false)
# end
end
However it's failing:
01:50:07 - INFO - Running: ./spec/thread_spec.rb:5
Run options: include {:locations=>{"./spec/thread_spec.rb"=>[5]}}
RubyBulletinBoard::Thread
example at ./spec/thread_spec.rb:5 (FAILED - 1)
Failures:
1) RubyBulletinBoard::Thread
Failure/Error: let (:thread) { RubyBulletinBoard::Thread.new }
NameError:
uninitialized constant RubyBulletinBoard::Thread
# ./spec/thread_spec.rb:4:in `block (2 levels) in <top (required)>'
# ./spec/thread_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.00055 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/thread_spec.rb:5 # RubyBulletinBoard::Thread
[1] guard(main)>
But I have no idea why because the class RubyBulletinBoard::Thread does exist in lib/ruby_bulletin_board/thread.rb:
require_relative 'id'
module RubyBulletinBoard
class Thread
attr_reader :uuid
attr_accessor :title
def initialize
@uuid = IdCreator.create_id
@title = title
end
end
end
Even weirder, when I uncomment line 2 in lib/ruby_bulletin_board/runner.rb the test passes:
require_relative 'example'
# require_relative 'thread' # <--- THIS IS LINE 2
module RubyBulletinBoard
class Runner
attr_accessor :greeter, :thread
def initialize
@greeter = RSpecGreeter.new
# @thread = RubyBulletinBoard::Thread.new
end
def run
greeter.greet
# p @thread.class
end
end
end
rspec output:
01:53:57 - INFO - Running: ./spec/thread_spec.rb:5
Run options: include {:locations=>{"./spec/thread_spec.rb"=>[5]}}
RubyBulletinBoard::Thread
should be a kind of RubyBulletinBoard::Thread
Finished in 0.00114 seconds
1 example, 0 failures
[1] guard(main)>
It seems to me that including requiring thread.rb in runner.rb would have nothing to do with my tests.
- Why is my original test in
spec/thread_spec.rbfailing? - Why does uncommenting line 2 in
lib/runner.rbcause the test to pass?
Thanks for your help :)
Edit:
The accepted answer helped me get things up and running, more questions can be found in another post
Edit 2:
Also just made a big discovery: I've been using a file named thread.rb, there is a ruby class named Thread, so when I've been saying require 'thread' in my thread_spec.rb it's been giving me errors:
[1] guard(main)>
17:57:09 - INFO - Running: spec/thread_spec.rb
/Users/max/Google Drive/devbootcamp/phase-0-ruby-bulletin-board/spec/thread_spec.rb:4:in `<top (required)>': uninitialized constant RubyBulletinBoard (NameError)
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1361:in `load'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1361:in `block in load_spec_files'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1359:in `each'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1359:in `load_spec_files'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:106:in `setup'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:92:in `run'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:78:in `run'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:45:in `invoke'
from /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/exe/rspec:4:in `<top (required)>'
from bin/rspec:17:in `load'
from bin/rspec:17:in `<main>'
17:57:10 - ERROR - Failed: "bin/rspec -f progress -r /Users/max/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/guard-rspec-4.7.2/lib/guard/rspec_formatter.rb -f Guard::RSpecFormatter --failure-exit-code 2 spec/thread_spec.rb" (exit code: 1)
by renaming thread.rb -> rbb_thread.rb I can then require 'rbb_thread' and I'm going red to green :)
Edit 3:
Another solution for the errors with thread.rb is to require_relative ../lib/thread and so no rename is required
回答1:
A few things here:
When you're running specs, you're running RSpec like an application and it's "config" is in spec/spec_helper.rb. I'll assume it's empty/irrelevant.
If you're running a more recent version of RSpec, you can just place
--require spec_helperin your.rspecfile and you won't need therequire "spec_helper"in your files.It's best to use
RSpec.describeinstead of plaindescribethe first time in a file.You can use a
subjectblock for more readability along withdescribed_class. It also lets you useit { is.expected_tosyntaxdescribecan take a class name instead of a string. This way it makes it obvious if you've required the file or not. If you pass a class, thensubjectbecomes implicit.
Since RSpec is like a separate app, it doesn't include your own library files by default (newer versions of RSpec do add lib to LOAD_PATH). So your tests have to individually require any files they test, e.g.
require 'spec_helper'
describe 'RubyBulletinBoard::Thread' do
let (:thread) { RubyBulletinBoard::Thread.new }
it { expect(thread).to be_kind_of(RubyBulletinBoard::Thread) }
becomes:
require 'ruby_bulletin_board/thread'
RSpec.describe RubyBulletinBoard::Thread do
it { is_expected.to be_kind_of(RubyBulletinBoard::Thread) }
If the above require fails, it means you need to put lib in your load path. Check your spec/spec_helper.rb if that's the case.
If your spec/spec_helper.rb is empty (or doesn't have anything important), you may want remove it along with .rspec and run rspec --init to generate a good started template for you. Be sure you uncomment the =begin and =end sections there.
来源:https://stackoverflow.com/questions/37640135/why-is-my-guard-rspec-test-failing