【Rails】RSpecでテストコードを書いてみよう【モデル編】

本記事はこんな方に向けて書いています。

  • RSpecを使ったことがない人
  • RSpecのitやdescribeなどの使い方が分からない人
  • とりあえずテストってどんなものか知りたい人

本記事では、Scaffoldで素早くアプリを作成し、簡単にRSpecによるテストをおこなえるように解説しています。

僕も最初は「RSpecって難しそう!」と感じていましたが、意外と覚えることは少ないです。ぜひ手を動かしてRSpecを実感して欲しいです。

STEP1 Scaffoldでアプリの雛形をつくろう

Railsの「Scaffold」を使うと、簡単に必要最低限の機能を備えたアプリを作成できます。まずはターミナル上で下記コマンドを実行しましょう。

rails new rspec_practice
rails g scaffold article title:string content:string
rails db:migrate
rails s

ここまで実行すると下の画面が表示されるます。

次に作成されたArticleモデルに対してバリデージョンを設定していきます。
バリデーションとは、例えば、記事のタイトルが未入力の場合は、エラーメッセージが出ると行ったような感じです。

では、article.rbを開き下記コードを追記してください。

class Article < ApplicationRecord
	validates :title, presence: true
	validates :title, length: {minimum:2, maximum: 25}

	validates :content, presence: true
end

サーバーを再起動して、次の章に進みましょう。

STEP2 RSpecの準備をしよう

次はRSpecの準備をしていきます。
RailsのGemfileを開き、下記を追加してください。

RSpecはリリースする前に正常に動くか確認するものなので、以下の場所に書くのが適切です。

group :development do
  gem 'rspec-rails'
end

追記できたら、ターミナルで「bundle install」を実行しましょう。
インストールが完了すると、「spec」フォルダと「.rspec」ファイルが作成されます。

次にテストコードを書くファイルを作成していきます。
ターミナルで下記コマンドを実行してください。

rails g rspec:model article

実行すると下画像のようなファイルが作成されます。
今回はこのフォルダにテストコードを書いていきます。

article.rbに対するテストフォルダ

STEP3 RSpecのテストコードを書いてみよう①

では実際にテストコードを書いていきます。
テストコードは以下のような構成になっていると理解しておいてください。

①何を確認したいのか?

②確認するためのデータを作成する

③①で決めたことが実際に起こるか確認する

では、article_spec.rbファイルを開きます。
まずは、コードを下記の状態にしてください。
(デフォルトでいらないコードが書かれている場合があるので、削除しておきます。)

require 'rails_helper'

RSpec.describe Article, type: :model do

end

まずは記事のタイトルと内容が入力されている場合のテストコードを書いていきます。先程の構成に沿って考えていきましょう。

①何を確認したいのか?
→タイトルと内容が入力されていれば、保存できること

②確認するためのデータを作成する
→Article.newでダミーデータを作れば良さそう

③①で決めたことが実際に起こるか確認する

では、再びarticle_spec.rbを開き、下記コードを貼り付けてください。

require 'rails_helper'

RSpec.describe Article, type: :model do
  context 'タイトルと内容が入力されている場合' do
    let!(:article) do
      Article.new({ title: 'RSpecテスト', content: 'RSpecテストの内容' })
    end
    it '記事を保存できる' do
      expect(article).to be_valid
    end
  end
end

ターミナルで下記コマンドを実行して結果を確認してみましょう。

bundle exec rspec spec/models/article_spec.rb

下画像のように緑文字になっていれば成功です。

なんとなくテストがどんなものかイメージできたと思うので、先程のコードについて解説していきます。

テストに関する宣言は『describe』で書こう

テストコードの書き方には、様々なルールが設けられています。その中の一つが『describe』です。

describeは「今から〇〇を確認するテストコード書くよ〜」という宣言をする際に使います。今回で言うと「Articleというモデルを確認しますよ〜」という意味で使われていますね。

