準備
Gemrails-controller-testing
をインストールする。
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
...
gem 'rails-controller-testing' #追記
end
$ bundle install
次のディレクトリを作成する。
spec/controllers
次のファイルを作成する。
spec/controllers/tweets_controller_spec.rb
require 'rails_helper'
describe TweetsController do
end
specファイルを特定してテストを実行する。
$ bundle exec rspec spec/controllers/tweets_controller_spec.rb
Finished in ~
0 examples, 0 failures
正常に実行できることを確認した。
テストコード
newアクション
require 'rails_helper'
describe TweetsController do
# describe 'http method' #action do
describe 'GET' #new do
it 'new.html.erbに遷移すること' do
get :new
expect(response).to render_template :new
end
end
end
response
example内で行われるリクエストの後の遷移先のビューの情報を持つインスタンス。
render_templateマッチャ
引数にシンボル型のアクションを指定することで、そのアクションがリクエストされた時に自動的に遷移するビューを返す。
テストを実行する。
$ bundle exec rspec spec/controllers/tweets_controller_spec.rb
TweetsController
GET #new
new.html.erbに遷移すること
Finished in ~
1 example, 0 failures
editアクション
コントローラ確認
def edit
@tweet = Tweet.find(params[:id])
end
editアクションでは、@tweetインスタンスを定義している。
require 'rails_helper'
describe TweetsController do
# describe 'http method' #action do
describe 'GET' #new do
...
describe 'GET #edit' do
it "@tweetに正しい値が入っていること" do
# factory_botで定義するインスタンスを一時的にDBに登録して取得する
# 登録したデータはテスト完了時に削除される
tweet = create(:tweet)
# 作成したインスタンスのidをセットする
get :edit, params: { id: tweet }
#editアクションで取得するtweetが、テストで作成したtweetと同じであることを確認する
expect(assigns(:tweet)).to eq tweet
end
it "edit.html.erbに遷移すること" do
tweet = create(:tweet)
get :edit, params: { id: tweet }
expect(response).to render_template :edit
end
end
end
assignsメソッド
コントローラのテスト時に、アクションで定義するインスタンス変数をテストするためのメソッド。
直前で定義したアクションの中で定義されるインスタンス変数を、シンボル型でとる。
(@tweet -> :tweet)
factory_botでtweetインスタンスを定義する。
FactoryBot.define do
factory :tweet do
text {"hello!"}
image {"hoge.png"}
# created_atをランダムに生成
created_at { Faker::Time.between(from: DateTime.now - 2, to: DateTime.now ) }
user
end
end
登録日カラムにて利用するFakerの説明は最後に。
indexアクション
indexアクションを確認する。
...
def index
@tweets = Tweet.includes(:user).order("created_at DESC").page(params[:page]).per(5)
end
...
describe 'GET #index' do
it "@tweetに正しい値が入っていること"
#tweetレコードを3つ保存して、変数tweetsにインスタンスに取得
tweets = create_list(:tweet, 3)
#indexアクションへの擬似的なリクエスト
get :index
# created_atを基準にして、降順にtweetsを並び替える処理
expect(assigns(:tweets)).to match(tweets.sort{ |a, b| b.created_at <=> a.created_at })
end
it "index.html.erbに遷移すること"
get :index
expect(response).to render_template :index
end
end
matchマッチャ
引数に配列クラスのインスタンスをとり、expectの引数と比較する。
配列の中身の順番までチェックする。
factory_botでのuserインスタンス定義する。
FactoryBot.define do
factory :user do
nickname {"abe"}
# email {"kkk@gmail.com"}
password {"00000000"}
password_confirmation {"00000000"}
sequence(:email) {Faker::Internet.email}
end
end
Faker
今回、tweetインスタンスを複数作ることになるが、emailの値が重複するとバリデーションによりエラーが起こる。
そのため、Fakerで動的にダミーデータを生成する。
group :test do
...
gem 'faker', "~> 2.8"
end
$ bundle install
テストの実行
$ bundle exec rspec spec/controllers/tweets_controller_spec.rb
2020-05-16 16:26:37 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
TweetsController
GET #new
new.html.erbに遷移すること
GET #edit
@tweetに正しい値が入っていること
edit.html.erbに遷移すること
GET #index
@tweetに正しい値が入っていること
index.html.erbに遷移にすること
Finished in 0.7887 seconds (files took 3.68 seconds to load)
5 examples, 0 failures
予期する通り動作することを確認できた。
RSpec参考書籍