[RUBY] RSpec-Testing "validation des utilisateurs"

Résultats de la révision du code de test de RSpec - 'validation des utilisateurs'

Avis de @jnchito! Si vous le souhaitez, veuillez suivre le lien ci-dessus!

Contexte

Ravi de vous rencontrer. Je suis nouveau sur les poteaux, rails et rspec Qiita. Soyez gentil avec moi. Pendant mes études à railstutorial, j'écris la "spécification du modèle" de ʻapp / models / user.rb`. Je voulais en faire un code de test sympa et beau, j'ai donc lu des articles sur la façon d'écrire rspec pour diverses personnes. J'ai écrit la spécification tout en concevant ma propre façon, et pendant que je pensais à cette façon d'écrire "N'est-ce pas plutôt cool?" Quand je regarde mon code en me référant à l'article, je ressens quelque chose de subtil, Je me suis perdu en demandant "quel est le code de test qui suit les règles?" Je ne peux pas m'engager facilement et je me promène en enfer. Si vous le souhaitez, je vous serais reconnaissant si vous pouviez revoir et indiquer le code de test.

référence

Pour le code de test, je me suis principalement référé à ce qui suit par jnchito.

Voyons ce qui précède, et ce sera le code que j'ai écrit à ma manière. Je n'ai pas fait référence à ce qui suit, mais l'article que j'ai vu et mon code semblaient être des ordures.

Image imbriquée

--describe: Quand # create (action) de ʻUser (model) , ʻattribute: name est --context: le nom doit être présent Le nom doit exister. --it: Vérifiez le modèle de «valide» ou «non valide».

Dans la création du test, l'image d'imbrication (?) model > action > attribute > validates: presence:true > valid or invalid J'ai écrit la spécification avec le regroupement à l'esprit. (Comme autre image, il semble que le résultat de l'exécution de $ bundle exec rspec au bas de l'article soit magnifique.)

Pourquoi tu ne peux pas sortir de l'enfer

--Utilisation correcte de «describe», «context» et «it». J'avais l'intention de l'écrire d'une manière facile à comprendre en tenant compte du cas où d'autres personnes le liraient. Voir Règle de base pour écrire RSpec magnifiquement "Ce n'est pas bien." (Y a-t-il une règle en premier lieu? Cela peut être un problème car je suis conscient que je vais créer et créer moi-même des règles.) --Mon code de test d'un point de vue professionnel Le code de test que j'ai écrit est vert et je pense que ça va, donc Je veux savoir "Je vais faire ça!" ―― N'est-il pas nécessaire d'effectuer "ce qui peut être sauvegardé ou ce qui ne peut pas être sauvegardé" dans chaque cas de test? Fondamentalement, comme ʻuser.valid? , Pour vous assurer qu'il a échoué dans le test cible, Je vérifie le contenu de l'erreur (ʻerrors [: name] ) comme ʻinclude (" cannot be blank "), Après cela, comme ʻuser.save! , (! Je pense que c'est une exception, mais ...) Je me demande si je devrais vérifier ce qui suit:

Ci-dessous, un extrait du code confirmant "ce qui peut ou ne peut pas être sauvegardé".

#Invalide si le nom n'existe pas
it 'is invalid because the name value does not exists' do
  user.name = nil
  user.valid?
  expect(user.errors[:name]).to include("can't be blank")

  expect(user.save).to be_falsey # ...Confirmez que cette ligne ne peut pas être enregistrée

end

Code de test

Le contenu du test est la validation du commun ʻusers.name, ʻuser.email. railstutorial Cela devient ici.

Eh bien, tout de suite, mais ...

Voici la validation actuelle.

app/models/user.rb


class User < ApplicationRecord
  before_save :downcase_email

  validates :name,
            presence: true,
            length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email,
            presence: true,
            length: { maximum: 255 },
            format: { with: VALID_EMAIL_REGEX },
            uniqueness: { case_sensitive: false }

  private

    def downcase_email
      self.email.downcase!
    end
end

Ce qui suit est l '«utilisateur» défini dans «FactoryBot».

spec/factories/users.rb


FactoryBot.define do
  factory :user do
    name { "hoge" }
    email { "foo@bar.com" }
  end
end

Voici le code de test réel.

spec/models/user_spec.rb


require 'rails_helper'
require 'pry'

