Ruby on Rails ヘルスケア ITの普及に向けて サービス開発備忘録 RSpec テスト~model spec

ずっと、サボっていましたが、技術力向上のためには、メモがてら、書き記すことが必要と思い、再開です。

言語化してアウトプットすることで、メタ的に認知し、結果、理解度が上がるんだろうか？

model specである。
こちらを参考にさせていただいた。
(https://qiita.com/Jwataru/items/2cac90cc9bca4f76bb11)

13)が通らない
patient.email = "Foo@ExAMPle.CoM"としているが、
下記のように出る。

```
  1) Patient emailを小文字に変換後の値と大文字を混ぜて登録されたアドレスは 13) 同じ
     Failure/Error: expect(patient.reload.email).to eq "foo@example.com"
     
       expected: "foo@example.com"
            got: "test11@example.com"
     
       (compared using ==)
     # ./spec/models/patient_spec.rb:120:in `block (3 levels) in <top (required)>'
```

FactoryBotのemailとなっている。
上書きされていないのか？

15)が通らない

```
  2) Patient passwordとpassward_confirmationの一致 passwordとpassward_confirmationは 15) 不一致
     Failure/Error: expect.(patient.errors[:password_confirmation]).to include("の入力が一致しません")
     
     ArgumentError:
       You must pass either an argument or a block to `expect`.
     # ./spec/models/patient_spec.rb:136:in `block (4 levels) in <top (required)>'```

```


```Ruby:patient_spec.rb
require 'rails_helper'

RSpec.describe Patient, type: :model do
  
  # FactoryBot patient
  let(:patient) { create(:patient) }

  describe '存在性' do

    context 'patientは' do
      it '1) 有効である' do
        expect(patient).to be_valid
      end
    end

    context 'nameが空白は' do
      it '2) 無効' do
      patient.patient_name = "     "
      expect(patient).to be_invalid
      end
    end

    context "emailが空白は" do
      it '3) 無効' do
        patient.email = "     "
        expect(patient).to be_invalid
      end
    end

    context "password空白は" do
      it '4) 無効' do
        patient.password = patient.password_confirmation = " " * 6
        expect(patient).to be_invalid
      end
    end
  
  end

  describe '長さ' do

    context "name17文字以上は" do
      it '5) 無効' do
        patient.patient_name = "a" * 17
        expect(patient).to be_invalid
      end
    end
    
    context "emailが256字以上" do
      it '6) 無効' do
        patient.email = "a" * 244 + "@example.com"
        expect(patient).to be_invalid
      end
    end

    context "emailが255字以下は" do
      it '7) 無効' do
        patient.email = "a" * 243 + "@example.com"
        expect(patient).to be_valid
      end
    end

    context "password5字以下は" do
      it '8) 無効' do
        patient.password = patient.password_confirmation = "a" * 5
        expect(patient).to be_invalid
      end
    end

    context "password 6字以上は" do
      it '9) 有効' do
        patient.password = patient.password_confirmation = "a" * 6
        expect(patient).to be_valid
      end
    end

  end

  # describe 'フォーマット' do
# 
    # context "emailは規定の表記でなければ" do
      # it '無効' do
        # invalid_addresses = %wpatient@example,com foo@bar..com user_at_foo.orgpatient.name@example. foo@bar_baz.com foo@bar+baz.com]
        # invalid_addresses.each do |invalid_address|
          # patient.email = invalid_address
          # expect(patient).to be_invalid,"#{invalid_address.inspect}が無効ではありません"
        # end
      # end 
    # end
# 
    # context "emailは規定の表記であれば" do
      # it '有効' do
        # valid_addresses = %wpatient@example.com USER@foo.COM A_US-ER@foo.bar.org first.last@foo.jp alice+bob@baz.cn]
        # valid_addresses.each do |valid_address|
          # patient.email = valid_address
          # expect(patient).to be_valid, "#{valid_address.inspect} が有効ではありません"
        # end
      # end
    # end
# 
  # end

  describe '一意性' do

    context "emailの重複は" do
      it '12) 無効' do
        duplicate_user = patient.dup
        duplicate_user.email = patient.email.upcase
        patient.save!
        expect(duplicate_user).to be_invalid
      end
    end

  end

  context "emailを小文字に変換後の値と大文字を混ぜて登録されたアドレスは" do
    it '13) 同じ' do
      patient.email = "Foo@ExAMPle.CoM"
      patient.save!
      #全て小文字のemailと等しいかのテスト
      expect(patient.reload.email).to eq "foo@example.com"
    end
  end

  describe 'passwordとpassward_confirmationの一致' do

    context 'passwordとpassward_confirmationは' do
      
      it "14) 一致" do
        expect(patient).to be_valid
      end
      
      it "15) 不一致" do
        patient.password ="password"
        patient.password_confirmation = "different"
        patient.valid?
        expect.(patient.errors[:password_confirmation]).to include("の入力が一致しません")
      end

    end
  
  end

end
```

```Ruby:factory/patients.rb
FactoryBot.define do
  factory :patient do #factory :testuser, class: User do のようにクラスを明示すればモデル名以外のデータも作れます。
    patient_name { "山田花子" }
    sequence(:email) { |n| "TEST#{n}@example.com" }
    password { "abcder" }
    password_confirmation { "abcder" }
    birth_date { "1967-01-01" }
    sex { "woman" }
  end
end
```

```Ruby:model/patients.rb
class Patient < ApplicationRecord
  
  # 以下コメントアウト 登録時は患者がclinicに所属していないから(import時にclinic_idが付与される)
  # belongs_to :clinic
  has_many :clinics, through: :clinic_patients
  has_many :clinic_patients
  has_many :tests
  
  #viewに男女を表示
  enum sex: { man: 1, woman: 2 }

  default_scope { where(leave_at: nil) }

  #devise設定
  devise :database_authenticatable, :registerable, 
  :validatable, :recoverable, :rememberable, 
  :confirmable, :lockable, :timeoutable,
  :trackable

  # validation

    validates :patient_name,
    { presence: true, length: { maximum: 16 } }
    # format: {
    #   with: /\A[A-Za-z0-9]+\z/,
    #   message: 'は小文字英数字で入力してください'
    # }
    
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    validates :email,
    { presence: true,
    confirmation: true,
    length: { maximum: 255 },
    format: { with: VALID_EMAIL_REGEX } }

    validates :sex,
    { presence: true }

    validates :birth_date,
    { presence: true }

end

```