Ruby on rails 测试RoR教程中的失败(第9.4章)
我正在学习RoR教程第9.4章。当所有的rspec测试都变成绿色时,我的测试就不能正常工作了。我运行bundle exec rspec spec/并得到四个失败,错误如下:Ruby on rails 测试RoR教程中的失败(第9.4章),ruby-on-rails,ruby,ruby-on-rails-3,rspec,railstutorial.org,Ruby On Rails,Ruby,Ruby On Rails 3,Rspec,Railstutorial.org,我正在学习RoR教程第9.4章。当所有的rspec测试都变成绿色时,我的测试就不能正常工作了。我运行bundle exec rspec spec/并得到四个失败,错误如下: Failures: 1) User pages index signup page with valid information after saving the user Failure/Error: sign_in user NoMethodError: undefined met
Failures:
1) User pages index signup page with valid information after saving the user
Failure/Error: sign_in user
NoMethodError:
undefined method `email' for nil:NilClass
# ./spec/support/utilities.rb:23:in `sign_in'
# ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi
red)>'
2) User pages index signup page with valid information after saving the user
Failure/Error: sign_in user
NoMethodError:
undefined method `email' for nil:NilClass
# ./spec/support/utilities.rb:23:in `sign_in'
# ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi
red)>'
3) User pages index signup page with valid information after saving the user
Failure/Error: sign_in user
NoMethodError:
undefined method `email' for nil:NilClass
# ./spec/support/utilities.rb:23:in `sign_in'
# ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (requi
red)>'
4) Authentication signin with invalid information after visiting another page
Failure/Error: it { should_not have_selector('div.alert.alert-error') }
expected #has_selector?("div.alert.alert-error") to return false, got tru
e
# ./spec/requests/authentication_pages_spec.rb:26:in `block (5 levels) in <
top (required)>'
Finished in 21.33 seconds
81 examples, 4 failures
用户\u页面\u spec.rb:
require 'spec_helper'
describe "User pages" do
subject { page }
describe "index" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit users_path
end
it { should have_title('All users') }
it { should have_content('All users') }
describe "pagination" do
before(:all) { 30.times { FactoryGirl.create(:user) } }
after(:all) { User.delete_all }
it { should have_selector('div.pagination') }
it "should list each user" do
User.paginate(page: 1).each do |user|
expect(page).to have_selector('li', text: user.name)
end
end
end
describe "delete links" do
it { should_not have_link('delete') }
describe "delete links" do
it { should_not have_link('delete') }
describe "as an admin user" do
let(:admin) { FactoryGirl.create(:admin) }
before do
sign_in admin
visit users_path
end
it { should have_link('delete', href: user_path(User.first)) }
it "should be able to delete another user" do
expect do
click_link('delete', match: :first)
end.to change(User, :count).by(-1)
end
it { should_not have_link('delete', href: user_path(admin)) }
end
end
end
describe "profile page" do
let(:user) { FactoryGirl.create(:user) }
before { visit user_path(user) }
it { should have_content(user.name) }
it { should have_title(user.name) }
end
describe "signup page" do
before { visit signup_path }
let(:submit) { "Create my account" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user@example.com"
fill_in "Password", with: "foobar"
fill_in "Confirmation", with: "foobar"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after saving the user" do
before { click_button submit }
let(:user) { User.find_by(email: 'user@example.com') }
it { should have_link('Sign out') }
it { should have_title(user.name) }
it { should have_selector('div.alert.alert-success', text: 'Welcome') }
end
end
end
describe "edit" do
let(:user) { FactoryGirl.create(:user) }
before do
sign_in user
visit edit_user_path(user)
end
describe "page" do
it { should have_content("Update your profile") }
it { should have_title("Edit user") }
it { should have_link('change', href: 'http://gravatar.com/emails') }
end
describe "with valid information" do
let(:new_name) { "New Name" }
let(:new_email) { "new@example.com" }
before do
fill_in "Name", with: new_name
fill_in "Email", with: new_email
fill_in "Password", with: user.password
fill_in "Confirm Password", with: user.password
click_button "Save changes"
end
it { should have_title(new_name) }
it { should have_selector('div.alert.alert-success') }
it { should have_link('Sign out', href: signout_path) }
specify { expect(user.reload.name).to eq new_name }
specify { expect(user.reload.email).to eq new_email }
end
end
end
end
身份验证\u页面\u spec.rb:
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin page" do
before { visit signin_path }
it { should have_content('Sign in') }
it { should have_title('Sign in') }
end
describe "signin" do
before { visit signin_path }
describe "with invalid information" do
before { click_button "Sign in" }
it { should have_title('Sign in') }
it { should have_selector('div.alert.alert-error') }
describe "after visiting another page" do
before { click_link "Home" }
it { should_not have_selector('div.alert.alert-error') }
end
end
describe "with valid information" do
let(:user) { FactoryGirl.create(:user) }
before { sign_in user }
it { should have_title(user.name) }
it { should have_link('Users', href: users_path) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Settings', href: edit_user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
describe "follower by signout" do
before {click_link "Sign out"}
it {should have_link('Sign in')}
end
end
end
describe "authorization" do
describe "for non-signed-in users" do
let(:user) { FactoryGirl.create(:user) }
describe "when attempting to visit a protected page" do
before do
visit edit_user_path(user)
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
describe "after signing in" do
it "should render the desired protected page" do
expect(page).to have_title('Edit user')
end
end
end
describe "in the Users controller" do
describe "visiting the edit page" do
before { visit edit_user_path(user) }
it { should have_title('Sign in') }
end
describe "submitting to the update action" do
before { patch user_path(user) }
specify { expect(response).to redirect_to(signin_path) }
end
end
describe "visiting the user index" do
before { visit users_path }
it { should have_title('Sign in') }
end
end
describe "as wrong user" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
before { sign_in user, no_capybara: true }
describe "submitting a GET request to the Users#edit action" do
before { get edit_user_path(wrong_user) }
specify { expect(response.body).not_to match(full_title('Edit user')) }
specify { expect(response).to redirect_to(root_url) }
end
describe "submitting a PATCH request to the Users#update action" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to(root_url) }
end
end
describe "as non-admin user" do
let(:user) { FactoryGirl.create(:user) }
let(:non_admin) { FactoryGirl.create(:user) }
before { sign_in non_admin, no_capybara: true }
describe "submitting a DELETE request to the Users#destroy action" do
before { delete user_path(user) }
specify { expect(response).to redirect_to(root_url) }
end
end
end
end
user.rb
class User < ActiveRecord::Base
has_secure_password
before_save { self.email = email.downcase }
before_create :create_remember_token
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_remember_token)
end
end
rails控制台测试:
irb(main):001:0> **user = FactoryGirl.build(:user)**
=> #<User id: nil, name: "Person 1", email: "person_1@example.com", created_at:
nil, updated_at: nil, password_digest: "$2a$04$LiRdaarU6QaX9PJa1uFjE.5e44SYRsmy1
OMY8A4EKZow...", remember_token: nil, admin: false>
irb(main):002:0> **user.valid?**
User Exists (1.0ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email")
= LOWER('person_1@example.com') LIMIT 1
=> true
irb(main):003:0> **user.errors**
=> #<ActiveModel::Errors:0x49dd678 @base=#<User id: nil, name: "Person 1", email
: "person_1@example.com", created_at: nil, updated_at: nil, password_digest: "$2
a$04$LiRdaarU6QaX9PJa1uFjE.5e44SYRsmy1OMY8A4EKZow...", remember_token: nil, admi
n: false>, @messages={}>
我更改了users_controller.rb,现在只有3个1-3个故障
用户\u controller.rb:
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
def edit
end
def update
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to @user
# Handle a successful update.
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
实际项目版本-。也许这有助于找到失败的原因/user\u page\u spec.rb中的一条结束语句放错了位置。描述索引块应在描述配置文件页面之前结束
i、 e
注册用于注册新用户,因此测试不应首先让用户登录
顺便说一句,您还描述了两次删除链接,嵌套在其内部,尽管这不会是错误的原因;它只是重复一个测试。如果我们也能在spec/factories.rb中看到工厂:用户是如何定义的,那就太好了,因为您已经以不同的方式定义了有效的电子邮件正则表达式 对于初学者,您可以将regex条件还原回原始状态:
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
或
确保验证部分与您的factory:user一起工作
并删除第二个密码以确保安全。您需要共享实际代码并测试失败的代码,而不仅仅是测试结果。让我们看看app/models/user.rb您是否也可以添加您的用户工厂。根据我下面的回答,您是否可以转到rails控制台测试,然后做user=FactoryGirl.build:user然后检查user.valid?还有user.errors.抱歉伙计-我再尝试一次。。。注册页面的测试正在描述索引块中运行。您的意思是在描述删除链接之前结束描述索引块吗?鉴于您正在测试注册功能,您可能不想在此之前登录。希望这是有意义的…我删除了第二个密码并更改了有效的电子邮件注册表。但仍然有相同的4次失败。
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def index
@users = User.paginate(page: params[:page])
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
sign_in @user
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
def edit
end
def update
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to @user
# Handle a successful update.
else
render 'edit'
end
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
# Before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
describe "index" do
...
describe "pagination" do
...
end
describe "delete links" do
...
end
end
describe "profile page" do
...
end
describe "signup page" do
...
end
etc.
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i