RSpec.describe User, type: :model do
  let(:user) { FactoryBot.build(:user) }

  describe '#create' do
    describe 'attribute: name' do
      context 'name should be present' do
        #Si le nom existe, il doit être valide
        it 'is valid because the name has the correct value' do
          expect(user).to be_valid
          expect(user.save).to be_truthy
        end
        #Invalide si le nom n'existe pas
        it 'is invalid because the name value does not exists' do
          user.name = nil
          user.valid?
          expect(user.errors[:name]).to include("can't be blank")
          expect(user.save).to be_falsey
        end
      end

      context 'name should be length is 50 characters or less' do
        #Doit être valide si le nom comporte 50 caractères ou moins
        it 'is valid because the name length is 50 characters or less' do
          user.name = 'a' * 50
          user.valid?
          expect(user.errors[:name]).not_to include('is too long (maximum is 50 characters)')
          expect(user.save).to be_truthy
        end
        #Non valide si le nom dépasse 50 caractères
        it 'is invalid because the name length is 50 characters over' do
          user.name = 'a' * 51
          user.valid?
          expect(user.errors[:name]).to include('is too long (maximum is 50 characters)')
          expect(user.save).to be_falsey
        end
      end

      context 'name should be not blank' do
        #Si le nom est vide, il n'est pas valide
        it 'is invalid because the name is blank' do
          user.name = ' '
          user.valid?
          expect(user.errors[:name]).to include("can't be blank")
          expect(user.save).to be_falsey
        end
      end
    end

    context 'attribute: email' do
      context 'email should be present' do
        #Non valide si l'e-mail n'existe pas
        it 'is invalid because the email value does not exists' do
          user.email = nil
          user.valid?
          expect(user.errors[:email]).to include("can't be blank")
          expect(user.save).to be_falsey
        end
      end

      context 'email should be length is 50 characters or less' do
        #Valide si l'e-mail contient 255 caractères ou moins
        it 'is valid because the email length is 255 characters or less' do
          user.email = 'a' * 243 + '@example.com'
          user.valid?
          expect(user.errors[:email]).not_to include('is too long (maximum is 255 characters)')
          expect(user.save).to be_truthy
        end
        #Non valide si l'e-mail dépasse 255 caractères
        it 'is invalid because the email length is 255 characters over' do
          user.email = 'a' * 244 + '@example.com'
          user.valid?
          expect(user.errors[:email]).to include('is too long (maximum is 255 characters)')
          expect(user.save).to be_falsey
        end
      end

      context 'email should be correct format' do
        #Si le format de l'e-mail est correct, il est valide
        it 'is valid because the email is the correct format' do
          user.email = 'user@example.com'
          expect(user).to be_valid
          expect(user.save).to be_truthy

          user.email = 'USER@foo.COM'
          expect(user).to be_valid
          expect(user.save).to be_truthy

          user.email = 'A_US-ER@foo.bar.org'
          expect(user).to be_valid
          expect(user.save).to be_truthy

          user.email = 'first.last@foo.jp'
          expect(user).to be_valid
          expect(user.save).to be_truthy

          user.email = 'alice+bob@baz.cn'
          expect(user).to be_valid
          expect(user.save).to be_truthy
        end
        #Non valide si le format de l'e-mail est incorrect
        it 'is invalid because the email format is incorrect' do
          user.email = 'user@example,com'
          expect(user).not_to be_valid
          expect(user.save).to be_falsey

          user.email = 'user_at_foo.org'
          expect(user).not_to be_valid
          expect(user.save).to be_falsey

          user.email = 'user.name@example.'
          expect(user).not_to be_valid
          expect(user.save).to be_falsey

          user.email = 'foo@bar_baz.com'
          expect(user).not_to be_valid
          expect(user.save).to be_falsey

          user.email = 'foo@bar+baz.com'
          expect(user).not_to be_valid
          expect(user.save).to be_falsey
        end
      end

      context 'email should be unique' do
        #Si le même email est déjà enregistré, il doit être invalide
        it 'is Invalid because the same email already exists' do
          dup_user = user.dup
          dup_user.email = dup_user.email.upcase
          dup_user.save!
          user.valid?
          expect(user.errors[:email]).to include('has already been taken')
          expect(user.save).to be_falsey
        end
      end

      #L'e-mail est enregistré en minuscules
      context 'email should be saved in lowercase' do
        it 'is valid because the email saved in lowercase' do
          user.email = 'Foo@Example.Com'
          user.save!
          expect(user.reload.email).to eq 'foo@example.com'
        end
      end

      context 'email should be not blank' do
        #Si l'e-mail est vide, il n'est pas valide
        it 'is invalid because the email is blank' do
          user.email = ' '
          user.valid?
          expect(user.errors[:email]).to include("can't be blank")
          expect(user.save).to be_falsey
        end
      end
    end

  end
end

Dans le test ci-dessus, la sortie de l'exécution de $ bundle exec rspec (vert) est la suivante. L'utilisation correcte du code de test «describe», «context» et «it» semble être imbriquée afin que la sortie suivante soit plus facile à voir.

User
  #create
    attribute: name
      name should be present
        is valid because the name has the correct value
        is invalid because the name value does not exists
      name should be length is 50 characters or less
        is valid because the name length is 50 characters or less
        is invalid because the name length is 50 characters over
      name should be not blank
        is invalid because the name is blank
    attribute: email
      email should be present
        is invalid because the email value does not exists
      email should be length is 50 characters or less
        is valid because the email length is 255 characters or less
        is invalid because the email length is 255 characters over
      email should be correct format
        is valid because the email is the correct format
        is invalid because the email format is incorrect
      email should be unique
        is Invalid because the same email already exists
      email should be saved in lowercase
        is valid because the email saved in lowercase
      email should be not blank
        is invalid because the email is blank

Merci de votre collaboration.

Recommended Posts

RSpec-Testing "validation des utilisateurs"
Personnalisation de la validation
Utiliser ControlsFX / Validation
[rails] Définir la validation
[Rails5] Rspec -validation-