3

更新:由于我的规范在规范/请求而不是规范/控制器中,请参阅帖子末尾的规范现在如何工作。仍然想知道如何让有效的登录用户与我的控制器进行集成测试。

我是第一次与 Devise 和 CanCan 合作,并且在进行最基本的集成测试时遇到了困难,我正在验证登录用户是否......嗯......登录。我已经阅读了无数的帖子和处理设计和 RSpec 集成测试的答案(即通过直接通过https://github.com/plataformatec/devise/wiki/How-To%3a-Test-with-Capybara访问会话来加速它们,http://schneems .com/post/15948562424/speed-up-capybara-tests-with-devise 和 CapybaraRSpec 和 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)

剥离路线.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

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

更新:

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

我引用:

如果您使用的是 Rails,请将您的 Capybara 规范放在规范/请求或规范/集成中。

https://github.com/jnicklas/capybara#readme找到

但是,我仍然想知道如何满足未来的要求,我可以在需要登录用户的控制器上进行集成测试......对于过去的其他非设计应用程序,这就像类似以下:

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
4

1 回答 1

5

有两个问题在起作用:

1. rspec/controller vs rspec/requests

我试图在规范/控制器下进行集成测试。根据https://github.com/jnicklas/capybara#readme,您需要将 Capybara 规范放在规范/请求或规范/集成中。根据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 集成测试的功能,因为 Devise::TestHelpers 是专门为控制器编写的/view 测试,而不是集成测试。请参阅rspec 和设计测试助手

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

更新

很久以后我重新审视了这一点,现在让 Warden 助手在我的集成测试中发挥作用。欢呼!在我的 448 次测试中,这已经花费了 8-10 秒。诀窍是https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara上的一个新条目。具体来说:

Capybara-Webkit

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

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

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

于 2012-11-07T17:54:16.483 回答