[Rails / RSpec] Ecrire un test de modèle (avec Shoulda Matchers / FactoryBot)

introduction

J'ai appris en écrivant RSpec à partir d'un état où je n'avais jamais écrit de test. Je voudrais laisser ce que je comprends dans l'article avec le code qui le décrit réellement.

supposition

--Table des utilisateurs --Colonnes: ```email: stringet password: string`` uniquement

Si vous utilisez `` Shoulda Matchers '', vous pouvez écrire un test en une seule ligne que vous ne pourriez pas faire sans écrire plusieurs lignes. Il y a certaines parties dont vous ne savez pas ce qui se fait, mais il existe des syntaxes utiles autres que le contenu décrit cette fois, donc si vous êtes intéressé, je vous recommande de le vérifier sur le site de référence. ..

Site de référence

C'était très facile à comprendre et très utile! Merci beaucoup!

Model

app/models/user.rb


class User < ApplicationRecord
  has_many :books #Association un-à-plusieurs avec des livres
  has_secure_password
  before_save { email.downcase! }

  validates :email, presence: true,
                    length: { maximum: 255 },
                    format: { with: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i },
                    uniqueness: { case_sensitive: false }
  validates :password, presence: true,
                       length: { minimum: 6 }
end

tester

Nous effectuons un total de 9 tests

Dossier entier

spec/models/user_spec.rb


# rails_Lire le fichier d'aide
require 'rails_helper'

#Test du modèle utilisateur, donc utilisateur, type: :Comme modèle
RSpec.describe User, type: :model do

  describe 'has_many' do
    # has_many :Livres de test
    it { should have_many(:books) }
  end

  describe 'has_secure_password' do
    # has_secure_test de mot de passe
    it { should have_secure_password }
  end
  
  describe 'validation' do
    context 'email' do
      #Créer des données de test avec FactoryBot
      let(:user) { create(:user) }
      let(:upcase_email_user) { build(:user, :upcase_email) }

      # presence:Vrai test
      it { should validate_presence_of(:email) }
      # length: { maximum: 255 }Test de
      it { should validate_length_of(:email).is_at_most(255) }

      # uniqueness: { case_sensitive: false }Test de
      it 'Ne pas autoriser le stockage en double des e-mails' do
        duplicate_user = user.dup
        duplicate_user.email = user.email.upcase
        expect(duplicate_user).to be_invalid
      end
     
      # format: { with: XXXXX }Test de
      it 'Ne pas autoriser les e-mails qui ne correspondent pas au format spécifié' do
        invalid_emails = %w[user@foo,com user_at_foo.org [email protected]@bar_baz.com foo@bar+baz.com [email protected]]
        invalid_emails.each do |invalid_email|
          user.email = invalid_email
          expect(user).to be_invalid
        end
      end

      # before_save { email.downcase! }Test de
      it 'downcase!Fonctionne correctement' do
        upcase_email_user.save!
        expect(upcase_email_user.email).to eq '[email protected]'
      end
    end

    context 'password' do
      # presence:Vrai test
      it { should validate_presence_of(:password) }
      # length: { minimum: 6 }Test de
      it { should validate_length_of(:password).is_at_least(6) }
    end
  end
end

Explication de chaque description

Déclaration de test

`` RSpec.describe model name, type :: test format do '', et cette description vous permet de tester le modèle User à l'intérieur du bloc.

RSpec.describe User, type: :model do

Test de has_many et has_secure_password

Validez l'association de modèle et l'application de has_secure_password en utilisant Shoulda Matchers

# has_many :Livres de test
describe 'has_many' do
  it { should have_many(:books) }
end

# has_secure_test de mot de passe
describe 'has_secure_password' do
  it { should have_secure_password }
end

Description de test séparée par description et contexte

describe 'validation' do
    context 'email' do
      #Rédiger un test de validation par e-mail
    end
    context 'password' do
      #Rédiger un test de validation de mot de passe
    end
end

Créer des données de test avec FactoryBot

Définissez les données de test créées par le bot d'usine dans un fichier dédié

spec/factories/users.rb


FactoryBot.define do
  factory :user do
    #Chaque fois que des données sont générées, un numéro de série est attribué pour créer une valeur unique.
    sequence(:email) { |n| "test#{n}@test.com" }
    password { 'password' }

    trait :upcase_email do
      email { '[email protected]' }
    end
  end
end

Les données de test sont créées avec let sur la base du fichier ci-dessus, et ces données de test peuvent être utilisées dans le bloc ʻit .. do ~~ end`` du bloc décrit. Dans le commentaire, le résultat de la vérification du contenu de ʻuser et` ʻupcase_email_user dans binding.pry`` est décrit.

  let(:user) { create(:user) }
  # user = <User:0x0000560469431138 id: 2610, email: "[email protected]", password_digest: "[FILTERED]", created_at: Tue, 27 Oct 2020 14:03:04 JST +09:00, updated_at: Tue, 27 Oct 2020 14:03:04 JST +09:00>
  let(:upcase_email_user) { build(:user, :upcase_email) }
  # upcase_email_user = <User:0x00005604690c12c8 id: nil, email: "[email protected]", password_digest: "[FILTERED]", created_at: nil, updated_at: nil>

