0

私は Devise を使って Rails 3 を学んでいますが、今のところうまく機能しているようです。カスタム セッションと登録コントローラーがあり、recaptcha が機能しており、サインインしているユーザーは、S3 に保存されている Carrierwave 経由でアバターをアップロードできます。私の進歩にかなり満足しています。

現在、Rspec テストを作成しています。うまくいかない!妥当なユーザー モデル テストがありますが、それはオンライン (https://github.com/RailsApps/rails3-devise-rspec-cucumber/) で見つけ、Michael Hartl の優れた「Ruby on Rails3 チュートリアル」です。

私の本当の問題は、コントローラーのテストと統合のテスト、特にコントローラーのテストです。最初は、Michael の本のテストを変換できると思っていましたが、ある程度は変換する必要がありますが、進行が遅く、常にレンガの壁に頭をぶつけているようです。 Rspec と capybara をよく知らない (いくつかの非常にばかげた間違いを犯した) だけでなく、Devise を十分に理解していないため、Devise が Rspec と同じようにうまく機能するかどうか疑問に思っています。Devise は Rack ベースであるため、Rspec で期待どおりに動作しない場合があることをどこかで読みました。それが本当かどうかわからないのですか?

Devise は gem であり、すでにテスト済みであるため、なぜこれが必要なのか疑問に思う人もいると思いますが、他の場所での変更により、すぐに気付かずにログインまたは登録が壊れた例がいくつかありました。コントローラーと統合テストの適切なセットがこれを解決したと思います。

もし私がこれを自分で行うことができれば、他の人のために公開したいと思いますが、これまでのところ、これらのテストを書くことは非常に苦痛であり、本当に他のことに移る必要があります.

これを使えるのは私だけではないはずです。そのような一連のテストを知っている人はいますか?

ジェシーの親切な助けの申し出に応えて...

これが私の registrations_controller_spec です。「「編集」ページをレンダリングする必要がある」のコメントは、私が苦労していることを示しています。また、「ユーザーを作成する必要があります」には、テストしようとしたができなかったことがいくつかあります。

require File.dirname(__FILE__) + '/../spec_helper'

describe Users::RegistrationsController do
  include Devise::TestHelpers
  fixtures :all
  render_views

  before(:each) do
    @request.env["devise.mapping"] = Devise.mappings[:user]
  end

  describe "POST 'create'" do
    describe "failure" do
      before(:each) do
        @attr = { :email => "", :password => "",
                  :password_confirmation => "", :display_name => "" }
      end

      it "should not create a user" do
        lambda do
          post :create, :user_registration => @attr
        end.should_not change(User, :count)
      end

      it "should render the 'new' page" do
        post :create, :user_registration => @attr
        response.should render_template('new')
      end
    end

    describe "success" do
      before(:each) do
        @attr = { :email => "user@example.com",
                  :password => "foobar01", :password_confirmation => "foobar01", :display_name => "New User" }
      end

      it "should create a user" do
        lambda do
          post :create, :user => @attr
          response.should redirect_to(root_path)
          #response.body.should have_selector('h1', :text => "Sample App")
          #response.should have_css('h1', :text => "Sample App")
          #flash[:success].should == "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
          #response.should have_content "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
        end.should change(User, :count).by(1)
      end

    end

  end

  describe "PUT 'update'" do
    before(:each) do
      @user = FactoryGirl.create(:user)
      @user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module
      sign_in @user
    end

    describe "Failure" do

      before(:each) do
        # The following information is valid except for display_name which is too long (max 20 characters)
        @attr = { :email => @user.email, :display_name => "Test", :current_password => @user.password }
      end

      it "should render the 'edit' page" do
        put :update, :id => subject.current_user, :user => @attr

        # HAVE PUT THE DEBUGS THAT I'D LIKE TO GET WORKING FIRST
        # Would like to be able to debug and check I'm getting the error(s) I'm expecting
        puts subject.current_user.errors.messages # doesn't show me the errors
        # Would like to be able to debug what html is being returned:
        puts page.html # only return the first line of html

        # Would like to be able to determine that this test is failing for the right reasons
        response.should have_content "Display name is too long (maximum is 20 characters)" # doesn't work

        response.should render_template('edit')
      end
    end

    describe "Success" do

      it "should change the user's display name" do
        @attr = { :email => @user.email, :display_name => "Test", :current_password => @user.password }
        put :update, :id => subject.current_user, :user => @attr
        subject.current_user.reload
        response.should redirect_to(root_path)
        subject.current_user.display_name == @attr[:display_name]
      end

    end
  end

  describe "authentication of edit/update pages" do

    describe "for non-signed-in users" do

      before(:each) do
        @user = FactoryGirl.create(:user)
      end

      describe "for non-signed-in users" do

        it "should deny access to 'edit'" do
          get :edit, :id => @user
          response.should redirect_to(new_user_session_path)
        end

        it "should deny access to 'update'" do
          put :update, :id => @user, :user => {}
          response.should redirect_to(new_user_session_path)
        end

      end

    end
  end

end
4

2 に答える 2

1

Devise Wikiによると、コントローラーのテストはある種のハイブリッド (ユニット + 統合) テストでなければなりません。データベースに User (または認証エンティティ) のインスタンスを作成する必要があります。Deviseのものを嘲笑するのは本当に難しいです、私を信じてください.

これを試してください: How-To:-Controllers-and-Views-tests-with-Rails-3-and-rspec

Cucumber を使用すると、すでにログイン プロセスを実行するステップを作成できます。

それが役に立てば幸い。

于 2012-10-26T20:04:28.077 に答える
0

OK、これを機能させるためのいくつかのこと:

本文に特定のテキストがあることをテストする方法は次のとおりです(.bodyがありませんでした

response.body.should include "Display name is too long (maximum is 30 characters)"

@user にエラーがあることをテストすることもできます。

assigns[:user].errors[:display_name].should include "is too long (maximum is 30 characters)"

ただし、実際には名前を 20/30 文字以上にする必要があるため、投稿される属性を次のように変更しました。

@attr = { :email => @user.email, :display_name => ("t" * 35), :current_password => @user.password }

https://gist.github.com/64151078628663aa7577

于 2012-10-27T18:31:10.873 に答える