在 Rails 中使用 RSpec 和 Capybara 时,未定义的方法“访问”

我不能让水豚使用 Rspec 它给了我这个错误:

undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>

我知道有很多关于这个的帖子,但是没有一个解决方案对我有用。它们中的大多数都涉及到不在/spec/Features 中的 spec-我的在/spec/Features 中。

首先是错误:

$bundle exec rspec spec
F


Failures:


1) security signs users in
Failure/Error: visit "/sessions/new"
NoMethodError:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>
# ./spec/features/security_spec.rb:4:in `(root)'


Finished in 0.006 seconds
1 example, 1 failure


Failed examples:


rspec ./spec/features/security_spec.rb:3 # security signs users in

我认为需要注意的是,起初我使用的是 URL Helper‘ new _ session _ path’,它一直给我一个错误 undefined local variable or method 'new_sessions_path'。我知道它是有效的,因为:

$ rake routes
logout_sessions GET    /sessions/logout(.:format) sessions#logout
sessions POST   /sessions(.:format)        sessions#create
new_sessions GET    /sessions/new(.:format)    sessions#new
contracts POST   /contracts(.:format)       contracts#create
new_contracts GET    /contracts/new(.:format)   contracts#new
edit_contracts GET    /contracts/edit(.:format)  contracts#edit
GET    /contracts(.:format)       contracts#show
PUT    /contracts(.:format)       contracts#update
DELETE /contracts(.:format)       contracts#destroy
root        /                          contracts#index

我的双子档案:

source 'https://rubygems.org'


gem 'rails', '3.2.11'
gem 'execjs'


group :assets do
gem 'sass-rails',   '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end


gem 'jquery-rails'
gem 'activerecord-oracle_enhanced-adapter', '~> 1.4.1'
gem 'jruby-openssl'
gem 'therubyrhino'
gem 'kaminari'
gem 'nokogiri'


group :development do
gem 'warbler'
end


group :test do
gem 'rspec-rails'
gem 'capybara'
gem 'activerecord-jdbcsqlite3-adapter'
end

在 my _ app/spec 中的 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'


# Capybara integration
require 'capybara/rspec'
require 'capybara/rails'


# 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}


RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
# Include path helpers
config.include Rails.application.routes.url_helpers
end

My _ app/spec/Features/security _ spec. rb:

describe "security", :type => :feature do
it "signs users in" do
visit "/sessions/new"
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"


page.should have_content('Login Successful')
end
end

我已经尝试过在使用和不使用 :type => :feature的情况下定义上面的测试。不管怎样都没有区别。你知道我接下来该做什么吗?

55410 次浏览

Try to add:

  config.include Capybara::DSL

to your config block.

# 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}


RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
# Include path helpers
config.include Rails.application.routes.url_helpers


config.include Capybara::DSL


end

Adding require 'rails_helper' at the top of my feature ended up fixing my problem:

require 'rails_helper'


describe "security", :type => :feature do


it "signs users in" do
visit new_sessions_path
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"


page.should have_content('Login Successful')
end
end

This seems odd to me since every example I've seen for rspec and capybara didn't have that require, but oh well. Problem solved.

Original Answer (older versions of rspec)

require 'spec_helper' is used by older versions of RSpec. The better answer would be require 'rails_helper'.

Try performing all your setup in a before block:

spec/features/security_spec.rb

describe "security" do
before do
visit "/sessions/new"
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"
end


it "signs users in" do
page.should have_content('Login Successful')
end
end

Since Capybara 2.0 one has to use folder spec/features Capybara commands don't work in folder spec/requests anymore.

I also had this problem,

Adding require 'rails_helper' at the top of my feature ended up fixing my problem:

require 'rails_helper'


RSpec.describe "Products", type: :request do
describe "GET /products" do
it "display tasks" do
Product.create!(:name => "samsung")
visit products_path
page.should have_content("samsung")
#expect(response).to have_http_status(200)
end
end
end

And add the 'config.include Capybara::DSL' in rails_helper.rb

RSpec.configure do |config|


config.fixture_path = "#{::Rails.root}/spec/fixtures"


config.use_transactional_fixtures = true


config.infer_spec_type_from_file_location!


config.include Capybara::DSL


end

Other than the upgrading issue which you would run into when ugprading from an older Rails app with require 'spec_helper.rb' instead of require 'rails_helper.rb', this happens for 3 known reasons:

1. Your spec isn't of type "feature" which means Capybara doesn't know how to run it using Javascript or a browser. You want to do one of two things: 1) Typically, you want config.infer_spec_type_from_file_location! set in your RSpec.configure and that will mean that what's in the features folder will be a feature.

if you have something non-standard, you can add type: :feature to the spec describe block to turn that spec in a feature, but typically it's easier just to put them into the /features folder and let the infer setting do its job.

2. You accidentally put the visit outside of the it block

The visit must be within the it, which is within the describe. Be sure not to put the visit directly within the describe.

3. Some other kernal panic you can't see has caused Capy to shut down the spec.

This is a nasty one to diagnose but I have seen it. It means that Capy didn't actually parse this file correctly, and so somehow isn't in the right scope when it gets to the visit block. Carefully pick apart your Capy spec to figure out where you introduced it.

I induced the kernal panic today but have a let block be called page (whoops). page appears to be a reserved word for Rspec or Capy here, and it causes the kernal panic, thus leading to the spec not to parse thus leading to the visit method not being found.

in my case, it was simply changing this:

let(:page) {Page.new()}

to

let(:content_page) {Page.new()}

Notice that the word page is not reserved by Rails, and works fine as a database name and also a model name, but the specific construction of using page here as the let variable name seemed to cause Capy to get kind of crappy.