[Rails / RSpec] Schreiben Sie einen Modelltest (mit Shoulda Matchers / FactoryBot)

Einführung

Ich habe beim Schreiben von RSpec aus einem Zustand gelernt, in dem ich noch nie einen Test geschrieben hatte. Ich möchte das, was ich im Artikel verstehe, zusammen mit dem Code belassen, der es tatsächlich beschreibt.

Annahme

--Benutzertabelle

Mit Shoulda Matchers können Sie einen Test in einer Zeile schreiben, den Sie nicht ohne das Schreiben vieler Zeilen durchführen könnten. Es gibt einige Teile, von denen Sie nicht wissen, was gerade getan wird, aber es gibt andere nützliche Syntaxen als die diesmal beschriebenen Inhalte. Wenn Sie interessiert sind, empfehle ich Ihnen, dies auf der Referenzseite zu überprüfen. ..

Referenzseite

Es war sehr leicht zu verstehen und war sehr hilfreich! Vielen Dank!

Model

app/models/user.rb


class User < ApplicationRecord
  has_many :books #Eins-zu-viele-Assoziation mit Büchern
  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

Prüfung

Wir machen insgesamt 9 Tests

Ganze Datei

spec/models/user_spec.rb


# rails_Hilfsdatei lesen
require 'rails_helper'

#Benutzermodelltest, also Benutzer, type: :Wie ein Model
RSpec.describe User, type: :model do

  describe 'has_many' do
    # has_many :Bücher testen
    it { should have_many(:books) }
  end

  describe 'has_secure_password' do
    # has_secure_Passworttest
    it { should have_secure_password }
  end
  
  describe 'validation' do
    context 'email' do
      #Erstellen Sie Testdaten mit FactoryBot
      let(:user) { create(:user) }
      let(:upcase_email_user) { build(:user, :upcase_email) }

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

      # uniqueness: { case_sensitive: false }Test von
      it 'Erlaube keine doppelte Speicherung von E-Mails' do
        duplicate_user = user.dup
        duplicate_user.email = user.email.upcase
        expect(duplicate_user).to be_invalid
      end
     
      # format: { with: XXXXX }Test von
      it 'Lassen Sie keine E-Mails zu, die nicht dem angegebenen Format entsprechen' 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 von
      it 'downcase!Funktioniert richtig' do
        upcase_email_user.save!
        expect(upcase_email_user.email).to eq '[email protected]'
      end
    end

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

Erklärung jeder Beschreibung

Testerklärung

RSpec.describe Modellname, Typ :: Testformat do, und diese Beschreibung ermöglicht es Ihnen, das Benutzermodell innerhalb des Blocks zu testen.

RSpec.describe User, type: :model do

Testen von has_many und has_secure_password

Überprüfen Sie die Modellzuordnung und Anwendung von "has_secure_password" mit "Shoulda Matchers"

# has_many :Bücher testen
describe 'has_many' do
  it { should have_many(:books) }
end

# has_secure_Passworttest
describe 'has_secure_password' do
  it { should have_secure_password }
end

Trennen Sie die Testbeschreibung nach Beschreibung und Kontext

describe 'validation' do
    context 'email' do
      #Schreiben Sie einen E-Mail-Validierungstest
    end
    context 'password' do
      #Schreiben Sie einen Passwortvalidierungstest
    end
end

Erstellen Sie Testdaten mit FactoryBot

Definieren Sie die vom Factory-Bot erstellten Testdaten in einer dedizierten Datei

spec/factories/users.rb


FactoryBot.define do
  factory :user do
    #Jedes Mal, wenn Daten generiert werden, wird eine Seriennummer zugewiesen, um einen eindeutigen Wert zu erstellen.
    sequence(:email) { |n| "test#{n}@test.com" }
    password { 'password' }

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

Testdaten werden mit let basierend auf der obigen Datei erstellt, und diese Testdaten können im Block it .. do ~~ end im beschriebenen Block verwendet werden. Das Ergebnis der Überprüfung des Inhalts von user und upcase_email_user in binding.pry im Kommentar wird beschrieben.

  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>

E-Mail-Validierung

Anwesenheit: wahre Länge: {Maximum: 255} Test (Sollte ein Matcher)

Schreiben Sie Tests mit "Shoulda Matchers"

  # presence:Test wahr
  it { should validate_presence_of(:email) }
  # length: { maximum: 255 }Prüfung
  it { should validate_length_of(:email).is_at_most(255) }

Eindeutigkeit: {case_sensitive: false} Test