RSpec.describe Article, type: :model do

ちなみにdescribeの内容は日本語でもOKです。

RSpec.describe "記事", type: :model do

テストで確認することは『it』を使って書こう

テストで確認したいことは、『it』を使うというルールがあります。

先程のコードでいうとこの部分ですね。

it '記事を保存できる' do

誰がみても何を確認しているのか分かるように書くのがベストです。

〇〇の場合は、『context』を使って書こう

次は『context』について解説していきます。
先程のコードでも登場していましたね。

context 'タイトルと内容が入力されている場合' do

contextには、テストの条件を書きます。

事前に変数を設定する場合は、『let!』を使おう

テストコードで使用する変数を定義する場合、『let!』を使いましょう。

テスト内で使用する変数は@articleというように『インスタンス変数』を使っても問題なくテストは通りますが、下記のような書き方は一般的ではありません。

RSpec.describe Article, type: :model do
  context 'タイトルと内容が入力されている場合' do
    before do
      @article = Article.new({ title: 'RSpecテスト', content: 'RSpecテストの内容' })
    end
    it '記事を保存できる' do
      expect(@article).to be_valid
    end
  end
end

テストコード内で何度も使用する変数はlet!を使うようにしましょう。

STEP4 RSpecのテストコードを書いてみよう

今度は別のテストコードを書いてみましょう。
テストの構成は次の通りです。

①何を確認したいのか?
→タイトルが1文字の場合、エラーメッセージが出る

②確認するためのデータを作成する
→Article.newでtitleが1文字のダミーデータを作れば良さそう

③①で決めたことが実際に起こるか確認する


では、次のコードをarticle_spec.rbに貼り付けてテストを実行してみましょう!

require 'rails_helper'

RSpec.describe Article, type: :model do
  context 'タイトルの文字が1文字の場合' do
    let!(:article_title_one_letter) do
      Article.create({ title: '1', content: 'RSpecテストの内容' })
    end
    it 'タイトルのエラーメッセージが出ること' do
      expect(article_title_one_letter.errors.messages[:title][0]).to eq('is too short (minimum is 2 characters)')
    end
  end
end

引っかかりそうなところは、let!で宣言している変数名とitの中身かなと思います。

変数名は何を表しているか直感的に分かるように書くのが基本なので、「タイトルが1文字の記事」という意味で、「article_title_one_letter」としました。

正しいエラーメッセージが表示されるか確認しよう

次にitの中身ですが、エラーメッセージが、「is too short (minimum is 2 characters)」となることを確認しています。

下記コードはタイトルに対するエラーメッセージを取り出すコードになっています。

article_title_one_letter.errors.messages[:title][0]

なぜこんなコードになるのか理解しづらい方のために、エラーメッセージがどのような構造になっているのか確認してみましょう!!

require 'rails_helper'

RSpec.describe Article, type: :model do
  context 'タイトルの文字が1文字の場合' do
    let!(:article_title_one_letter) do
      Article.create({ title: '1', content: 'RSpecテストの内容' })
    end
    it 'タイトルのエラーメッセージが出ること' do
      #下記を追記
      puts article_title_one_letter.errors.messages
      expect(article_title_one_letter.errors.messages[:title][0]).to eq('is too short (minimum is 2 characters)')
    end
  end
end

テストを実行すると下記のような結果がえられると思います。
これがエラーメッセージの内容です。

{:title=>["is too short (minimum is 2 characters)"]}


実はエラーメッセージはハッシュになっているのです!
つまり先程の

article_title_one_letter.errors.messages[:title][0]


を文字で説明するとこんな感じですね。

①エラーメッセージのハッシュから、キーが「title」の値を取り出す。

②取り出した値は配列になっているので、1番目(インデックスが0)の要素を取り出す。

ハッシュから値を取り出す方法が分からない人は、下の記事を参考にしてください。

【Ruby】ハッシュのシンボルについて解説【初心者向け】

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です