【RSpec】System Spec
- 今回の記事の目的
- 実行するテストケースを限定したいとき
- 別タブで開いたページをテストしたいとき
- 確認画面のページ操作したいとき
- ApplicationHelperで定義したメソッドをRSpecで使いたいとき
- Updateのテストがうまくいかない。値が更新されないとき
- FactoryBotのtraitを使う
- Capybaraのメソッドについて
今回の記事の目的
System Specのコードを書いていて迷うことがいくつかあったので、復習していきます。
前回の記事同様、RSpec,FactoryBot and Capybaraは設定済です。
実行するテストケースを限定したいとき
it
の代わりにfit
を使います。
spec_helper.rb
で config.filter_run_when_matching :focus
と設定しているため、各テストの頭文字にf
をつけることで、focus: true
を設定できます。
別タブで開いたページをテストしたいとき
リンクをクリックし、遷移したページ先の項目についてテストしたいときは、within_window(windows.last)
で最後に開いたタブを指定します。
it 'Project詳細からTask一覧ページにアクセスした場合、Taskが表示されること' do visit project_path(project) click_link 'View Todos' #これでページ遷移する。 within_window(windows.last)do #以下、遷移先の内容 expect(page).to have_content task.title expect(Task.count).to eq 1 expect(current_path).to eq project_tasks_path(project) end end
withinメソッド
Capybaraのwithin
メソッドは、ページ内の特定のエリアやアクションを指定できます。
within_window
はウィンドウ画面の指定。
確認画面のページ操作したいとき
何かの項目を削除するとき、「本当に削除しますか?」とアラートメッセージがでますが、それの操作は以下のようにします。
#許可するとき page.driver.browser.switch_to.alert.accept #拒否するとき page.driver.browser.switch_to.alert.dismiss
ApplicationHelperで定義したメソッドをRSpecで使いたいとき
何も考えず使おうとしたら、使えませんでした。私はこういうところをよく忘れるので注意します。
当たり前ですが、include
で読み込む必要があります。
今回は、systemspecファイルでrequire 'rails_helper'
しているので、spec/rails_helper.rb
内でapplication_helper.rb
を読み込む設定をします。
config.include ApplicationHelper #追加
これで、ApplicationHelperで定義したメソッドshort_time
がRspecでも使用できます。
it 'Taskを編集した場合、一覧画面で編集後の内容が表示されること' do fill_in 'Deadline', with: Time.current #今の時刻にdeadlineを更新する。 click_button 'Update Task' click_link 'Back' expect(find('.task_list')).to have_content(short_time(task.reload.deadline)) #ここ expect(current_path).to eq project_tasks_path(project) end
Updateのテストがうまくいかない。値が更新されないとき
上のコードの解説です。
最初、short_time(task.deadline)
としたら、更新前の日時しか取得できなかった。更新出来てないってこと?
謎だったけど、その場しのぎでTime.current
にしてしまいました。
そしてちゃんと調べたら、ドンピシャな記事がありました。
DBの値が更新されても、インスタンスの値は更新されない。task.reload.deadline
とする。
これでテストが通りました。
rspecでupdateのテストを通せない初心者が疑うべきこと - Qiita
findメソッド
Capybaraのfind
メソッドは特定の要素を指定できます。
さきのコード例では、find('.task_list')
で、viewで定義しているclass = "task_list"
を指定しています。
strftimeメソッド
Rubyのメソッドです。
時刻を format 文字列に従って文字列に変換した結果を返します。
Time#strftime (Ruby 2.7.0 リファレンスマニュアル)
以下のように使います。
expect(page).to have_content(Time.current.strftime('%Y-%m-%d'))
FactoryBotのtraitを使う
属性をいろいろ指定して定義したいとき、trait
を使います。
テスト内で何度も同じ属性を指定して呼び出していると、コードの重複が生じてしまいます。
traitを使えばスッキリとした見た目になります。
また、添付ファイルを予めセットすることもできます。(やり方は『everyday Rails』P174 )
#trait定義前 let!(:task) {create(:task, project_id: project.id, status: :done, completion_date: Time.current.yesterday)} #trait定義後 let!(:task) { create(:task, :done) }
FactoryBot.define do factory :task do sequence(:title, "title_1") status { rand(2) } from = Date.parse("2019/08/01") to = Date.parse("2019/12/31") deadline { Random.rand(from..to) } association :project trait :done do #ここ status { :done } completion_date { Time.current.yesterday } end end end
Capybaraのメソッドについて
公式は例もあって分かりやすい
GitHub - teamcapybara/capybara: Acceptance test framework for web applications