Erstellen Sie Kopierdaten von user mit dup method. Stellen Sie sicher, dass let (: user) {create (: user)} duplicate_user nicht mit derselben email wie der bereits registrierte user speichert. Durch Großschreiben der E-Mail mit "Großbuchstaben" vor dem Test wird auch überprüft, ob die E-Mail auch dann als gleich beurteilt wird, wenn sie in Großbuchstaben geschrieben ist.

be_invalid wird übergeben, wenn es durch Validierung zerkratzt wird (wenn ein Fehler auftritt)

it 'Erlaube keine doppelte Speicherung von E-Mails' do
  duplicate_user = user.dup
  #Inhalt an dieser Stelle
  # 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.Inhalt nach Großbuchstaben
  # #<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?Bestehen Sie, wenn es wahr ist
end

Format: {mit: / \ A [\ w + \ -.] + @ [Az \ d \ -] + (. [Az \ d \ -] +) * . [Az] + \ z / i} Prüfung

it 'Lassen Sie keine E-Mails zu, die nicht dem angegebenen Format entsprechen' do
  #Bereiten Sie 6 Zeichenfolgen vor, die nicht dem angegebenen Format entsprechen
  invalid_emails = %w[user@foo,com user_at_foo.org [email protected]@bar_baz.com foo@bar+baz.com [email protected]]
  #Überprüfen Sie dies, indem Sie eine E-Mail, die nicht dem Format entspricht, in die E-Mail des Benutzers einfügen
  invalid_emails.each do |invalid_email|
    user.email = invalid_email
    expect(user).to be_invalid # duplicate_user.invalid?Bestehen Sie, wenn es wahr ist
  end
end

test before_save {email.downcase!}

Es wird überprüft, dass die E-Mail "TeSt @ TEst.Com" von "upcase_email_user" nach dem Speichern zu "test @ test.com" wird. erwarten (X) .zu Gleichung Y testet "X ist gleich Y".

it 'downcase!Funktioniert richtig' do
  # before_Speichern wird kurz vor dem Speichern aufgerufen, also speichern!Machen
  upcase_email_user.save!
  expect(upcase_email_user.email).to eq '[email protected]'
end

Passwortüberprüfung

Anwesenheit: wahr, Länge: {Maximum: 6} Test (Sollte ein Matcher)

Schreiben Sie Tests mit "Sollte ein Matcher" sowie per E-Mail

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

Schließlich

Als ich RSpec zum ersten Mal lernte, war ich mit der Syntax nicht vertraut und hatte große Probleme. Es gibt jedoch viele leicht verständliche Erklärungsartikel, und es wird Spaß machen, wenn Sie sich daran gewöhnen und den Test wie erwartet bestehen. Diesmal habe ich einen Artikel über das Testen von Modellen geschrieben, aber ich habe auch etwas über das Testen von Anfragen gelernt, sodass ich hoffe, dass ich in Zukunft darüber schreiben kann.

Recommended Posts

[Rails / RSpec] Schreiben Sie einen Modelltest (mit Shoulda Matchers / FactoryBot)
[Rails] Testcode mit Rspec
[RSpec] Unit Test (mit gem: factory_bot)
[Ruby on Rails] Modelltest mit RSpec
[Schienen] Test mit RSpec
[Schienen] Von der Testvorbereitung zum Modelleinheitentest [RSpec]
[RSpec] Verwenden wir FactoryBot [Rails]
[Rails] Informationen zum Rspec-Antworttest
Ich habe einen Unit-Test der Rails-Anwendung mit RSpec und FactoryBot versucht
Bild-Upload mit CarrierWave ~ Rspec-Test ~
[R Spec on Rails] So schreiben Sie Testcode für Anfänger von Anfängern
[Rails5] Rspec -Einheitentest beim Verschachteln-
[Schienen] Machen wir einen Unit-Test mit Rspec!
[Rails] Unit-Testcode für das Benutzermodell
Führen Sie RSpec ein und schreiben Sie den Unit-Test-Code
[Ruby on Rails] Test mit RSpec anzeigen
[Ruby on Rails] Controller-Test mit RSpec
[Ruby On Rails] Bei der Durchführung eines Modell-Unit-Tests mit RSpec mit FactoryBot tritt ein Fehler auf, da der externe Schlüssel nicht eingegeben wurde.
[Ruby On Rails] Testfehler mit RSpec MySQL-Client ist nicht verbunden
Generieren Sie ein Testkontokennwort mit Rails SecureRandom.alphanumeric
Einführung in Rspec, ein Testframework für Ruby on Rails