はじめに
RSpecはRailsで定番のテストフレームワーク。
minitestと比べると必要なGemが多い。
とはいえ一度に全てのGemを入れると、どのGemがどこでどういう働きをするのかが曖昧になってしまう。
そこで、RSpecの学習に至っては、テストの内容に応じてGemを逐次追加していく手法を取ることにした。
RSpecとFactoryBot
Gemの導入と設定
RSpec
と、テスト用データの生成用となるFactoryBot
を導入する。
FactoryBotはminitestにおけるfixture的な役割を担う。
ここでspring-commands-rspec
を入れておくと、RSpecをbinstub
から実行し、spring
を使ってテスト開始にかかる時間を短縮できるとのこと。
group :development, :test do
gem "rspec-rails"
gem 'spring-commands-rspec'
gem "factory_bot_rails"
end
bundle install
したら以下のコマンドでRSpec用のデータを生成する。
$ bundle exec rails generate rspec:install
RSpecの設定を追加する。
設定はconfig/application.rb
に書く。
ここではgenerate
コマンド実行時にRSpec用のファイルを生成するかを設定している。
true
かfalse
かはプロジェクトによって適宜変更する。
module SampleApp
class Application < Rails::Application
.
.
.
config.generators do |g|
g.test_framework :rspec,
controller_specs: true,
fixtures: true,
helper_specs: true,
model_specs: true,
request_spec: true,
routing_specs: false,
view_specs: false
end
end
end
次にFactoryBotの設定。
以下のように記述することで、FactoryBotクラスの呼び出しを簡略化できる。
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
end
# FactoryBotクラスの呼び出し
user = FactoryBot.create(:user)
#省略版
user = create(:user)
テスト用データの設定をもう一つ。
以下の一行のコメントアウトを外しておく。
spec/support/
配下のファイルを読み込めるようになる。
ここにはテスト用のヘルパーを記述するファイルなどが置かれる。
# The following line is provided for convenience purposes. It has the downside
# of increasing the boot-up time by auto-requiring all files in the support
# directory. Alternatively, in the individual `*_spec.rb` files, manually
# require only the support files necessary.
#
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }
最後に、RSpecのbinstubを導入する。
これで$ bundle exec rspec spec/
に加えて$ bin/rspec spec/
でテストを実行できるようになる。
$ bundle exec spring binstub rspec
# 実行コマンド
$ bin/rspec spec/
specファイルの生成
RSpecで使用されるファイルは全て*_spec.rb
というファイル名になっている。
これをコントローラやモデルに合わせて各種用意していく。
例えばusers_controller用のspecファイルは以下のように生成する。
$ rails g rspec:controller users
create spec/controllers/users_controller_spec.rb
テスト用データの用意
FactoryBotを使って、各種クラスのテスト用データ(インスタンス)を定義する。
例えばUserクラスなら、/spec/factories/users.rb
に定義していく。
FactoryBot.define do
# Userモデルのテストデータmichaelを定義
factory :michael, class: User do # Class: Userはいらないかも
name { 'michael' }
email { 'michael@example.com' }
end
# 汎用データをたくさん用意する
factory :user do
sequence(:name) { |n| "name-#{n}"}
sequence(:email) { |n| "test-#{n}@example.com"}
end
end
定義したテストデータを呼び出してインスタンス変数に格納し、テストで使用する。
RSpec.describe User, type: :model do
before do
# モデルのみの作成
@michael = build(:michael)
# DBへレコード生成
@michael = create(:michael)
# 汎用データの活用
@user1 = build(:user)
@user2 = build(:user)
@user3 = build(:user)
end
.
.
.
end
続く