Why is my guard-rspec test failing?

百般思念 提交于 2019-12-12 02:35:29

问题


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.

  1. Why is my original test in spec/thread_spec.rb failing?
  2. Why does uncommenting line 2 in lib/runner.rb cause 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:

  1. 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.

  2. If you're running a more recent version of RSpec, you can just place --require spec_helper in your .rspec file and you won't need the require "spec_helper" in your files.

  3. It's best to use RSpec.describe instead of plain describe the first time in a file.

  4. You can use a subject block for more readability along with described_class. It also lets you use it { is.expected_to syntax

  5. describe can 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, then subject becomes 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!