2
0

初めてのRSpecで学んだこと No.2

Posted at

バージョン

  • ruby 3.2.2
  • Rails 6.1.7.6

タスク管理アプリでの、タスクが降順に並んでいるかをRSpecでテストする

タスク管理アプリにて、投稿したタスクを降順に並べ、降順に並んでいるかをテストするために、「最新のタスクが一番上に表示される」、ということを確認するためのコードを書いたが、その時に学んだことを備忘録として残しておく。

spec/factories/tasks.rb
FactoryBot.define do
  factory :task do
    name { 'パパ' }
    content { '日曜日歯医者' }
  end
end
spec/system/task.rb
RSpec.describe 'タスク管理機能', type: :system do
  describe '新規作成機能' do
    context 'タスクが作成日時の降順に並んでいる場合' do
      it '新しいタスクが一番上に表示される' do
        FactoryBot.create(:task, content: '自転車修理')
        FactoryBot.create(:task, content: '買い物')
        FactoryBot.create(:task, content: '洗濯')
        visit tasks_path
        list = all('.task_list')[0] 
        expect(list).to have_content '洗濯'        
      end
    end
  end
end
app/views/tasks/index.html.erb
<h1><%= t('view.index') %></h1>
<div class="task_list">
  <table>
    <tr>
      <th><%= t('view.task_name') %></th>
      <th><%= t('view.content') %></th>
    </tr>

  <% @tasks.each do |task| %>
    <tr>
      <td><%= task.name %></td>
      <td><%= task.content %></td>

      <td><%= link_to t('view.detail'), task_path(task.id) %></td>
      <td><%= link_to t('view.edit'), edit_task_path(task.id) %></td>
      <td><%= link_to t('view.destroy'), task_path(task.id), method: :delete ,data: { confirm: '本当に削除していいですか?' } %></td>
    </tr>
  <% end %>
  </table>
</div>

<%= link_to t('view.new_task'), new_task_path %>

テストが「洗濯」でも「買い物」でも「自転車修理」でも成功してしまう!なぜだ??

私は上記のようにコードを書いていました。

spec/system/task.rb内で、下記のように3つのテストデータを作成するが、

FactoryBot.create(:task, content: '自転車修理')
FactoryBot.create(:task, content: '買い物')
FactoryBot.create(:task, content: '洗濯')

一番最新のデータはcontentが「洗濯」のデータなので、

expect(list).to have_content '洗濯'

の部分で、最新のデータに「洗濯」を含んでいることを確認する。
なのに、「洗濯」でも「買い物」でも「自転車修理」でも成功してしまうのです...なぜだ...

考えてみましたがわからなかったのでメンターさんに教えてもらいました。まず、

all('.task_list')

これは、htmlファイル内の、task_list要素全てを、配列の形で取り出す。そして、

list = all('.task_list')[0]

とすることで、0番ということで、1番最初のデータが取り出され、それを変数listに代入している。

問題は、app/views/tasks/index.html.erb 内の2行目

<div class="task_list">

これの位置。ここに書いてしまうと
スクリーンショット 2023-11-29 14.29.25.png
このように、ひとつのtask_listの中に、「自転車修理」も「買い物」も「洗濯」も全て含まれてしまっている。
なので変数listの中にも、「自転車修理」も「買い物」も「洗濯」も全て含まれてしまうので、「洗濯」でも「買い物」でも「自転車修理」でもテストが成功してしまったのでした。

なので、class="task_list"の位置を変えます。

<h1><%= t('view.index') %></h1>
<div>
  <table>
    <tr>
      <th><%= t('view.task_name') %></th>
      <th><%= t('view.content') %></th>
    </tr>

  <% @tasks.each do |task| %>
    <tr class="task_list">
      <td><%= task.name %></td>
      <td><%= task.content %></td>

      <td><%= link_to t('view.detail'), task_path(task.id) %></td>
      <td><%= link_to t('view.edit'), edit_task_path(task.id) %></td>
      <td><%= link_to t('view.destroy'), task_path(task.id), method: :delete ,data: { confirm: '本当に削除していいですか?' } %></td>
    </tr>
  <% end %>
  </table>
</div>

<%= link_to t('view.new_task'), new_task_path %>

9行目に移動させました。すると、フォームビューで見てみると、
スクリーンショット 2023-11-29 14.40.42.png
このように、「自転車修理」「買い物」「洗濯」それぞれに、class="task_list"が付いているので、all('.task_list')[0] には、1番最新のデータが入り、それが 変数listに代入される。1番最新のtask_listは、「パパ」「洗濯」なので、「洗濯」のみでテストは成功し、「買い物」「自転車修理」ではテストは不成功となる!!

初学者の私には、とーても新発見で面白かったので記事にしました!一緒に誰かのお役に立つと良いです。
本日は以上!!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0