LoginSignup
12
5

More than 5 years have passed since last update.

RSpecのインストール方法と動かし方

Last updated at Posted at 2019-02-02

記事の内容

RSpecをインストールして動作させるまでの手順

前提

  • Ruby 2.3.3
  • Rails 5.2.2
  • RSpec 3.8

内容

Rialsプロジェクトを作る

以下コマンドを順番に実行してRailsプロジェクトを作る

console
mkdir rspec_test
cd rspec_test
rails new .

注意
※プロジェクト名をRSpecにするとうまく動かないので注意

RailsプロジェクトにRSpecをインストールする

gemファイルの「test」にRSpecを追加する。

Gemfile
group :test do
 ...
 ...
 gem 'rspec-rails'
end

gemファイルの内容をインストールする

console
bundle install

rspecの構成ファイル/構成フォルダを作成する。

console
// 実行するとspecフォルダができる
rails g rspec:install

テスト対象クラスを作る

今回はtitleカラムを持つTodoモデルをテスト対象とする。
以下のコマンドを実行してテスト対象クラスを作る。

console
rails g model todo

マイグレーションファイルを下記のように編集する。

20190202080103_create_todos.rb
class CreateTodos < ActiveRecord::Migration[5.2]
  def change
    create_table :todos do |t|
      t.text :title
      t.timestamps
    end
  end
end

下記のコマンドを実行してマイグレーションを行う。

console
rails db:migrate

テストコードを作成する

以下のコマンドを実行してテストコードの雛形を作成する。

console
rails g rspec:model todo

テストコードを記述する。

todo_spec.rb
require 'rails_helper'

RSpec.describe Todo, type: :model do
  describe "#title" do
    context "空の場合" do
      let(:todo){Todo.new(title:"")} #titleが空文字のTodoオブジェクトを生成

      it "エラーを返す" do
        todo.valid? #バリデーションを実行
        expect(todo.errors[:title]).to be_present #期待結果:エラーメッセージが存在する
      end
    end

    context "Nullの場合" do
      let(:todo){Todo.new(title:nil)} #titleがNullのTodoオブジェクトを生成

      it "エラーを返す" do
        todo.valid? #バリデーションを実行
        expect(todo.errors[:title]).to be_present #期待結果:エラーメッセージが存在する
      end
    end

    context "値が入っている場合" do
      let(:todo){Todo.new(title:"this is title")} #titleに値が入っているTodoオブジェクトを生成

      it "エラーを返さない" do
        todo.valid? #バリデーションを実行
        expect(todo.errors[:title]).to be_blank #期待結果:エラーメッセージが存在しない
      end
    end
  end
end

describeに「テスト概要」を記述して、contextに「テスト条件」を記述して、itに「期待結果」を書く感じ。
期待結果の書き方は、下記の通り。

expect(検証対象変数).to [期待結果]

より詳細なexpectの書き方は、こちらの記事がわかりやすい。

テストを実行する

下記のコマンドを実行してテストを実行する

console
rspec

下記のような結果が返ってくる。

console
  1) Todo#title 空の場合 エラーを返す
     Failure/Error: expect(todo.errors[:title]).to be_present
       expected `[].present?` to return true, got false
     # ./spec/models/todo_spec.rb:9:in `block (4 levels) in <top (required)>'

  2) Todo#title Nullの場合 エラーを返す
     Failure/Error: expect(todo.errors[:title]).to be_present
       expected `[].present?` to return true, got false
     # ./spec/models/todo_spec.rb:17:in `block (4 levels) in <top (required)>'

Finished in 0.04147 seconds (files took 1.89 seconds to load)
3 examples, 2 failures

Failed examples:

rspec ./spec/models/todo_spec.rb:7 # Todo#title 空の場合 エラーを返す
rspec ./spec/models/todo_spec.rb:15 # Todo#title Nullの場合 エラーを返す

「空の場合」と「Nullの場合」はテストに失敗していることがわかる。
「値が入っている場合」は期待通りの結果になっているので、テストが成功していることがわかる。

テスト対象コードを修正する

「空の場合」と「Nullの場合」に、テストの期待結果通りバリデーションエラーが発生するようにコードを修正する。

todo.rb
class Todo < ApplicationRecord
    validates :title, presence: true
end

テストを実行する

以下のコマンドを実行してテストを行う。

console
rspec

下記のような結果が返ってくるはず。

console
Finished in 0.02788 seconds (files took 0.95229 seconds to load)
3 examples, 0 failures

テスト失敗がなくなっていることがわかる。

(2019/2/2 追記) Subjectを使ったRSpecの書き方

Subjectメソッドを使うと、もっと簡潔に書ける。

todo_spec.rb
require 'rails_helper'

RSpec.describe Todo, type: :model do
  describe "#title" do
    #テストする対象ロジック
    subject{ todo.valid?; todo.errors[:title] }

    context "空の場合" do
      # titleが空のオブジェクトを作る
      let(:todo){Todo.new(title:"")}

      # titleが空のときの期待結果を定義する
      it { should be_present }
    end

    context "Nullの場合" do
      let(:todo){Todo.new(title:nil)}
      it { should be_present }
    end

    context "値が入っている場合" do
      let(:todo){Todo.new(title:"this is title")}
      it { should be_blank }
    end

  end
end

subjectに「テスト対象の処理」を記述して、itに「その期待結果」を記述する。
subjectを使うとitの方の記述が簡単になる。

感想

JUnitしか書いたことがなかったが、RSpecは「振る舞い駆動」のテストケースを書きやすくて良いなと思いました。TDDもやりやすいんじゃないかな。

終わり。

12
5
0

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
12
5