Help us understand the problem. What is going on with this article?

【RSpec3.9】苦手意識克服!一番シンプルな文法で簡単なテストを書いて理解してみよう

はじめに

これからRSpecを導入しようとされている方の中で、

  • テストに対する抵抗感をなくしたい
  • まずは簡単なテストの書き方を知りたい

という方向けに書きました。

RSpecの超基本文法とそれを使ったテストの例を以下4つの視点で1つずつ掲載しています。

  1. Model
  2. Controller
  3. View
  4. Routing

参考になれば幸いです。

【参考にさせて頂いた記事】
使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita
使えるRSpec入門・その2「使用頻度の高いマッチャを使いこなす」 - Qiita
使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」 - Qiita
Ruby on Rails のテストフレームワーク RSpec 事始め - Qiita

この記事が役に立つ方

  • RSpecでテストを書いたことがない方

この記事のメリット

  • RSpecへの抵抗感がなくなる

環境

  • OS: macOS Catalina 10.15.1
  • シェル: zsh
  • Ruby: 2.6.5
  • Rails: 5.2.3
  • RSpec: 3.9.0

【事前準備】

今回はscaffoldを使ったアプリケーションを例にしますので、3ステップで事前準備をしておきましょう。

1. scaffoldでアプリケーションを作成しておく

$ rails g scaffold user name:string email:string

2. RSpecをインストールし、テスト用ファイルを作成する

Gemfile
group :development, :test do
  gem `rspec-rails`
end

$ bundle install

$ rails g rspec:install

3.テストの実行方法の把握

$ rspec

上記で全テストが走りますので、テストを書いたら走らせてみましょう。

次に基本文法を見ていきます。

基本文法

require 'rails_helper'

RSpec.describe テスト対象, テストの種類 do
  describe 'テスト対象' do
    it '期待する内容を言葉で書く' do
      期待する動作をコードで書く
    end
  end
end

※実際は他にcontextbeforeなども使いますが、本記事では超シンプルなテストを例にします。

基本文法だけ見てもよく分からないと思いますので、さっと目を通して以下具体例に移りましょう。

具体例

MVC+Routingそれぞれに対し、1つずつ超シンプルなテストを書いて試していきます。

それぞれ、動作するテストのみ記載していますので、自分でいじってみて失敗するかどうかも確認するほうが良いと思います。

1.Model

バリデーションが正しく動作するかをテストしたい

Userモデルに以下のようなバリデーションがかかっていて、それをテストしたいとします。

models/user.rb
class User < ApplicationRecord
  with_options presence: true do
    validates :name
    validates :email
  end
end

では、テストを書いてみましょう。
最初に以下コマンドを実行し、テストの雛形を作成しましょう。

$ rails g rspec:models user

spec/models/user_spec.rb
が出来ているはずなので、以下のように記述して下さい。

spec/models/user_spec.rb
require 'rails_helper'

RSpec.describe User, type: :model do
  describe 'Userモデルのバリデーションテスト' do
    it 'nameとemailに値があれば有効' do
      user = User.new(
       name: "name",
       email: "sample@example.com"
      )
      expect(user).to be_valid
    end
  end
end

【解説】

User, type: :modelでUser Modelのテストであることを明示。

userに適当な名前とメールアドレスを指定してUserモデルから新規インスタンスを作成し、それをbe_validというマッチャで有効かどうかを判定しています。


2.Controller

indexアクションで正常にページが表示されるかテストしたい

正常にページが表示されるかはHTTPレスポンスが200であると言い換えることが出来ます。

テストを書いてみましょう。
まず先程と同様、以下コマンドを実行します。

$ rails g rspec:request users

「あれ?request? controllerじゃないの?」と思いますよね。

実は、Rails5以降はcontroller_specが非推奨となっています。

controller_specでも書けるのですが、controller関連はrequest_specで記載するのが良いようです。
詳細は下記リンクより。

RSpec 3.5 がリリースされました!

では戻ります。

先程のコマンドで
spec/request/users_spec.rb
が出来ているので以下のように記述して下さい。

spec/request/users_spec.rb
require 'rails_helper'