validation par e-mail

présence: vraie longueur: {maximum: 255} test (devrait être un Matchers)

Écrire des tests en utilisant `` Shoulda Matchers ''

  # presence:Test vrai
  it { should validate_presence_of(:email) }
  # length: { maximum: 255 }Tester
  it { should validate_length_of(:email).is_at_most(255) }

unicité: test {case_sensitive: false}

Créez des données de copie de utilisateur '' avec la méthode dup ''. Vérifiez que duplicate_user avec le même ʻemail`` que le ʻuser déjà enregistré avec` `let (: user) {create (: user)}` `n'est pas enregistré. En mettant en majuscule l'email avec `ʻupcase avant le test, il est également vérifié que l'e-mail est jugé identique même s'il est en majuscules.

be_invalid passera s'il est rayé par validation (si une erreur survient)

it 'Ne pas autoriser le stockage en double des e-mails' do
  duplicate_user = user.dup
  #Contenu à ce stade
  # duplicate_user = <User:0x000055f1e1d71e90 id: nil, email: "[email protected]", password_digest: "[FILTERED]", created_at: nil, updated_at: nil>
  duplicate_user.email = user.email.upcase
  # user.email.Contenu après upcase
  # #<User:0x000055f1e1d71e90 id: nil, email: "[email protected]", password_digest: "[FILTERED]", created_at: nil, updated_at: nil>

  expect(duplicate_user).to be_invalid  # duplicate_user.invalid?Passer si c'est vrai
end

format: {avec: / \ A [\ w + \ -.] + @ [Az \ d \ -] + (. [Az \ d \ -] +) * . [Az] + \ z / i} tester

it 'Ne pas autoriser les e-mails qui ne correspondent pas au format spécifié' do
  #Préparez 6 séquences de chaînes de caractères qui ne correspondent pas au format spécifié
  invalid_emails = %w[user@foo,com user_at_foo.org [email protected]@bar_baz.com foo@bar+baz.com [email protected]]
  #Vérifiez en mettant un e-mail qui ne correspond pas au format dans l'e-mail de l'utilisateur
  invalid_emails.each do |invalid_email|
    user.email = invalid_email
    expect(user).to be_invalid # duplicate_user.invalid?Passer si c'est vrai
  end
end

test before_save {email.downcase!}

On vérifie que l'email TeSt @ TEst.Com de ```upcase_email_userdevient test @ test.com après sauvegarde. `ʻExpect (X) .to eq Y teste" X est égal à Y ".

it 'downcase!Fonctionne correctement' do
  # before_save est appelé juste avant save, donc save!Faire
  upcase_email_user.save!
  expect(upcase_email_user.email).to eq '[email protected]'
end

validation du mot de passe

Présence: vrai, longueur: {maximum: 6} test (si un matchers)

Rédiger des tests en utilisant `` Should a Matchers '' ainsi que par courrier électronique

context 'password' do
  # presence:Vrai test
  it { should validate_presence_of(:password) }
  # length: { maximum: 6 }Test de
  it { should validate_length_of(:password).is_at_least(6) }
end

finalement

Quand j'ai appris RSpec pour la première fois, je n'étais pas familier avec la syntaxe et j'ai eu beaucoup de problèmes. Cependant, il existe de nombreux articles avec des explications faciles à comprendre, et ce sera amusant si vous vous y habituez et réussissez le test comme prévu. J'ai écrit un article sur les tests de modèles cette fois-ci, mais j'ai également appris sur les tests de requêtes, donc j'espère pouvoir écrire à ce sujet à l'avenir.

Recommended Posts

[Rails / RSpec] Ecrire un test de modèle (avec Shoulda Matchers / FactoryBot)
[Rails] Code de test à l'aide de Rspec
[RSpec] Test unitaire (avec gem: factory_bot)
[Ruby on Rails] Test de modèle avec RSpec
[Rails] Test avec RSpec
[Rails] De la préparation du test au test unitaire du modèle [RSpec]
[RSpec] Utilisons FactoryBot [Rails]
[Rails] À propos du test de réponse Rspec
J'ai essayé un test unitaire de l'application Rails en utilisant RSpec et FactoryBot
Téléchargement d'images à l'aide de CarrierWave ~ Test Rspec ~
[R Spec on Rails] Comment écrire du code de test pour les débutants par les débutants
[Rails5] Rspec -Test d'unité lors de l'imbrication-
[rails] Faisons un test unitaire avec Rspec!
[Rails] Code de test unitaire pour le modèle utilisateur
Introduire RSpec et écrire le code de test unitaire
[Ruby on Rails] Afficher le test avec RSpec
[Ruby on Rails] Test du contrôleur avec RSpec
[Ruby On Rails] Lors de l'exécution d'un test d'unité de modèle avec RSpec à l'aide de FactoryBot, une erreur se produit car la clé externe n'est pas saisie.
[Ruby On Rails] Erreur de test utilisant le client RSpec MySQL n'est pas connecté
Générer un mot de passe de compte de test à l'aide de Rails SecureRandom.alphanumeric
Présentation de Rspec, un framework de test pour Ruby on Rails