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

終於通過了!

results matching ""

    No results matching ""