RSpec.describe "Users", type: :request do
  describe "GET /users" do
    it "HTTPレスポンスが200になる" do
      get users_path
      expect(response).to have_http_status(200)
    end
  end
end

【解説】

"Users", type: :requestと指定することでUsersのrequest_specであることを明示。

getリクエストでusers_path(/users)を指定し、それに対するHTTPレスポンスがresponseに入ります。

そのresponseに対してhave_http_statusというマッチャで200と等しいかを確認しています。


3.View

<h1>タグ内が正しく表示されるかをテストする

app/views/users/index.html.erb
<h1>Users</h1>

index/html/erbにはこんなh1タグが記載されています。

このh1タグ内に表示されている内容が正しく表示されているかをテストしてみましょう。

まずはテスト用のファイルを以下のように作成します。

$ rails g rspec:view users index

spec/views/users/index.html.erb_spec.rb
が出来ているので、以下のように記述して下さい。

spec/views/users/index.html.erb_spec.rb
require 'rails_helper'

RSpec.describe "users/index", type: :view do
  describe 'index.html.erbのテスト' do
    it 'h1タグ内にUsersが表示されているかどうか' do
      visit users_path
      expect(page).to have_selector('h1', text: 'Users')
    end
  end
end

【解説】

users/indexviewのテストであることを最初に明示。

visitの後にusers_pathを指定することでindex.html.erbにアクセス。

expect(page)で今いるページを明示、have_selectorというマッチャで'h1'にUsersが表示されているかをテストしています。
...

※実は上記テストはうまくいきません。

騙したようで申し訳ありません。テストを実行したら、

NoMethodError: undefined method 'visit'

というエラーが出ませんでしたか?
実は自分もここで手間取りました。

ググるとかなり沢山記事が出てくるので、良くあるエラーなんだと思います。

原因はgemcapybaraがRSpecに読み込まれていないことです。

visitcapybaraの中で定義されているDSL(ドメイン指定言語)のため、読み込むために設定を追加しなければいけません。

spec/spec_helper.rb
を開いて以下のように2行追記して下さい。

spec/spec_helper.rb
...

require 'capybara/rspec' # ここに追記

RSpec.configure do |config|

config.include Capybara::DSL # ここに追記

...

end


この設定で読み込まれるCapybara::DSLで定義されているDSL一覧は以下で確認することができます。

もし他にNoMethodErrorが出たら参考にしてみるのも良いかもしれません。

capybara cheat sheet · GitHub

うまくいったら次に進みましょう。


4.Routing

ページのルーティングが正しいかをテストする

最後はルーティングです。

createアクションに対してルーティングがうまくいっているかテストをしてみましょう。

テスト用のファイルはジェネレータを使わなくても作成出来るので、
今回は、手入力でファイルを作成します。

spec/routing/users_routing_spec.rb
を新規作成し、以下のように記述して下さい。

spec/routing/users_routing_spec.rb
require 'rails_helper'

RSpec.describe "routes for Users", type: :routing do
  describe 'ルーティングのテスト' do
    it 'createアクションのルーティング' do
      expect(post("/users")).to route_to("users#create")
    end
  end
end

【解説】

Usersroutingについてのテストであることを明示。

/usersにPOSTしたら usersコントローラーのcreateアクションが動くことをテストしています。

おわりに

いかがでしたでしょうか?

超基本的な内容ではありますが、書くことに対しての苦手意識が少しで減ればいいなと思います。

私も書きながら調べていましたが、検索でヒットする内容には古い情報が多く、苦労しました。

今後も以下最新情報を参照しつつ勉強していこうと思います:point_up:
RSpec Rails 3-9 - RSpec Rails - RSpec - Relish

参考にさせて頂いたサイト(いつもありがとうございます)

使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」 - Qiita
使えるRSpec入門・その2「使用頻度の高いマッチャを使いこなす」 - Qiita

使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」 - Qiita
Ruby on Rails のテストフレームワーク RSpec 事始め - Qiita
全国のSeleniumer必読 - Qiita
undefined method `visit’ when using RSpec and Capybara in rails
capybara cheat sheet · GitHub

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away