1.1 : courses#index 要能見到所有的 Course
編輯 spec/controllers/courses_controller_spec.rb
原先的檔案內容是:
require 'rails_helper'
RSpec.describe CoursesController, type: :controller do
end
spec 的檔案結構通常是,在第一行 require rails_helper
;接著 describe
這個 class CoursesController
要作什麼。
index action 要作什麼?
通常我們期待 index
action ,要撈出所有站上所有的 courses
,assigns 到 @courses
這個變數並顯示出來。
所以 Test 內容會是這樣:
require "rails_helper"
RSpec.describe CoursesController, type: :controller do
describe "GET index" do
it "assigns @courses and render template" do
course1 = Course.create(title: "foo", description: "bar")
course2 = Course.create(title: "bar", description: "foo")
get :index
expect(assigns[:courses]).to eq([course1, course2])
expect(response).to render_template("index")
end
end
end
https://www.relishapp.com/rspec/rspec-rails/docs/matchers/render-template-matcher
豆知識:
通常建議在 Controller 寫的 Test 命名法是以 HTTP verb + action_name 的方式命名,如:
- GET index
- POST create
- PUT update
- DELETE destroy
在 Terminal 執行 rspec spec/controllers/courses_controller_spec.rb
會得到以下結果。
F
Failures:
1) CoursesController GET index assigns @courses and render template
Failure/Error: course1 = Course.create(title: "foo", description: "bar")
NameError:
uninitialized constant Course
# ./spec/controllers/courses_controller_spec.rb:6:in `block (3 levels) in <top (required)>'
Finished in 0.00796 seconds (files took 2.59 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/courses_controller_spec.rb:5 # CoursesController GET index assigns @courses and render template
出現錯誤, RSpec 告訴我們沒有 Course
這個 class。
嗯...我們的確還沒有建立這個 model。那趕緊來建立吧!
執行
rails g model course title:string description:text
invoke active_record
create db/migrate/20160607190511_create_courses.rb
create app/models/course.rb
invoke rspec
create spec/models/course_spec.rb
然後跑 rake db:migrate
。這樣應該可以了吧?
重新執行:rspec spec/controllers/courses_controller_spec.rb
出現了另外一個錯誤:
F
Failures:
1) CoursesController GET index assigns @courses and render template
Failure/Error: get :index
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"courses"}
# ./spec/controllers/courses_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
Finished in 0.01862 seconds (files took 2.64 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/courses_controller_spec.rb:6 # CoursesController GET index assigns @courses and render template
然後它說沒有這個 routing。
補上 routing
到 config/routes.rb
加入
resources :courses
重新執行:rspec spec/controllers/courses_controller_spec.rb
F
Failures:
1) CoursesController GET index assigns @courses and render template
Failure/Error: get :index
AbstractController::ActionNotFound:
The action 'index' could not be found for CoursesController
# ./spec/controllers/courses_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
Finished in 0.02481 seconds (files took 1.2 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/courses_controller_spec.rb:6 # CoursesController GET index assigns @courses and render template
這次換找不到 index
這個 action。
補上 action
到 app/controllers/courses_controller.rb
加入
def index
@courses = Course.all
end
重新執行:rspec spec/controllers/courses_controller_spec.rb
它又抱怨沒有 view 。
F
Failures:
1) CoursesController GET index assigns @courses and render template
Failure/Error: get :index
ActionController::UnknownFormat:
CoursesController#index is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
NOTE! For XHR/Ajax or API requests, this action would normally respond with 204 No Content: an empty white screen. Since you're loading it in a web browser, we assume that you expected to actually render a template, not… nothing, so we're showing an error to be extra-clear. If you expect 204 No Content, carry on. That's what you'll get from an XHR or API request. Give it a shot.
Finished in 0.02609 seconds (files took 1.26 seconds to load)
1 example, 1 failure
補上 view:
mkdir -p app/views/courses
touch app/views/courses/index.html.erb
<div class="col-md-12">
<div class="course">
<%= link_to("New course", new_course_path , :class => "btn pull-right") %>
</div>
<table class="table">
<thead>
<tr>
<td> # </td>
<td> Title </td>
<td> Description </td>
</tr>
</thead>
<tbody>
<% @courses.each do |course| %>
<tr>
<td>#</td>
<td><%= link_to(course.title, course_path(course)) %></td>
<td><%= course.description %></td>
<td>
<%= link_to("Edit", edit_course_path(course), :class => "btn btn-xs") %>
<%= link_to("Delete", course_path(course), :class => "btn btn-xs", :method => :delete, :data => { :confirm => "Are you sure?" } ) %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
重新執行:rspec spec/controllers/courses_controller_spec.rb
.
Finished in 0.02203 seconds (files took 1.33 seconds to load)
1 example, 0 failures
終於通過了!