factory_bot_rails導入
gem factory_bot_railsを、RSpecと同じ環境に追加する。
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem 'rspec-rails'
gem 'factory_bot_rails'
end
$ bundle install
ディレクトリ spec/factories を作成する。
ファイル users.rbを作成する。
テストで使うuserクラスのデフォルトインスタンスを定義する。
※テストの際に、一部を変更して使う。
FactoryBot.define do
factory :user do
nickname {"abe"}
email {"kkk@gmail.com"}
password {"00000000"}
password_confirmation {"00000000"}
end
end
メソッド
buildメソッド
factory_botに記述したクラスをシンボル型で引数に指定してインスタンスを生成します。
#factory_botを利用しない場合
user = User.new(nickname: "abe", email: "kkk@gmail.com", password: "00000000", password_confirmation: "00000000")
#factory_botを利用する場合
user = FacrtoryBot.build(:user)
createメソッド
buildメソッド同様、factory_botに記述したクラスをシンボル型で引数に指定してインスタンスを生成します。
さらにテスト用のDBに値が保存されます。
テストが終了するたびにDBの内容はロールバックされます。
# createしたインスタンスはDBに保存される
user = FactoryBot.create(:user)
factory_botの記法の省略
インスタンスを作成する際に必要となるレシーバであるクラスのFactoryBot
という記述を、rails_helper.rb
に記述することでuser_spec.rb
での記述を省略することができます。
RSpec.configure do |config|
...
#下記の記述を追加
config.include FactoryBot::Syntax::Methods
...
end
factory_botを利用したインスタンス生成
require 'rails_helper'
describe User do
describe '#create' do
it "nicknameがない場合は登録できないこと" do
# user = User.new(nickname: "", email: "kkk@gmail.com",password: "00000000", password_confirmation: "00000000")
user = build(:user, nickname: "")
user.valid?
expect(user.errors[:nickname]).to include("can't be blank")
end
it "emailがない場合は登録できないこと" do
# user = User.new(nickname: "nick", email: "",password: "00000000", password_confirmation: "00000000")
user = build(:user, email: "")
user.valid?
expect(user.errors[:email]).to include("can't be blank")
end
end
end
バリデーションに関するテストコードを書く
テスト項目
1.nicknameとemail、passwordとpassword_confirmationが存在すれば登録できること
2.nicknameがない場合は登録できないこと
3.emailがない場合は登録できないこと
4.passwordがない場合は登録できないこと
5.passwordが存在してもpassword_confirmationがない場合は登録できないこと
6.nicknameが7文字以上であれば登録できないこと
7.nicknameが6文字以下では登録できること
8.重複したemailが存在する場合登録できないこと
9.passwordが6文字以上であれば登録できること
10.passwordが5文字以下であれば登録できないこと
テストコード
テスト項目に沿って次の通り書く。
require 'rails_helper'
describe User do
describe '#create' do
#1
it "nicknameとemail、passwordとpassword_confirmationが存在すれば登録できること" do
user = build(:user)
expect(user).to be_valid
end
#2
it "nicknameがない場合は登録できないこと" do
user = build(:user, nickname: "")
user.valid?
expect(user.errors[:nickname]).to include("can't be blank")
end
#3
it "emailがない場合は登録できないこと" do
user = build(:user, email: "")
user.valid?
expect(user.errors[:email]).to include("can't be blank")
end
#4
it "passwordがない場合は登録できないこと" do
user = build(:user, password: "")
user.valid?
expect(user.errors[:password]).to include("can't be blank")
end
#5
it "passwordが存在してもpassword_confirmationがない場合は登録できないこと" do
user = build(:user, password_confirmation: "")
user.valid?
expect(user.errors[:password_confirmation]).to include("doesn't match Password")
end
#6
it "nicknameが7文字以上であれば登録できないこと" do
user = build(:user, nickname: "abematv")
user.valid?
expect(user.errors[:nickname]).to include("is too long (maximum is 6 characters)")
end
#7
it "nicknameが6文字以下では登録できること" do
user = build(:user, nickname: "abemat")
expect(user).to be_valid
end
#8
it "重複したemailが存在する場合登録できないこと" do
user1 = create(:user, email: "testman@test")
user2 = build(:user, email: "testman@test")
user2.valid?
expect(user2.errors[:email]).to include("has already been taken")
end
#9
it "passwordが6文字以上であれば登録できること" do
user = build(:user, password: "123456", password_confirmation: "123456")
expect(user).to be_valid
end
#10
it "passwordが5文字以下であれば登録できないこと" do
user = build(:user, password: "12345", password_confirmation: "12345")
user.valid?
expect(user.errors[:password]).to include("is too short (minimum is 6 characters)")
end
end
end
テスト実行
$ bundle exec rspec
2020-05-10 19:22:19 WARN Selenium [DEPRECATION] Selenium::WebDriver::Chrome#driver_path= is deprecated. Use Selenium::WebDriver::Chrome::Service#driver_path= instead.
User
#create
nicknameとemail、passwordとpassword_confirmationが存在すれば登録できること
nicknameがない場合は登録できないこと
emailがない場合は登録できないこと
passwordがない場合は登録できないこと
passwordが存在してもpassword_confirmationがない場合は登録できないこと
nicknameが7文字以上であれば登録できないこと
nicknameが6文字以下では登録できること
重複したemailが存在する場合登録できないこと
passwordが6文字以上であれば登録できること
passwordが5文字以下であれば登録できないこと
Finished in 0.10159 seconds (files took 1.61 seconds to load)
10 examples, 0 failures
表示0 failures
により、予期した通り動作することを確認できた。
be_validマッチャ
expectの引数にしたインスタンスが全てのバリデーションをクリアする場合にパスする。
次の通り書く。
it "nickname、email、passwordとpassword_confirmationが存在すれば登録できること" do
user = build(:user)
expect(user).to be_valid
end
テストの原則
#####①1example、1エクスペクテーション
2つ以上含めると、どちらのエクスペクテーションでエラーが出たのか判別できない。
#####②期待する結果をわかりやすく書く
it "〜" doの"〜"の部分は、期待する結果を書いておく場所。
#####③起きて欲しいことと起きてほしくないこと両方をテストする
起きて欲しいことをチェックしたら、起きてほしくない場合にどんな結果が起こるかも想定しその通りになるか確かめる。
予期せぬ動作が残るのを防ぐため。
#####④境界値をテストする
6文字以上でバリデーションに引っかかる、という条件の場合は「5文字までは正常」と「6文字以上ならば異常」を確かめるようにする。
#####⑤可読性を考えつつ、適度にDRYにする
テストではわかりやすさを優先する。
その上で「Don't Repeat Yourself」
関連リンク