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

我开始使用Rspec,但是当我运行bundle exec rspec我收到一个错误

  /spec/requests/pages_spec.rb:20:in `block (2 levels) in ': undefined local variable or method `root_path' for # (NameError) 

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

未定义的局部变量或方法`root_path’(Rspec Spork Guard)

我在spec_helper.rb文件中添加了config.include Rails.application.routes.url_helpers ,但这没有帮助。 undefined局部变量或方法`root_path’Hartl的教程第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 

要保存结构 – 您可以像这样更改代码:

 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块中。 而且你的结构并不完美。 如果要避免重复,最好将代码放入模块然后包含它。

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

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