【Ruby on Rails】Rspecのテストをやってみよう!


【Ruby on Rails】Rspecのテストをやってみよう!

プログラミング初心者の中には、Rspecに関して苦手意識を持っている方もおられるかもしれません。実はRspecは覚える構文も少なく、意外と難しくはありません。

本記事では実際にRspecのテストコードを書き、理解を深めていけるようになっています。ぜひ参考にしてみてください。

目次
  1. アプリケーションの雛形を作成しよう
  2. Rspecの準備をしよう
  3. Rspecのテストコードを書いてみよう①
  4. Rspecの構文を理解しよう
  5. テストの宣言をおこなう「describe」
  6. テストで確認することを宣言する「it」
  7. 「〜の場合は」を表現する「context」
  8. 変数を宣言する「let!」
  9. Rspecのテストコードを書いてみよう②
  10. まとめ

アプリケーションの雛形を作成しよう

まずはRspecでテストをおこなうために、「Scaffold」を使ってアプリケーションの雛形を作成していきます。Scaffoldはアプリケーションを動かすのに、必要最低限の機能を備えたものを簡単に作成可能です。

まずはターミナル(コマンドプロンプト)を開き、下記コマンドを実行してください。

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

ここまでのコマンドを実行すると、下画像が表示されます。

image

次にScaffoldにより作成されたPostモデルに対して、バリデーションを設定していきます。バリデーションとは、例えば入力フォームに何も入力されていないと、エラーを発生させる機能を作るために必要なものです。

それでは、「post.rb」を開き、下記コードを貼り付けてください。

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

モデルに関連するファイルを編集したので、一度サーバーを再起動しましょう。 下記コマンドを実行すると再起動できます。

//サーバーを停止
Ctrl + C
//サーバーを起動
rails s

ここまででアプリケーションの準備は完了です。

Rspecの準備をしよう

この章では、Rspecでテストをおこなうために必要なgemのインストールやテストのコードについて解説していきます。まずはGemfileを開き、下記コードを追記してください。

Rspecを用いたテストは開発環境でおこなうものなので、「group :development do」のグループ内に「gem 'rspec-rails'」と記載しています。

gemをインストールするために、ターミナルで「bundle install」を実行してください。次にテストコードの実行に必要なファイルを準備しいきましょう。

ターミナルで下記コマンドを実行してください。

rails g rspec:install
//下記のファイルが作成される
//.rspec & spec/spec_helper.rb & spec/rails_helper.rb

rails g rspec:model article
//下記のファイルが作成される
//spec/models/post_spec.rb

コマンドを実行すると、「post_spec.rb」など必要なファイルが作成されたことが分かります。

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

テストをおこなうためのファイルを作成できたので、実際にテストコードを書いていきます。細かい構文に関しては、後ほど解説するので、まずはRspecのテストの雰囲気をつかんでください。

では、「post_spec.rb」を開き、下記コードを貼り付けてください。デフォルトで書かれている内容は、消して問題ありません。

require 'rails_helper'

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

Rspecでテストコードを書く際は、3点を意識しましょう。

①テストで何を確認したいのか決める
②確認するために必要なデータを作成する
③①で決めたことが実際に起こるか確認する

上記のコードでは、下記3点をおこなっています。
①タイトルが2文字以上10文字以下かつコンテンツが入力されている場合に、エラーが出ないことを確認する
②Post.new….でダミーデータを作成する
③「bundle exec rspec spec/models/post_spec.rb」でテストを実行する

ではターミナルを開き、下記コマンドを実行して結果を確認してください。

bundle exec rspec spec/models/post_spec.rb

//実行結果
.

Finished in 0.06612 seconds (files took 5.6 seconds to load)
1 example, 0 failures

緑の文字が現れたら、テストに問題なく合格したしるしです。では次にテストに失敗するケースをみていきましょう。

「post_spec.rb」を開き、下記コードに書き換えてください。 今回のテストでは、①タイトルが10文字以上②コンテンツが空のため、バリデーションエラーが発生するはずです。

require 'rails_helper'

