はじめに
現場ではRspecを使用してテストコードを書いています。
modelのテストを行うにあたって先輩に要件を確認していたところ、「Shoulda Matchersを使うと簡単だよ。」と教えてもらいました。
そもそもこれなんて読むんだ?そして何が美味しいんだ?
と思いながら調べてみましたので備忘録として残します。
誤り、おかしな点はぜひご指摘いただければと思います。
環境(私のPC)
Ruby 2.7.1
Rails 6.0.5
Shoulda Matchersとは
Shoulda Matchersとは長くて複雑かつつまずきやすいテストコードをワンライナーで記述することができるgemです。ワンライナーなので一行ということです。
え?そんなことができるの?ありえないでしょう。
半信半疑の思いを払拭すべく実際にやってみることにします。
(補足)
調べてみると「シュルダ マッチャーズ」と読むみたいですね。
スウェーデン語のようで日本語に訳すと「一致すべきです」となります。
前提条件
※すでにRspecがインストールされているものとします。
モデルの準備
次のようなモデルを作成します。
モデルに次のようなバリデーションを追加します。
- titleが空では登録できない
- 最大文字数255文字までしか登録できない
class Tool < ApplicationRecord
validates :title, presence: :ture, length: { maximum: 255 }
end
Shoulda Matchersのgemをインストール
Gemfileに下記のように記述し、bundle installします。
group :development, :test do
# ここから追記----------------------------ーーーーーーーーーーーーーーー
gem 'shoulda-matchers',
git: 'https://github.com/thoughtbot/shoulda-matchers.git',
branch: 'rails-5'
# ここまで追記----------------------------ーーーーーーーーーーーーーーー
end
spec/rails_helper.rbの末尾に下記を追加記述します。
# 省略
RSpec.configure do |config|
# 省略
end
# ここから追記----------------------------
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails
end
end
# ここまで追記----------------------------
これで準備はできました。
※Shoulda Matchersのgemをインストールできず、下のようなエラーが発生することがあります。(私がそうでした)
NoMethodError: undefined method `new' for BigDecimal:Class
こちらの記事を参考にgemを更新すると上手くいきましたので試してみてください。
実際にやってみる
今回検証したいものは次の3点です。
- titleが空文字の場合、登録できないこと
- titleが255文字以内の場合、登録できること
- titleが256文字以上の場合、登録できないこと
では通常のRspecで記述していきます。
いつものRspec
通常のRspecの記述法であれば細かな違いはあるにせよ、以下のようになると思います。
require 'rails_helper'
RSpec.describe Tool, type: :model do
describe 'tool' do
before do
@tool = Tool.new(title: "シャープペンシル")
end
it '空文字の場合、登録できないこと' do
@tool.title = ""
@tool.valid?
expect(@tool.errors[:title]).to include("can't be blank")
end
it '255文字の場合、登録できること' do
@tool.title = "あ"*255
expect(@tool).to be_valid
end
it '256文字の場合、登録できないこと' do
@tool.title = "あ"*256
@tool.valid?
expect(@tool.errors[:title]).to include("is too long (maximum is 255 characters)")
end
end
end
テストを実行してみましょう。
bundle exec rspec spec/models/tool_spec.rb
Shoulda Matchersを使ってみる
Shoulda Matchersを使ってテストコードを書いてみます。
require 'rails_helper'
RSpec.describe Tool, type: :model do
describe 'tool' do
it { is_expected.to validate_presence_of :title }
it { is_expected.to validate_length_of(:title).is_at_most(255) }
end
end
非常にさっぱりにすることができます。
確かにワンライナーで書くことができてますね。
it { is_expected.to validate_presence_of :title }
こちらが空かどうかを検証するテストコードです。
it { is_expected.to validate_length_of(:title).is_at_most(255) }
こちらが文字数が適切か検証するテストコードです。
Shoulda Matchersを使うことで、255文字以内のテストと256文字以上のテストをまとめられています。
また、最初にbefore end内で@toolを作成しておく必要もなくなりました。
検証結果は下のように表示されます。
気になった点
個人的に2点気になりました。
- テストコード及び検証結果を見て何をしているかの理解が難しい(可読性)
- 開発が終了しているらしいが導入の影響はあるのか
どなたかいい解決法わかればぜひ教えてほしいです。
※追記
@daishiman さんに共有していただきました。
テストは非エンジニアの方もできるものでなければならないという観点からいけば通常テストの方が適していると言えますね!
おわりに
Shoulda Matchersを使ってシンプルに短くテストを書くことができました。
使い方をもっと工夫すればあらゆる場面で使用できそうです。
もっと学習を深めていきたいと思います。
参考