はじめに
deviseを導入したは良いものの最初のテストが書けない…!どうやって書いたらいいの、というとこで情報がまとまってなかったので自分でまとめてみました。
自分でアプリを作り始めた初心者さん向けです。
Ruby '2.6.6'
Rails '5.2.4'
1.Gemfileの編集
group :development, :test do
・
・
gem "rspec-rails"
gem "factory_bot_rails"
end
をGemfileに加える
bundle install
bundle install
Fetching gem metadata from https://rubygems.org/.............
Fetching gem metadata from https://rubygems.org/.
・
・
Using duktape 2.3.0.0
Fetching factory_bot 6.1.0
Installing factory_bot 6.1.0
Fetching factory_bot_rails 6.1.0
Installing factory_bot_rails 6.1.0
Using jbuilder 2.10.0
・
・
Using web-console 3.7.0
Bundle complete! 22 Gemfile dependencies, 95 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
RSpecをダウンロードする
$ bundle exec rails generate rspec:install
2. rspecの設定
.rspecに以下の記述を行います。
--require spec_helper
--format documentation #ここを追加
上の記述はあってもなくてもいいのですが、あるなしでテスト実行時の表示がこのくらい変わります。
なし
$ ...............................
あり
$ User
$ #create
$ is valid
$ is invalid without email
$ is invalid without password
引用元:rspecのテスト環境でdeviseにログインする方法【rails】
https://qiita.com/Kohei_Kishimoto0214/items/e29e509b12a6eb484a42
なにも書いて無いけど試しにテストしてみる
テストするコマンドは
bundle exec rspec
または、個別に指定することもできる
bundle exec rspec
No examples found.
Finished in 0.00101 seconds (files took 3.71 seconds to load)
0 examples, 0 failures
まだ確認することは記述してないですが、表示はされています…!!!
3.Factory_botの設定をする
rails_helper.rb
内のconfigの部分に以下の記述を追加します。
RSpec.configure do |config|
config.includeFactoryBot::Syntax::Methods
end
こんな感じになると思います。
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.include FactoryBot::Syntax::Methods
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
end
4.rails_helperの設定
次に、/spec/rails_helper.rb
内で以下の一文がコメントアウトされているので、コメントアウトを外してください。
これでspec/support/
のファイルを読み込むことができます。
Dir[Rails.root.join('spec/support/**/*.rb')].each{|f|requiref}
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
#
# 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')].sort.each { |f| require f } ここのコメントアウトを外した
# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.include FactoryBot::Syntax::Methods
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# You can uncomment this line to turn off ActiveRecord support entirely.
# config.use_active_record = false
# RSpec Rails can automatically mix in different behaviours to your tests
# based on their file location, for example enabling you to call `get` and
# `post` in specs under `spec/controllers`.
#
# You can disable this behaviour by removing the line below, and instead
# explicitly tag your specs with their type, e.g.:
#
# RSpec.describe UsersController, type: :controller do
# # ...
# end
#
# The different available types are documented in the features, such as in
# https://relishapp.com/rspec/rspec-rails/docs
config.infer_spec_type_from_file_location!
# Filter lines from Rails gems in backtraces.
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
end
5.テストデータの準備
新しいフォルダ&ファイルspec\factories\user.rb
を作成
今回、Fakerは入れてないので、手動でデータ入力をします。
通し番号を振っていく付け方もありますが、今回は一番シンプルな方法にします。
devise初期設定は名前がないので以下の3要素のみ必要です。
nameカラムを追加している方はspec\factories\user.rb
にもnameの項目を追加して下さい。
FactoryBot.define do
factory :user do
email {"test@gmail.com"}
password {"111111"}
password_confirmation {"111111"}
end
end
6.controller_macrosの作成
spec/support/controller_macros.rb
を作成し、下記の公式の内容を追記してください。
公式:How To: Test controllers with Rails (and RSpec)
https://github.com/heartcombo/devise/wiki/How-To:-Test-controllers-with-Rails-(and-RSpec)
module ControllerMacros
def login_admin
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:admin]
sign_in FactoryBot.create(:admin) # Using factory bot as an example
end
end
def login_user
before(:each) do
@request.env["devise.mapping"] = Devise.mappings[:user]
user = FactoryBot.create(:user)
user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
sign_in user
end
end
end
7. rails_helper内でdeviseとcontroler_macrosを読み込む
rails_helperのRSpec.configure外に以下を記述し、deviseとmacrosを読み込みます。
require'devise'
require File.expand_path("spec/support/controller_macros.rb")
RSpec.configure内に以下を記述し、deviseのtest_helperとmacrosをcontroller内で使えるようにします。
RSpec.configure do |config|
・
・
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::IntegrationHelpers, type: :request
config.extend ControllerMacros, :type => :controller
・
・
加えるとこんな感じになります。
# This file is copied to spec/ when you run 'rails generate rspec:install'
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'devise'
require File.expand_path("spec/support/controller_macros.rb")
require_relative 'support/controller_macros'
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
exit 1
end
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::IntegrationHelpers, type: :request
config.extend ControllerMacros, :type => :controller
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
end
8. user_spec.rbで、userをcreateしログイン処理をする
createしたuserをletに格納しインスタンス変数のように使用できるようにしました。
さらにそのuserにlogin_userメソッドを使ってdeviseにログインさせます。
modelのvalidationをテストします。
事前にvalidationは設定してください。
require 'rails_helper'
RSpec.describe User, type: :model do
describe 'ユーザー登録' do
it "name、email、passwordとpassword_confirmationが存在すれば登録できること" do
user = build(:user)
expect(user).to be_valid # user.valid? が true になればパスする
end
end
引用元:[Rspecを使用したテスト①(単体テスト:バリデーションのテスト)]
(https://misukeblog.com/rspec/)
引用元:[Rspecを使用したテスト②(統合テスト)]
(https://misukeblog.com/rspec2/)
かいてからの
bundle exec rspec
でいける
はず!!!!これで完成!!
$ bundle exec rspec
User
name、email、passwordとpassword_confirmationが存在すれば登録できること
Finished in 0.5297 seconds (files took 9.34 seconds to load)
1 example, 0 failures
9.ハマったところ
パターン1
& rails g rspec:model user
conflict spec/models/user_spec.rb
Overwrite C:/Users/.../ (アプリ名) /spec/models/user_spec.rb? (enter "h" for help) [Ynaqdhm]
force spec/models/user_spec.rb for help) [Ynaqdhm]
$ bundle
Migrations are pending. To resolve this issue, run:
bin/rails db:migrate RAILS_ENV=test
No examples found.
こんな時は指示通り
$ rails db:migrate RAILS_ENV=test
しましょう
パターン2
こんなエラーがでたらそれはgemfileの中に古いGemが混ざっています。
$ bundle exec rspec
2020-09-02 22:36:39 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrom
e#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#dri
ver_path= instead.
An error occurred while loading ./spec/models/user_spec.rb.
Failure/Error: require File.expand_path('../config/environment', __dir__)
Selenium::WebDriver::Error::WebDriverError:
per-2.1.1/bin/chromedriver-helper"
# ./config/application.rb:7:in `<top (required)>'
# ./config/environment.rb:2:in `<top (required)>'
# ./spec/rails_helper.rb:4:in `require'
# ./spec/rails_helper.rb:4:in `<top (required)>'
# ./spec/models/user_spec.rb:1:in `require'
# ./spec/models/user_spec.rb:1:in `<top (required)>'
No examples found.
Finished in 0.00008 seconds (files took 7.23 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples
参考:Rspecが動かない rails_helperの読み込み
https://teratail.com/questions/247938?link=qa_related_pc
Gemfileを書き換えます。
group :test do
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15'
gem 'selenium-webdriver'
# Easy installation and use of chromedriver to run system tests with Chrome
#gem 'chromedriver-helper' #この1文を削除orコメントアウト
gem 'webdrivers', '~> 3.0' #この1行を追加
gem 'rspec-rails'
gem "factory_bot_rails"
end
・
・
gem 'devise'
そして
bundle install
これでいけるはずです!
最後に
間違いなどがあればご指摘いただけると嬉しいです。
#いろいろな参考
[RailsアプリへのRspecとFactory_botの導入手順]
(https://qiita.com/Ushinji/items/522ed01c9c14b680222c)
[RSpec初心者のdevise認証システムテスト]
(https://qiita.com/zongxiaojie/items/d488edd42ba3864859c7)
[rspecのテスト環境でdeviseにログインする方法【rails】]
(https://qiita.com/Kohei_Kishimoto0214/items/e29e509b12a6eb484a42)
[deviseを使ったコントローラのテスト]
(https://qiita.com/nysalor/items/ef3d658ff76bee165379)
[RSpecを用いた単体テストについての備忘録 @TECH CAMP #11 -note]
(https://note.com/ruquia7/n/n00ff04fc9129)
[[Ruby on Rails]rspecを用いたmodelの単体テスト -note]
(https://note.com/vixer93/n/n6ef6555d7a3e)
[Railsでmigrate後のエラー「bin/rails db:migrate RAILS_ENV=test」について]
(https://teratail.com/questions/178462)