0

私は練習用の小さなRailstodoアプリを書いています。チュートリアルに従うのではなく、さまざまなことについて独自のRspecテストを作成しようとしています。テストは数回しかありませんが、いくつか失敗していて、その理由がわかりません。私はここに質問を投稿することを最後の手段にしようとしていますが、ここで質問をするたびに、問題の良い解決策を得ることができました。

ここにいくつかのコードがあります:

require 'spec_helper'

describe "TodosPages" do
  describe "home page" do
before { visit root_path }

it "should have the content 'Todo App'" do      
    page.should have_content('Todo App')
end  
it "should have title tag" do       
    page.should have_selector 'title'
end  
  it "should delete a todo and redirect to index" do    
      expect { click_link "Delete last todo" }.to change(Todo, :count).by(-1)
      response.should redirect_to :action => 'index'
  end
 describe "Add Todo" do
  subject { page }
   before {click_button "Add todo"}
   it { should have_selector('div.alert.alert-success', text: 'Todo Successfully Created') }

  end

  it "should have a error message" do
    pending
  end

  it "should create a Todo" do
   expect { click_button "Add todo" }.to change(Todo, :count).by(1)
  end


 end

end

 todos_controller



  class TodosController < ApplicationController
  def index
    @todo_items = Todo.all
    @new_todo = Todo.new
    render :index

  end

  def delete
    @todo_delete = Todo.last
    @todo_delete.delete
    redirect_to :action => 'index'

  end

   def add
   todo = Todo.create(:todo_item => params[:todo][:todo_item])
   unless todo.valid?
     flash[:error] = todo.errors.full_messages.join("<br>").html_safe
   else
     flash[:success] = "Todo Successfully Created"  
   end
  redirect_to :action => 'index'
end

def complete
    params[:todos_checkbox].each do |check|
       todo_id = check
       t = Todo.find_by_id(todo_id)
       t.update_attribute(:completed, true)
     end
     redirect_to :action => 'index'
    end
  end

   index.html.erb

<% @title = "Todo App" %>
<div class="container"> 
    <div class="row">
     <div class='span6' >

      <h1 class="hero-unit">Simple Todo App</h1>


      <p>All your todos here</p>
            <%= form_for @new_todo, :url => { :action => "add" }  do |f|  %>
            <%= f.text_field  :todo_item %>
            <%= f.submit "Add todo", class: "btn btn-primary" %>
         <%end%>

            <% if flash[:error] %>
             <div class="alert alert-error">
                <button type="button" class="close" data-dismiss="alert" >×</button>
                <strong><%= flash[:error] %></strong>
                </div>
            <% end %>

            <% if flash[:success] %>
           <div class="alert alert-success">
             <button type="button" class="close" data-dismiss="alert" >×</button>
                <strong><%= flash[:success] %></strong>
           </div>
      <% end %>

