我正在关注Ruby on Rails Tutorial,现在我需要为授权代码编写测试,例如确保用户只能编辑自己的个人资料。
有两个要测试的操作。一是确保用户无法访问编辑其他用户个人资料的页面。这个很容易,在水豚中进行简单的“功能”测试。
但我当然也希望测试PUT操作,以便用户无法手动提交PUT请求,绕过编辑页面。根据我的阅读,这应该作为rspec“请求”测试完成。
现在我的问题是,我是否必须将它们保存在不同的目录中? (规格/功能与规格/要求)?这听起来不对,因为这两种情况密切相关。这些测试通常如何在Rails中完成?
例如,
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user }
describe "visiting Users#edit page" do
before { visit edit_user_path(wrong_user) }
it { should_not have_selector('title', text: full_title('Edit user')) }
end
describe "submitting a PUT request to the Users#update action" do
before { put user_path(wrong_user) }
specify { response.should redirect_to(root_path) }
end
end
第二次测试在capybara 2.x中不起作用,因为不再支持“put”。它必须是一个请求测试。现在我必须编写第二个“sign_in”方法,因为当前的方法使用的方法仅适用于要素测试。闻起来像是很多代码重复。
========我的解决方案========
在确定如何登录请求测试之后,感谢Paul Fioravanti的回答,
before do
post sessions_path, email: user.email, password: user.password
cookies[:remember_token] = user.remember_token
end
我更改了所有测试以请求测试。所以我不必将它们分成不同的文件。保罗的解决方案也可行,但我认为这更清洁。
describe 'authorization' do
describe 'as un-signed-in user' do
let(:user) { FactoryGirl.create(:user) }
describe 'getting user edit page' do
before { get edit_user_path(user) }
specify { response.should redirect_to(signin_path) }
end
describe 'putting to user update page' do
before { put user_path(user) }
specify { response.should redirect_to(signin_path) }
end
end
describe 'as wrong user' do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: 'wrong@example.com') }
before do
post sessions_path, email: user.email, password: user.password
cookies[:remember_token] = user.remember_token
end
describe 'getting user edit page' do
before { get edit_user_path(wrong_user) }
specify { response.should redirect_to(root_path) }
end
describe 'putting to user update page' do
before { put user_path(wrong_user) }
specify { response.should redirect_to(root_path) }
end
end
end
答案 0 :(得分:2)
在完成The Rails Tutorial并将我的Sample App升级到Capybara 2.0之后,我最终完成了分割我的请求和功能规范的艰难过程。既然你说你现在还在做教程,我建议你继续使用Hartl指定的宝石(Capybara 1.1.2),完成你的示例应用程序,然后回到请求/功能问题作为重构行使。尽管如此,这是我最后编写“错误用户”授权规范的方式:
<强>规格/支持/ utilities.rb 强>
def sign_in_through_ui(user)
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign In"
end
def sign_in_request(user)
post session_path(email: user.email, password: user.password)
cookies[:remember_token] = user.remember_token
end
RSpec::Matchers::define :have_title do |text|
match do |page|
Capybara.string(page.body).has_selector?('title', text: text)
end
end
<强>规格/特征/ authentication_pages_spec.rb 强>
describe "Authentication on UI" do
subject { page }
# ...
describe "authorization" do
# ...
context "as a wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before do
visit root_path
click_link "Sign In"
sign_in_through_ui(user)
end
context "visiting Users#edit" do
let(:page_title) { full_title("Edit User") }
before { visit edit_user_path(wrong_user) }
it { should_not have_title(page_title) }
end
end
end
end
<强>规格/请求/ authentication_requests_spec.rb 强>
describe "Authentication Requests" do
subject { response }
# ...
describe "authorization" do
# ...
context "as a wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in_request(user) }
context "PUT Users#update" do
before { put user_path(wrong_user) }
it { should redirect_to(root_url) }
end
end
end
end
在尝试找出如何将feature
规范与我的request
规范分开时,我主要使用以下两个链接作为参考:
如果您不想使用自定义RSpec匹配器,您还可以在上面的测试中使用以下内容在title
元素上获得相同的结果:
its(:source) { should have_selector('title', text: page_title) }
答案 1 :(得分:1)
根据Jnicklas(https://github.com/jnicklas/capybara),您应该将规格/要求中的所有Capybare规格移至规格/功能,因为规格/功能现在将由Capybara 2.x使用。因此,这意味着一旦将Capybara规范移动到功能部件,就可以从spec / requests目录中完全删除这些规范。
就个人而言,我已经完成了Ruby on Rails教程,没有任何问题。我使用Capybara 2.x并且从未使用过spec / features(只是'旧'spec / requests)。对于Rspec 2.x支持,您必须添加require&gt;'capybara / rspec'&lt;到你的spec_helper.rb文件。没有它,你的测试可能会失败。
编辑:
我刚读过Rspec文档。如果您在规格中使用Capybara,则必须将这些规格移至规格/功能。如果没有涉及Capybara,那么规格就可以保留在您的请求目录中。
功能规格 https://www.relishapp.com/rspec/rspec-rails/v/2-12-2/docs/feature-specs/feature-spec!
请求规格 https://www.relishapp.com/rspec/rspec-rails/v/2-12-2/docs/request-specs
更多信息,来自Rubydoc: http://rubydoc.info/github/jnicklas/capybara/master#Using_Capybara_with_RSpec