RSpec.describe Post, type: :model do
  context 'タイトルと内容が入力されている場合' do
    let!(:post) do
      Post.new({ title: 'これは10文字以上のタイトルです。', content: '' })
    end
    it '記事を保存できる' do
      expect(post).to be_valid
    end
  end
end

コードを貼り付けたら、ターミナルで下記コマンドを実行して結果を確認してみましょう。

bundle exec rspec spec/models/post_spec.rb


//実行結果
F

Failures:

  1) Post タイトルと内容が入力されている場合 記事を保存できる
     Failure/Error: expect(post).to be_valid
       expected #<Post id: nil, title: "これは10文字以上のタイトルです。", content: "", created_at: nil, updated_at: nil> to be valid, but got errors: Title is too long (maximum is 10 characters), Content can't be blank
     # ./spec/models/post_spec.rb:9:in `block (3 levels) in <top (required)>'

Finished in 0.1769 seconds (files took 6.48 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/models/post_spec.rb:8 # Post タイトルと内容が入力されている場合 記事を保存できる

上記のエラー文が赤文字で表示されればOKです。

Rspecの構文を理解しよう

ここまででRspecの雰囲気をつかめたと思うので、テストコードを書く際に必要な構文について解説していきます。

テストの宣言をおこなう「describe」

「describe」は、「〇〇を確認するテストを行います」という宣言をするための構文です。本記事では、下記のように使用されています。

RSpec.describe Post, type: :model do

ちなみにdescribeのあとは日本語でもOKです。

RSpec.describe “記事”, type: :model do

テストで確認することを宣言する「it」

テストで確認することは、「it」を使って表現可能です。本記事では、下記のように使用されています。

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

Rspecのテストコードは誰がみても分かるように記述されているのがベストです。 例えば下記のような記述だと、「何を保存するのか」という疑問が生まれてしまうので注意してください。

 it '保存できる' do

主語と述語を意識して書くと良いでしょう。

「〜の場合は」を表現する「context」

「〜の場合は」を表現する場合、「context」を使用します。本記事では下記のように使用されています。

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

itの場合と同じく、誰がみても分かるように宣言するのがコツです。

変数を宣言する「let!」

最後に「let!」についてみていきましょう。テストコードで使用する変数は、「@post」のようなインスタンス変数で宣言するのではなく、「let!」を使うのが一般的です。

本記事では、下記のように使用しています。

let!(:post) do

仮にインスタンス変数を用いて、テストコードを書き直すと下記のようになります。 はじめは慣れないかもしれませんが、積極的に「let!」を使いましょう。

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

Rspecのテストコードを書いてみよう②

Rspecで使用する構文について理解できたので、もう1つテストコードを書いてみましょう。「post_spec.rb」を開き、下記コードに書き換えてください。

require 'rails_helper'

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

コードを貼り付けたら、下記コマンドを実行して結果を確認してください。 緑の文字が表示されればOKです。

bundle exec rspec spec/models/post_spec.rb

//実行結果
.

Finished in 0.10166 seconds (files took 4.76 seconds to load)
1 example, 0 failures

ではテストコードについてもう少し詳しくみていきましょう。下記コードは、タイトルが2文字以下の場合に、「is too short (minimum is 2 characters」というエラーメッセージが表示されることを確認しています。

 expect(post_title_one_letter.errors.messages[:title][0]).to eq('is too short (minimum is 2 characters)')

実はバリデーションのエラーメッセージは「errors.messages」に格納されています。確認のため、下記コードをテストコードに貼り付けてください。

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

再度ターミナルで下記コマンドを実行して、結果を確認すると下記の結果が追加されています。これがエラーメッセージの正体です。

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

エラーメッセージは上記のようにハッシュになっているので、その中身を取り出すために、「post_title_one_letter.errors.messages[:title][0]」という記述をしています。

これでRspecに関する解説は以上です。 お疲れ様でした。

Rubyでのサービス開発スキルが身に付く

CodeCampの無料体験はこちら

まとめ

Rspecのテストについて解説してきました。本記事で紹介した構文を再度復習してみて、理解を深めてみてはいかがでしょうか。


関連記事

ヤマモト
この記事を書いた人
ヤマモト
\ 無料体験開催中!/自分のペースで確実に習得!
オンライン・プログラミングレッスンNo.1のCodeCamp