[英]Why are my Rspec tests failing?
我正在編寫一個小的Rails todo應用程序進行練習。 我正在嘗試為各種事情編寫自己的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
我會為此刺一針。 沒有特別的順序:
測試2(TodosPages主頁應刪除待辦事項並重定向到索引)
看來您的Todo表在測試數據庫中為空,因此在控制器操作中調用Todo.last時,您得到nil,然后嘗試對nil調用delete。
在刪除測試之前,您在測試中的任何地方看不到要創建至少一個Todo對象的地方。
另外,在控制器中,您可能需要考慮使用destroy而不是delete方法。
測試1(TodosPages主頁應創建一個待辦事項)
在驗證方面,您的Todo模型中有什么? 是否有任何必填字段? 我猜測:todo_item是必填字段,但是在您的rspec測試中,您只需單擊按鈕,並且不為該字段提供任何輸入,因此它可能無法通過模型驗證。
在要添加的控制器操作中,使用create! 而不是創建,如果模型驗證失敗,應該會給您其他錯誤消息。
測試3(TodosPages主頁添加Todo)
可能由於上述測試失敗的相同原因而失敗,即驗證失敗。 首先解決該問題,然后查看此測試是否通過。
希望這可以幫助。
編輯:通過參數的測試示例
我個人的喜好是將控制器測試(測試特定的控制器功能)與集成類型測試(確保頁面正確填充,按鈕出現且可單擊等)分開。 對於后者,我喜歡使用黃瓜。 然后,您可以使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.