LoginSignup
14
11

【初心者向け】deviseのユーザー登録をRSpecでテストする

Last updated at Posted at 2020-09-20

はじめに

deviseを導入したは良いものの最初のテストが書けない…!どうやって書いたらいいの、というとこで情報がまとまってなかったので自分でまとめてみました。
自分でアプリを作り始めた初心者さん向けです。

Ruby '2.6.6'
Rails '5.2.4'

1.Gemfileの編集

Gemfile
group :development, :test do


  gem "rspec-rails"
  gem "factory_bot_rails"
end

をGemfileに加える

Terminal
bundle install
Terminal

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をダウンロードする

Terminal
$ bundle exec rails generate rspec:install

2. rspecの設定

.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
または、個別に指定することもできる

Terminal
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の部分に以下の記述を追加します。

spec/rails_helper.rb
RSpec.configure do |config|
    config.includeFactoryBot::Syntax::Methods
end

こんな感じになると思います。

spec/rails_helper.rb
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/のファイルを読み込むことができます。

/spec/rails_helper.rb
Dir[Rails.root.join('spec/support/**/*.rb')].each{|f|requiref}
/spec/rails_helper.rb
# 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の項目を追加して下さい。

spec\factories\user.rb
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)

spec/support/controller_macros.rb
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を読み込みます。

spec/rails_helper.rb
require'devise'
require File.expand_path("spec/support/controller_macros.rb")

RSpec.configure内に以下を記述し、deviseのtest_helperとmacrosをcontroller内で使えるようにします。

spec/rails_helper.rb
RSpec.configure do |config|


 config.include Devise::Test::ControllerHelpers, type: :controller
  config.include Devise::Test::IntegrationHelpers, type: :request
  config.extend ControllerMacros, :type => :controller


加えるとこんな感じになります。
 

spec\rails_helper.rb

 # 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は設定してください。

spec\models\user_spec.rb
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/)

かいてからの

Terminal
bundle exec rspec

でいける

はず!!!!これで完成!!

Terminal
$ bundle exec rspec
 
User
  nameemailpasswordpassword_confirmationが存在すれば登録できること        
 
Finished in 0.5297 seconds (files took 9.34 seconds to load)
1 example, 0 failures

9.ハマったところ

パターン1

Terminal

& 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.

こんな時は指示通り

Terminal
$ rails db:migrate RAILS_ENV=test

しましょう

パターン2

こんなエラーがでたらそれはgemfileの中に古いGemが混ざっています。

Terminal

$ 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を書き換えます。

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'

そして

Terminal
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)

14
11
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
11