Capybara,Devise,CanCan和RSpec集成测试:有效签到302重定向到example.com

更新:请参阅文章的结尾,了解规范现在如何工作,我的规格/请求中的规格而不是规格/控制器。 仍然想知道如何获得一个有效的登录用户与我的控制器进行集成测试。

我第一次使用Devise和CanCan,并且很难进行最基本的集成测试,我正在validation登录的用户是……好……登录。我已经阅读了无数post和处理Devise和RSpec集成测试的答案(即通过https://github.com/plataformatec/devise/wiki/How-To%3a-Test-with-Capybara,http:// schneems直接访问会话来加速它们.com / post / 15948562424 / speed-up-capybara-tests-with-devise ,以及Capybara,RSpec和Devise:通过绕过慢速登录和直接设置会话,可以更快地进行集成测试吗?但我一直无法做到得到一个标准的工作按预期工作,我很困惑:

  1. 开发环境工作正常(可以登录并重定向到正确的页面,导航登录链接更改为注销等)。
  2. test.log表示没有问题,直到302重定向到http://www.example.com而不是我的root_path。

对于具有不同解决方案的类似问题的大量用户,我显然不是唯一一个遇到此问题的人,因为会话的各个方面等在不同场景中不可用。

剥离测试:

subject { page } describe 'should be able to log in' do before do visit '/users/sign_in' user = FactoryGirl.create(:admin) #user.add_role :admin fill_in 'Username', with: user.username fill_in 'Password', with: user.password click_on 'Sign in' end it { should have_link 'Logout' } end ... 

相关的log.test输出:

  Started POST "/users/sign_in" for 127.0.0.1 at 2012-11-06 17:31:10 -0800 Processing by Devise::SessionsController#create as HTML Parameters: {"utf8"=>"✓", "user"=>{"username"=>"username1", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"} [1m[36mUser Load (0.1ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."username" = 'username1' LIMIT 1[0m [1m[35m (0.0ms)[0m SAVEPOINT active_record_1 [1m[36m (0.0ms)[0m [1mRELEASE SAVEPOINT active_record_1[0m [1m[35m (0.0ms)[0m SAVEPOINT active_record_1 [1m[36m (0.1ms)[0m [1mUPDATE "users" SET "last_sign_in_at" = '2012-11-07 01:31:10.722712', "current_sign_in_at" = '2012-11-07 01:31:10.722712', "last_sign_in_ip" = '127.0.0.1', "current_sign_in_ip" = '127.0.0.1', "sign_in_count" = 1, "updated_at" = '2012-11- 07 01:31:10.723051' WHERE "users"."id" = 1[0m [1m[35m (0.0ms)[0m RELEASE SAVEPOINT active_record_1 Redirected to http://www.example.com/ Completed 302 Found in 12ms (ActiveRecord: 0.0ms) 

剥离routes.rb:

 authenticated :user do root :to => 'home#index' end root :to => "home#index" devise_for :users resources :users 

剥光能力:

课程能力包括CanCan :: Ability

  def initialize(user) user ||= User.new # guest user (not logged in) if user.has_role? :admin can :manage, :all end ... 

并且要彻底,当前的Gemfile:

 source 'https://rubygems.org' gem 'rails', '3.2.8' gem "bootstrap-sass", "~> 2.1.0.1" gem 'faker', '1.1.2' gem 'will_paginate', '~> 3.0.3' gem 'bootstrap-will_paginate', '~> 0.0.9' gem 'jquery-rails' gem 'client_side_validations' gem 'thin' gem "devise", "~> 2.1.2" gem "cancan", "~> 1.6.8" gem "rolify", "~> 3.2.0" gem "simple_form", "~> 2.0.4" group :assets do gem 'sass-rails', '~> 3.2.3' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' end group :development, :test do gem 'sqlite3', '1.3.5' gem "rspec-rails", "~> 2.11.4" gem 'guard-rspec', '1.2.1' #gem 'listen', github: 'guard/listen', branch: 'polling/double' gem 'guard-spork' gem 'guard-cucumber' gem 'spork', '0.9.2' gem "factory_girl_rails", ">= 4.1.0" end group :development do gem 'annotate', '2.5.0' gem "quiet_assets", ">= 1.0.1" end group :test do gem 'capybara', ">= 1.1.2" gem "email_spec", ">= 1.2.1" gem "cucumber-rails", ">= 1.3.0", :require => false gem "database_cleaner", ">= 0.9.1" gem "launchy", ">= 2.1.2" gem 'rb-fsevent', '0.9.1', :require => false gem 'growl', '1.0.3' gem 'terminal-notifier-guard' end group :production do gem 'pg', '0.12.2' end 

还有另一个用户遇到了这个基本任务的问题,但事实certificate这只是一个语法错误(请参阅使用rspec / devise进行登录集成测试 ),所以我确定我只是遗漏了一些非常明显的东西。

更新:

你一定是在跟我开玩笑。 离开它几个小时之后,事实certificate我在规格/控制器中出于某种原因有这个规格,当简单地将其切换到规格/请求时,一切都变为绿色。

我引用:

如果您使用的是Rails,请将您的Capybara规格放入spec / requests或spec / integration中。

发现于https://github.com/jnicklas/capybara#readme

但是,我仍然想知道未来的要求如何我可以在我的控制器上进行集成测试,这需要有一个登录用户….对于过去的其他非Devise应用程序,这就像这样简单下列:

 describe SomeController do let(:user) { FactoryGirl.create(:user) } before { valid_sign_in user } ... 

我帮手很简单

  def valid_sign_in(user) visit signin_path fill_in "Email", with: user.email fill_in "Password", with: user.password uncheck(:remember_me) click_button "Sign In" # Sign in when not using Capybara as well. cookies[:remember_token] = user.remember_token end 

有两个问题在起作用:

1. rspec / controller vs rspec / requests

我试图在spec / controller下进行集成测试。 根据https://github.com/jnicklas/capybara#readme ,您需要将Capybara规格放入spec / requests或spec / integration中。 根据https://stackoverflow.com/a/5803121/9344 :

请求规范是ActionDispatch :: IntegrationTest的一个瘦包装器,它不像控制器规范(包装ActionController :: TestCase)那样工作。 即使有可用的会话方法,我也不认为它是受支持的(即它可能存在,因为包含在其他实用程序中的模块也包含该方法)。

最初这可以通过帮助方法使用Devise解决,例如:

 # file: spec/requests_helper.rb def login(user) post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password end 

但是我已经实现的官方/最新解决方案(但请参见下面的第二点,为什么它没有解决我的问题),可以在https://github.com/plataformatec/devise/wiki/How-To找到: -测试与-水豚

2. Devise :: HelperTests用于控制器/视图测试,而不是集成测试。

如果我想在控制器上做一些测试,我可以使用Devise :: TestHelpers(通过spec_helper.rb引用),但即使这样我也没有得到Capybara集成测试的function,因为Devise :: TestHelpers是专门为控制器编写的/查看测试,而不是集成测试。 请参阅rspec和设计测试助手 。

总之,我不想在控制器测试中做什么,因为它实际上是一个集成测试,并且会话等不能用于规范/控制器。 但是,有一些Devise测试助手可以用来帮助进行控制器/视图测试。

UPDATE

我稍后再重访,现在让Warden助手在我的集成测试中运行。 欢呼! 在我的448测试中,这已经取消了8-10秒。 诀窍是https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara上的新条目。 特别:

水豚-的Webkit

如果您在使用带有capybara-webkit驱动程序的Warden的login_as方法时遇到问题,请尝试在login_as选项结构中将run_callbacks设置为false

 user = Factory.create(:user) login_as(user, :scope => :user, :run_callbacks => false) 

总之,我不需要每次需要经过身份validation的用户进行集成测试时都要进行实际的表单填写和发布,现在我只需要login_as(user, :scope => :user, :run_callbacks => false) (当然,重构为辅助方法)。