1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rspec】before と let! を使ってSystem Specを書いてみた (データ作成日時降順表示のテスト)

Last updated at Posted at 2023-06-08

はじめに

 
プログラミングスクールにてRuby on Railsを学習している者です。
この記事では、System Specの書き方で疑問に思った点と自分なりの解釈をまとめます。

初学者(学習期間1ヶ月)のため、初歩的な内容です。
誤った記述があるかもしれませんが、ご指摘いただけますと幸いです。
よろしくお願いいたします。

前提

タスク管理アプリの一覧画面にて、タスク登録日時の降順表示(最新のものが上にくる)に切り替えた際のテストコードです。


task_spec.rb
require 'rails_helper'
RSpec.describe 'タスク管理機能', type: :system do
  let!(:task) {FactoryBot.create(:task, name: 'aaa')}
  describe '一覧表示機能' do
    before do
      task1 = FactoryBot.create(:task, name: 'bbb')
      task2 = FactoryBot.create(:task, name: 'ccc')
      visit tasks_path
    end
    context '一覧画面に遷移した場合' do
      it '作成済みのタスク一覧が表示される' do
        expect(page).to have_content 'bbb'
        expect(page).to have_content 'ccc'
      end
    end
    context 'タスクが作成日時の降順に並んでいる場合' do
      it '新しいタスクが一番上に表示される' do
        expect(page.text).to match(/#{task2.name}[\s\S]*#{task1.name}/)
      end
    end
  end
end

factories/tasks.rb

FactoryBot.define do
  factory :task do
    name { 'test_name' }
    detail { 'test_detail' }
  end
end

エラー発生

上記のコードを実行すると、it '新しいタスクが一番上に表示される' do の部分で task1 って何?taskのことですか? とエラーが出ました。

Failure/Error: expect(page.text).to match(/#{task2.name}[\s\S]*#{task1.name}/)
NameError:
       undefined local variable or method `task1' for #<RSpec::ExampleGroups::Nested::Nested_2::Nested_2 "新しいタスクが一番上に表示される" (./spec/system/task_spec.rb:29)>
       Did you mean?  task

しかし、it '作成済みのタスク一覧が表示される' do のテストはパスしているため、
beforeの部分のcreateは成功しているはずです。
では、なぜtask1が定義されていないと怒られてしまうのでしょう?

それもそのはず。インスタンス変数でないと、メソッド外で呼び出せません。
下記の通り、beforeの定義の際に、データをインスタンス変数に代入することで、テスト成功。

before do
      @task1 = FactoryBot.create(:task, name: 'bbb')
      @task2 = FactoryBot.create(:task, name: 'ccc')
      visit tasks_path
end

さらに疑問に思ったこと

先ほどのエラーメッセージでtask1じゃなくて、taskじゃないですか?と言われておりました。

Failure/Error: expect(page.text).to match(/#{task2.name}[\s\S]*#{task1.name}/)
NameError:
       undefined local variable or method `task1' for #<RSpec::ExampleGroups::Nested::Nested_2::Nested_2 "新しいタスクが一番上に表示される" (./spec/system/task_spec.rb:29)>
       Did you mean?  task

このtaskって何?逆にそのtaskはどこに存在しているのでしょう?

自分なりの解釈

自分で書いたコードなのに自信がありません。
let!で定義している変数taskのことでしょうか。

let!(:task) {FactoryBot.create(:task, name: 'aaa')}

試しに binding.irb で確認した所、taskにはname'aaa'のデータが入っていました。
let!で定義した変数はインスタンス変数としてどこでも使えるのですね。
@はついてないけど・・・・・。

おまけ

今回のコードでは、

let! で name'aaa' のデータを作成

before で name'bbb' のデータを作成

before で name'ccc' のデータを作成


この順番でデータが作成されました。
ということは、なんとなくイメージ被りしているlet!とbeforeですが、let!のほうが実行順位が高いんですね。いや、let!のほうがネストの浅いところに記述しているので当然・・・?
今後もう少しコードを動かして考えてみようと思います。



※コードの中に不要なlet!が存在しており気持ち悪く感じられた方がいらっしゃいましたら申し訳ございません。let!は今回記載していない別の機能でのみ必要でしたが、エラー文に関係していたためコードを残しました。

参考にさせていただいた記事

使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
【Rspec】system testで並び順をテストする
【Rspec】letとlet!、beforeの違い
RSpec letとlet!とbeforeの実行されるタイミング.

ありがとうございました。

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?