<div class="well">
    <%= form_tag("/todos/complete/", :method => "post") do %>
        <ul style="list-style-type:none;">
        <% @todo_items.each do |t| %> 
         <% if t.completed == true %>
         <li style="color:grey;"> <%= check_box_tag  "todos_checkbox[]",t.id %>  <strike><%= t.todo_item %></strike> </li>
      <% else %>
         <li> <%= check_box_tag  "todos_checkbox[]",t.id %> <%= t.todo_item %> </li>
      <% end %>
            <%end%>
            </ul>
                <%= submit_tag("Complete Todos", :class=>"btn btn-success") %>
            <%end %>
        </div> <!-- well --> 
        <%=  link_to "Delete last todo", delete_path %>

    </div> <!-- span6--> 
 </div> <!-- row --> 

  Failures:

 1) TodosPages home page should create a Todo
 Failure/Error: expect { click_button "Add todo" }.to change(Todo, :count).by(1)
   count should have been changed by 1, but was changed by 0
 # ./spec/views/index_page_spec.rb:29:in `block (3 levels) in <top (required)>'

 2) TodosPages home page should delete a todo and redirect to index
 Failure/Error: expect { click_link "Delete last todo" }.to change(Todo, :count).by(-1)
 NoMethodError:
   undefined method `delete' for nil:NilClass
 # ./app/controllers/todos_controller.rb:11:in `delete'
 # (eval):2:in `click_link'
 # ./spec/views/index_page_spec.rb:14:in `block (4 levels) in <top (required)>'
 # ./spec/views/index_page_spec.rb:14:in `block (3 levels) in <top (required)>'

 3) TodosPages home page Add Todo 
 Failure/Error: it { should have_selector('div.alert.alert-success', text: 'Todo Successfully   Created') }
   expected css "div.alert.alert-success" with text "Todo Successfully Created" to return something
 # ./spec/views/index_page_spec.rb:20:in `block (4 levels) in <top (required)>'

 Finished in 0.33114 seconds
 8 examples, 3 failures, 1 pending

 Failed examples:

 rspec ./spec/views/index_page_spec.rb:28 # TodosPages home page should create a Todo
 rspec ./spec/views/index_page_spec.rb:13 # TodosPages home page should delete a todo and redirect to index
 rspec ./spec/views/index_page_spec.rb:20 # TodosPages home page Add Todo 

 Randomized with seed 32260

前もって感謝します!

------Todo.rb


 class Todo < ActiveRecord::Base
    attr_accessible :todo_item, :completed
    validates :todo_item, presence: true , length: { maximum: 25 }

    end
4

1 に答える 1

1

私はこれを突き刺します。順不同:

テスト 2 (TodosPages ホームページは todo を削除し、インデックスにリダイレクトする必要があります)

テスト データベースで Todo テーブルが空のように見えるため、コントローラー アクションで Todo.last を呼び出すと、nil が返され、nil で delete を呼び出しようとします。

削除テストの前に少なくとも 1 つの Todo オブジェクトを作成しているテストのどこにも見当たりません。

別の注意として、コントローラーでは、delete メソッドの代わりに destroy を使用することを検討することをお勧めします。

テスト 1 (TodosPages ホームページで Todo を作成する必要があります)

検証に関して、Todo のモデルには何がありますか? 必須フィールドはありますか? :todo_item は必須フィールドだと思いますが、rspec テストでは、ボタンをクリックするだけでそのフィールドに入力を提供しないため、モデルの検証に失敗する可能性があります。

add のコントローラー アクションで、create! を使用します。モデルの検証に失敗している場合は、追加のエラー メッセージが表示されます。

テスト 3 (TodosPages ホームページに Todo を追加)

上記のテストが失敗しているのと同じ理由で失敗している可能性があります。つまり、検証が失敗しています。最初にそれを修正してから、このテストに合格するかどうかを確認してください。

お役に立てれば。

編集:パラメータを渡すテストの例

私の個人的な好みは、コントローラーのテスト (特定のコントローラー機能のテスト) を統合タイプのテスト (ページが適切に入力されていること、ボタンが表示され、クリック可能であることなど) から分離することです。後者については、Cucumber を使用するのが好きです。次に、Rspec を使用してより簡単な Controller テストを作成できます。これにより、特定のロジックをテストしたり、テストしているアクションに直接パラメーターを渡すことができます。テストは次のようになります

describe "add Todo" do
 it "increases count by 1" do 
  expect {post: :add, todo_item: "string"}.to change(Todo, :count).by(1)
 end
end

あるいは、引き続き Rspec で統合テストを行いたい場合 (ブラウザのシミュレーションに Capybara を使用していると仮定)、todo_item テキスト フィールドに一意の ID または名前を指定する必要があります。

it "should create a Todo" do
 fill_in "*todo_item_unique_id" with "some text"
 expect { click_button "Add todo" }.to change(Todo, :count).by(1)
end
于 2013-02-14T04:58:55.517 に答える