RSpecの基本文法をまとめた

プログラミング

さてさて、今回はRSpecの基本的な書き方について書いていきたいと思います。

①beforeについて

前回解説した通り、基本的にはまずひな形を書きます。

そのあとは、beforeやletで前準備をしていくのですが、まずはbeforeについて。

「before do」を使うことで、あらかじめユーザーや投稿などをfactory_botに作らせることができます。

このbeforeやletなどで定義したユーザーや投稿は「/facotories」ファイルで定義したユーザーや投稿を基に作成されます。

具体的なコードは下のような感じ。

RSpec.describe Like, type: :model do
  before do
    @user = FactoryBot.create(:user, id: 1)
    @post = FactoryBot.create(:post, user_id: 1)
    @like = FactoryBot.build(:like, user_id: 1, post_id: 1)
  end
end

これで、事前にユーザー、投稿、いいね!を作成しています。

factory_botの定義の仕方については前回の記事「RSpecを始める時の準備をまとめた」を読んでみてください。

②describeとcontextとitについて

このdescribeやcontextやitは具体的にどの部分の何をテストするのかということを書き手や読み手に分かりやすくするために書きます。

具体的には、下のようなコード。

require 'rails_helper'

RSpec.describe Post, type: :system do
  
  before do
      FactoryBot.create(:user, name: 'test', email: 'test@example.com', image_name: 'default_user.jpg')
      FactoryBot.create(:post, content: '最初の投稿', user_id: 1, post_image: 'default_post.jpg', post_document_image: 'test.jpg')
      visit "/login"
      fill_in 'email', with: 'test@example.com'
      fill_in 'password', with: 'password'
      click_button 'ログイン'
    end
    
  describe '投稿機能' do
    context '投稿一覧' do
      it 'testが作成した投稿が投稿一覧に表示される' do
        visit posts_path
        expect(page).to have_content '最初の投稿'
        expect(page).to have_selector("img[src$='default_post.jpg']")
      end
    end
end

これは投稿機能の中の投稿一覧について、実際に投稿したデータが投稿一覧にしっかり表示されているかを確認するテストになっています。

beforeの中でユーザーと投稿を事前に作成していて、ログインもしてあるので、本文の中は、いきなり投稿一覧ページに飛んで確認しに行けているわけです。

describeやcontextやitの中身は英語で書く場合も多いですが、僕自身は日本語でも問題ないと思っています。

テストは読みやすさ重視、書きやすさ重視の方が結果的には良いというのが僕の考えです。

③letについて

より高度な技術でletというのがあります。

これは、まあ、だいたいbeforeと同じようなものだと思ってください。

つまり、事前にユーザーや投稿を定義しておくというものです。

具体的には、下のようなコード。

require 'rails_helper'
RSpec.describe User, type: :system do
   
      let(:user) { FactoryBot.create(:user, name: 'test', email: 'test@example.com', image_name: 'default_user.jpg') }

describe 'ユーザー新規登録' do
    
         context 'フォームの入力値が正常' do
          it 'ユーザーの新規作成が成功' do
            #ユーザー新規登録画面へ遷移
            visit new_user_path
            #ユーザー名にtestと入力
            fill_in 'name', with: 'test'
            #メールアドレスにtest@example.comと入力
            fill_in 'email', with: 'test@example.com'
            #パスワードにpasswordと入力
            fill_in 'password', with: 'password'
            #ログインと記述のあるsubmitをクリック
            click_button '新規登録'
            #users_index_pathに遷移することを期待する
            expect(current_path).to eq "/users/1"
            #遷移されたページに'ユーザー登録が完了しました'の文字列があることを期待する
            expect(page).to have_content 'ユーザー登録が完了しました'
            
            expect(page).to have_content 'test'
          end
        end
end

letでユーザーを事前に定義しています。

beforeと何が違うの?というもっともな疑問を持たれる方もいると思いますので、少しだけ深く解説すると、letはbeforeと違って遅延評価をしているというのが最大の違いになります。

どういうことかというと、beforeはその文字通り、事前にユーザーや投稿を作成しています。

しかし、letは事前に定義したユーザー等は実は必要になるまで呼び出されていません。

そして、必要になったときにジャスト・イン・タイムで必要な情報をお届けしているわけですね。

上の例だと、

  1. visit new_user_path
  2. new_user_pathってどのユーザーのパスだ?
  3. あー、let(:user)か←ここではじめて呼び出される。

みたいな感じになります。

ちなみに、letは遅延評価であるがゆえにエラーになってしまうこともあるので、そんなときは「let!」を使いましょう。

この「!」を付けることで、beforeとまったく同じように事前に作成されるようになります。

しかしさっきも書いたように、テストは書きやすさ重視で書いた方が良いと思うので無理にletなんか使わずにbeforeを使ってしっかりと書いて、慣れてきたらそろそろlet使ってみるかぁで全然いいと思いますよ。

以上!

コメント

タイトルとURLをコピーしました