Rspec未定义的局部变量或方法root_path

时间:2014-01-18 22:51:41

标签: ruby-on-rails rspec ruby-on-rails-4 urlhelper

我开始使用Rspec,但是当我运行bundle exec rspec时出现错误

 /spec/requests/pages_spec.rb:20:in `block (2 levels) in <top (required)>': undefined local
 variable or method `root_path' for #<Class:0x00000102e46850> (NameError)

我没有运行Spork或Guard,所以下面的问题不适用

undefined local variable or method `root_path' (Rspec Spork Guard)

我在config.include Rails.application.routes.url_helpers文件中添加了spec_helper.rb,但这没有帮助。 undefined local variable or method `root_path' Hartl's Tutorial Chapter 5.3.2

这是pages_spec.rb

require 'spec_helper'                                                                                                                                                       

describe "Pages" do                                                                                                                                                         
  describe "navigation" do                                                                                                                                                  

    def self.it_should_be_on(path_name, value=nil)                                                                                                                          
      before { visit path_name }                                                                                                                                            

      it "should be on #{path_name}" do                                                                                                                                     
        page.should have_link('Home')                                                                                                                                       
        page.should have_link('Inventory')                                                                                                                                  
        page.should have_link('FAQ')                                                                                                                                        
        page.should have_link('About Us')                                                                                                                                   
        page.should have_link('Location')                                                                                                                                   
        page.should have_link('Contact Us')                                                                                                                                 
        # page.should have_link('Login')                                                                                                                                    
      end                                                                                                                                                                   
    end                                                                                                                                                                     

    it_should_be_on root_path                                                                                                                                               
    it_should_be_on faq_path                                                                                                                                                
    it_should_be_on about_path                                                                                                                                              
    it_should_be_on location_path                                                                                                                                           
    it_should_be_on contact_path                                                                                                                                            
    # it_should_be_on login_path                                                                                                                                            
  end                                                                                                                                                                       
end       

spec_helper.rb

# This file is copied to spec/ when you run 'rails generate rspec:install'                                                                                                  
ENV["RAILS_ENV"] ||= 'test'                                                                                                                                                 
require File.expand_path("../../config/environment", __FILE__)                                                                                                              
require 'rspec/rails'                                                                                                                                                       
require 'rspec/autorun'                                                                                                                                                     
# Requires supporting ruby files with custom matchers and macros, etc,                                                                                                      
# in spec/support/ and its subdirectories.                                                                                                                                  
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }                                                                                                         

# Checks for pending migrations before tests are run.                                                                                                                       
# If you are not using ActiveRecord, you can remove this line.                                                                                                              
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)                                                                                                 

RSpec.configure do |config|                                                                                                                                                 
  # ## Mock Framework                                                                                                                                                       
  #                                                                                                                                                                         
  # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:                                                                                             
  #                                                                                                                                                                         
  # config.mock_with :mocha                                                                                                                                                 
  # config.mock_with :flexmock                                                                                                                                              
  # config.mock_with :rr                                                                                                                                                    

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures                                                                                              
  config.fixture_path = "#{::Rails.root}/spec/fixtures"                                                                                                                     

  # If you're not using ActiveRecord, or you'd prefer not to run each of your                                                                                               
  # examples within a transaction, remove the following line or assign false                                                                                                
  # instead of true.                                                                                                                                                        
  config.use_transactional_fixtures = true                                                                                                                                  

  # If true, the base class of anonymous controllers will be inferred                                                                                                       
  # automatically. This will be the default behavior in future versions of                                                                                                  
  # rspec-rails.                                                                                                                                                            
  config.infer_base_class_for_anonymous_controllers = false                                                                                                                 

  # Run specs in random order to surface order dependencies. If you find an                                                                                                 
  # order dependency and want to debug it, you can fix the order by providing                                                                                               
  # the seed, which is printed after each run.                                                                                                                              
  #     --seed 1234                                                                                                                                                         
  config.order = "random"                                                                                                                                                   
  config.include Capybara::DSL                                                                                                                                              
  config.include Rails.application.routes.url_helpers                                                                                                                       
end                                              

更新 在阅读了shared_examples之后,我成功地尝试了这一点。有没有更好的方法来编写这个测试?我最终将页面分成了主页等单独的页面。

require 'spec_helper'                                                               

describe "Pages" do                                                                 

  subject { page }                                                                  

  shared_examples "navigation" do |path_name|                                       
    before { visit send( path_name) }                                               

    describe "navigation links should be on #{path_name}" do                        

      it { should have_link('Home') }                                               
      it { should have_link('Inventory') }                                          
      it { should have_link('FAQ') }                                                
      it { should have_link('About Us') }                                           
      it { should have_link('Location') }                                           
      it { should have_link('Contact Us') }                                         
      # it { should have_link('Login') }                                            
    end                                                                             
  end                                                                               

  describe "Home Page" do                                                           
    include_examples "navigation", :root_path                                       
  end                                                                               
end            

2 个答案:

答案 0 :(得分:5)

在RSpec的describe块的顶层,没有任何Rails助手可用。它们仅在较低级别的区块中可用(例如letbeforeit等。)

如果您希望在示例之间共享此类代码,可以使用shared_context或shared_example,如RSpec文档中所述,或者在describe级别切换到使用符号作为参数并推迟解释它们作为方法,直到你在较低级别的区块内,如the answer from @IharDrozdov

所示

答案 1 :(得分:1)

要保存结构 - 您可以更改以下代码:

require 'spec_helper'                                                                                                                                                       

describe "Pages" do                                                                                                                                                         
  describe "navigation" do                                                                                                                                                  

    shared_examples_for 'main page' do |path_name|                                                                                                                         
      before { visit send(path_name) }                                                                                                                                            

      it "should be on #{path_name}" do                                                                                                                                     
        page.should have_link('Home')                                                                                                                                       
        page.should have_link('Inventory')                                                                                                                                  
        page.should have_link('FAQ')                                                                                                                                        
        page.should have_link('About Us')                                                                                                                                   
        page.should have_link('Location')                                                                                                                                   
        page.should have_link('Contact Us')                                                                                                                                 
        # page.should have_link('Login')                                                                                                                                    
      end                                                                                                                                                                   
    end                                                                                                                                                                     

    it_should_behave_like 'main_page', :root_path                                                                                                                                               
    it_should_behave_like 'main_page', :faq_path                                                                                                                                                
    it_should_behave_like 'main_page', :about_path                                                                                                                                              
    it_should_behave_like 'main_page', :location_path                                                                                                                                           
    it_should_behave_like 'main_page', :contact_path                                                                                                                                            
    # it_should_behave_like 'main_page', :login_path                                                                                                                                            
  end                                                                                                                                                                       
end    

因为“路径未在规范中的类级别定义”(c) 您不能在spec类中调用路径方法。它应该在it块中。 而你的结构并不完美。如果你想避免重复,最好把代码放在模块中然后包含它。