4
1

初めてのRSpecで学んだこと

Last updated at Posted at 2023-11-26

課題で出てきて、初めて取り組んだRSpec!
色々なポイントを学んだので備忘録として残しておく。
初学者なので、間違ってる点などあればご指摘下さい。

バージョン

  • ruby 3.2.2
  • Rails 6.1.7.6

作成しているアプリはタスク管理アプリ

SystemSpecの基本

Factoryを使用したテスト

Factoryとは、railsでテストをする時用のテストデータを作成してくれるテンプレートのこと。
factory_bot_rails というgemをインストールすることで使用できるようになる。
(Factoryを使用する手順(インストール方法など)は今回は省略。)
今回のタスク管理アプリで、「一覧画面に遷移した場合」→「作成済みのタスク一覧が表示される」というテストコードを書く際、Factoryを使用した。

spec/factories/task_spec.rb
FactoryBot.define do
  factory :task do
    name { 'パパ' }
    content { '日曜日歯医者' }
  end
end

まず、 spec/factories/task_spec.rb の中に、テストデータの定義的なものを書く。
上記のように書くことで、テストデータの基本内容は、 name が、「パパ」、 content が「日曜日歯医者」となる。

spec/system/task_spec.rb
require 'rails_helper'
RSpec.describe 'タスク管理機能', type: :system do
  describe '一覧表示機能' do
    context '一覧画面に遷移した場合' do
      it '作成済みのタスク一覧が表示される' do
        FactoryBot.create(:task)
        visit tasks_path
        expect(page).to have_content '日曜日歯医者'
      end
    end
  end
end

このコードの説明。
6行目の

FactoryBot.create(:task)

の一文の中の「:task」によって、 spec/factories/task_spec.rb の中の、2行目

factory :task do

の部分の task が繋がり、 spec/factories/task_spec.rb で定義した内容を元にテストデータが作成される。
この場合、 name が、「パパ」、 content が「日曜日歯医者」というテストデータとなる。
なので8行目の

expect(page).to have_content '日曜日歯医者'

の一文で、「日曜日歯医者」の文字がページの中に含まれているかを確認しており、このテストは成功すれば、プログラムは正しいということ。

また、以下のような書き方もある。

spec/system/task_spec.rb
require 'rails_helper'
RSpec.describe 'タスク管理機能', type: :system do
  describe '一覧表示機能' do
    context '一覧画面に遷移した場合' do
      it '作成済みのタスク一覧が表示される' do
        FactoryBot.create(:task, content: '日曜日買い物')
        visit tasks_path
        expect(page).to have_content '日曜日買い物'
      end
    end
  end
end

違いは6行目で

FactoryBot.create(:task, content: '日曜日買い物')

「content: '日曜日買い物'」が有るかどうか。
このように content: '日曜日買い物' を入れることで、 spec/factories/task_spec.rb で定義した基本のテストデータ、 name が、「パパ」、 content が「日曜日歯医者」というのを
name が、「パパ」、 content が「日曜日買い物」というテストデータに変えることができる。

「タスクを新規作成した場合、新規登録が正常に完了するか」というテストのコード

これを考える際、私は

require 'rails_helper'
RSpec.describe 'タスク管理機能', type: :system do
  describe '新規作成機能' do
    context 'タスクを新規作成した場合' do
      it '新規登録が正常に完了する' do
        FactoryBot.create(:task)
        visit task_path(Task.last)
        expect(page).to have_content ’投稿を作成しました!’
        expect(page).to have_content '日曜日歯医者'

とすると、エラーになってしまった💦「投稿を作成しました!」なんて無いよーと言ってます。

スクリーンショット 2023-11-25 15.19.47.png

この「’投稿を作成しました!’」というのは

def create
    @task = Task.new(task_params)
      if @task.save
        redirect_to task_path(@task.id), notice: "投稿を作成しました!"
      else
        render :new
      end
end

上記のように、新規タスク作成した時に、 notice にて、投稿を作成しました、と出るようにしていたので、新規作成後の遷移したページに「投稿を作成しました!」という表示があれば、テストできるのではないかと考えたのですが、
なぜ、これではテストに失敗してしまうのかというと

このFactoryBotで作成されたテストデータによって作成されたページというのは、tasks_controller の中の create アクションは通過していない!!そのため、「投稿を作成しました!という文は無い! 

とメンターさんに教えてもらいました!!なるほど!!確かにそうだ!!

ということで、この新規作成完了のテストは FactoryBot は使わず

describe '新規作成機能' do
  context 'タスクを新規作成した場合' do
    it '作成したタスクが表示される(新規登録が正常に完了する)' do
      visit new_task_path
      fill_in 'task_name', with: 'パパ'
      fill_in 'task_content', with: '日曜日歯医者'
      click_on 'Create Task'
      expect(page).to have_content '日曜日歯医者'
    end
  end
end

というコードに書き直し、無事課題をクリアすることができました!
ちなみに、この fill_in を使用する際にもポイントがあり、

fill_in 'task_name', with: 'パパ'
fill_in 'task_content', with: '日曜日歯医者'

この task_nametask_content の部分を、

fill_in 'name', with: 'パパ'
fill_in 'content', with: '日曜日歯医者'

というように、カラム名をそのまま書きがちだが、これだとエラーになることがあるとのこと。
カラム名そのままでなく、Railsが自動で作成してくれているIDを用いて指定すると、うまくいく。

スクリーンショット 2023-11-25 15.46.04.png

RSpecについての学びはこれで以上〜!お疲れ様でした!!

ちなみに、RSpecのこと以外でも、面白い学びがあったので、それも書き残しておく。

visit task_path(Task.last)

この、 task_path(Task.last) の部分。
task_path  って、
task_path(task.id)  というように、後に id を指定して、 path の先を指定するイメージだったけど、今回は、 task_path(Task.last) というように、 id を指定していないのにうまくプログラムが動くのが疑問だったので、調べてみた。

まず、Railsガイドで、 last メソッドの使い方を調べてみた。
last とはモデルの最後のレコードを取得するメソッドである。

スクリーンショット 2023-11-26 15.22.53.png

Railsガイドによると、 id も含めて、最後のレコード全体を取得しているのがわかるけど、なんでこれで id を取得できるのかが疑問だったのでメンターさんに聞いてみた。
すると、
Railsが、このデータ全体から id のみを取得してくれる、とのこと!! Railsの機能らしい!!
おー!そうなんだ!
なので、実は、 task_path(task.id) というのも、 task_path(task) としてしまっても、きちんと動くのだそう!!
へぇーーー!そうだったんだ!!
初学者の私にとっては、とっても面白く、100「へぇ」くらいの学びでした!(笑)

本日は以上!お疲れ様でした!

4
1
1

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