Rails Buchbesprechung App RSpec Einführung

RSpec eingeführt

Anstelle des Standard-Rails-Minitests werden wir RSpec einführen, das eine höhere Akzeptanzrate aufweist als der Minitest in der Praxis. Wir werden mehr über ** TDD (Test Driven Development) und BDD (Behavior Driven Development) ** erfahren, die Testmethoden sind.

verschiedene Einstellungen

Capybara ・ ・ ・ Simuliert den Browserbetrieb von Webanwendungen FactoryBot gem ・ ・ Ein Juwel, das die Erstellung einer Testdatenbank unterstützt

Jede Gem-Installation

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'rspec-rails',       '~> 4.0.0'
  gem 'factory_bot_rails', '~> 4.11'
  gem 'capybara',          '~> 2.13'
end

$bundle $bin/rails g rspec:install Minitest-Verzeichnis löschen $rm -r ./test Schreiben Sie die folgende Beschreibung in .rspec, damit das Ergebnis der Testausführung leicht sichtbar ist. --format documentation Färbung --color

Erste Vorbereitung für Capybar

spec/spec_helper.rb


require 'capybara/rspec'

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :selenium_chrome_headless
  end

Webtreibereinstellungen

Installieren Sie Web-Treiber, mit denen Chrome Driver problemlos installiert werden kann Gem'webdrivers' hinzugefügt $ mkdir spec/support $ touch spec/support/driver_setting.rb

spec/support/driver_setting.rb


RSpec.configure do |config|
  config.before(:each, type: :system) do
    #Bei der Ausführung von Spec kann der Browser automatisch starten und das Verhalten überprüfen.
    # driven_by(:selenium_chrome)

    #Browser AUS, wenn Spec ausgeführt wird
    driven_by(:selenium_chrome_headless)
  end
end

Bereiten Sie die Erstellung von Testdaten mit FactoryBot vor

Normalerweise können Sie eine Methode ohne FactoryBot nicht aufrufen user = FactoryBot.create(:user)

Durch Hinzufügen der obigen Einstellungen kann die Beschreibung von FactoryBot weggelassen werden. user = create(:user)

spec/rails_helper.rb


require "support/factory_bot"

spec/support/factory_bot.rb


RSpec.configure do |config|
  #Vereinfachung des FactoryBot-Aufrufs
  config.include FactoryBot::Syntax::Methods

  #Verhindern Sie, dass das Werk aufgrund der Feder ordnungsgemäß geladen wird
  config.before :all do
    FactoryBot.reload
  end
end

spec/rails_helper.rb


#Kommentieren Sie diesen Code aus
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

** User Factory definieren **

spec/factories/users.rb


FactoryBot.define do
  factory :user do
    name { 'Benutzer testen' }
    email { '[email protected]' }
    password { 'password' }  
  end
end

** Definieren Sie eine Überprüfungsfabrik **

spec/factories/reviews.rb


FactoryBot.define do
  factory :review do
    title { "MyString" }
    author { "MyString" }
    description { "MyText" }
    user
  end
end

Führen Sie spring-command-rspec ein

Dieses Juwel beschleunigt den Teststart

group :development do
  gem 'spring-commands-rspec'
end

bundle install und dann bundle exec spring binstub rspec generieren eine rspec-Datei im bin-Verzeichnis

#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
require 'bundler/setup'
load Gem.bin_path('rspec-core', 'rspec')

Sollte Matchers Einstellungen

Shoulda Mathers ist ein Juwel, mit dem Sie Tests präzise und intuitiv schreiben können, indem Sie RSpec und Minitest eine einzeilige Testsyntax hinzufügen.

group :test do
  gem 'shoulda-matchers'

  #Für Rails5 oder höher
  gem 'shoulda-matchers', git: 'https://github.com/thoughtbot/shoulda-matchers.git', branch: 'rails-5'
end

spec/support/shoulda_matchers.rb


Shoulda::Matchers.configure do |config|
  config.integrate do |with|
    with.test_framework :rspec
    with.library :rails
  end
end

spec/rails_helper.rb


require "support/shoulda_matchers"

config/application.rb


require_relative 'boot'
require 'rails/all'
require 'uri'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module BookReviewApp
  class Application < Rails::Application
    config.load_defaults 5.1
    config.generators.template_engine = :slim
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]

    config.generators do |g| 
      g.test_framework :rspec,
        fixtures: false, 
        view_specs: false, 
        helper_specs: false, 
        routing_specs: false
    end
  end
end

Schreiben Sie den Code für den Modelltest

Erstellen Sie einen Ordner mit dem Namen models im Ordner spec, erstellen Sie eine Datei user_spec.rb im Ordner models und schreiben Sie den folgenden Code $ mkdir spec/models $ touch spec/models/user_spec.rb

spec/mogels/user_spec.rb


require 'rails_helper'

RSpec.describe User, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"

  context "if name is entered" do              
    it 'if user registration is successful' do 
    end
  end

  context "if name is not entered" do          
    it 'if user registration fails' do
    end
  end
  
  context 'if email is entered' do
    it 'if user registration is successful' do
    end
  end

  context 'if email is not entered' do
    it 'if user registration fails' do
    end
  end

  context "if password is entered" do
    it 'if user registration is successful' do
    end
  end

  context "if password is not entered" do
    it 'if user registration fails' do
    end
  end
end
 #Die Sprache der Testbeschreibung hängt von der Syntax ab

 #Beispielsyntax
example 'japanisch' do
  #Code schreiben
end

  #es Syntax
it 'English' do
  #Code schreiben
end

Wenn Sie nur diese Datei testen möchten, müssen Sie die Datei angeben $ bundle exec rspec spec/models/user_spec.rb

Beispiele: Vorhandene Tests / Fehler: Fehlgeschlagene / ausstehende Tests: Nicht ausgeführte Tests

Systemspezifikation der Anzeigefunktion für Überprüfungslisten

$ mkdir spec/system/ $ touch spec/system/reviews_spec.rb

Machen Sie zunächst einen Überblick über Spec mit Kommentaren

spec/system/reviews_spec.rb


require 'rails_helper'

describe 'Überprüfen Sie die Verwaltungsfunktion', type: :system do
    describe 'Listenanzeigefunktion' do
        before do 
        #Benutzer A erstellen
        #Erstellen Sie eine Bewertung, deren Autor Benutzer A ist
        end

context 'Wenn der Benutzer angemeldet ist' do
    before do 
        #Benutzer A meldet sich an
    end

    it 'Von Benutzer A erstellte Bewertungen werden angezeigt' do
        #Stellen Sie sicher, dass der Titel der erstellten Überprüfung auf dem Bildschirm angezeigt wird
    end
  end
 end
end

Beschreiben Sie in "beschreiben" "wofür Sie die Spezifikation beschreiben möchten" (Testziel). Die äußerste Beschreibung beschreibt das Thema der gesamten Spec-Datei. Beschreiben Sie ein detaillierteres Thema in der tieferen Beschreibung.

"Kontext" wird verwendet, um den Testinhalt nach der Variation von "Status / Status" zu klassifizieren. Sie können die Tests organisieren und vereinfachen, um festzustellen, ob sie unter verschiedenen Bedingungen ordnungsgemäß funktionieren müssen.

before ist der Ort, an dem der Code geschrieben wird, um die" Voraussetzungen "des gesamten Bereichs auszuführen. Wenn Sie zuvor in Beschreibung oder Kontext schreiben, wird der im Vorher-Block geschriebene Code ausgeführt, bevor der Testcode im entsprechenden Beschreibungs- oder Kontextbereich ausgeführt wird.

it beschreibt das erwartete Verhalten in Sätzen und Code im Block. Wenn das Ziel wie erwartet funktioniert, ist der Test erfolgreich.



Ersetzen Sie jeden Kommentar durch den tatsächlichen Code

spec/system/reviews_spec.rb


require 'rails_helper'

describe 'Überprüfen Sie die Verwaltungsfunktion', type: :system do
    describe 'Listenanzeigefunktion' do
        before do 
        #Benutzer A erstellen
        user_a = create(:user, name: 'Benutzer A.', email: '[email protected]')
        #Erstellen Sie eine Bewertung, deren Autor Benutzer A ist
        create(:review, name: 'Erste Überprüfung', user: user_a)
        end

context 'Wenn der Benutzer angemeldet ist' do
    before do 
        #Benutzer A meldet sich an
        visit login_path
        fill_in 'Mail Adresse', with: '[email protected]'
        fill_in 'Passwort', with: 'password'
        click_button 'Anmeldung'
    end 

    it 'Von Benutzer A erstellte Bewertungen werden angezeigt' do
        #Stellen Sie sicher, dass der Titel der erstellten Überprüfung auf dem Bildschirm angezeigt wird
        expect(page).to have_content 'Erste Überprüfung'
    end
  end
 end
end
 #Wenn der Test fehlschlägt
$ bundle exec rspec spec/system/reviews_spec.rb

Überprüfen Sie die Verwaltungsfunktion
Listenanzeigefunktion
Wenn der Benutzer angemeldet ist
Von Benutzer A erstellte Bewertungen werden angezeigt(FAILED - 1)

Failures:

  1)Überprüfungsverwaltungsfunktion Listenanzeigefunktion Von Benutzer A erstellte Überprüfungen werden angezeigt, wenn der Benutzer angemeldet ist.
     Failure/Error: user_a = FactoryBot.create(user, name: 'Benutzer A.', email: '[email protected]')
     
     NameError:
       undefined local variable or method `user' for #<RSpec::ExampleGroups::Nested::Nested::Nested:0x00007fed26346f28>
     
     [Screenshot]: tmp/screenshots/failures_r_spec_example_groups_nested_nested_nested_Vom Benutzer a erstellte Bewertungen werden angezeigt_412.png


     
     # ./spec/system/reviews_spec.rb:7:in `block (3 levels) in <top (required)>'

Finished in 4.19 seconds (files took 5.32 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/system/reviews_spec.rb:21 #Überprüfungsverwaltungsfunktion Listenanzeigefunktion Von Benutzer A erstellte Überprüfungen werden angezeigt, wenn der Benutzer angemeldet ist.

Systemspezifikation für neue Überprüfungsfunktion

spec/system/reviews_spec.rb


.
.
.
describe 'Neue Überprüfungsfunktion' do
    let(:login_user) { :user_a }

    before do 
        visit new_review_path
        fill_in 'Titel', with: review_name
        click_button 'Post'
    end

    context 'Bei der Eingabe eines Titels auf dem neuen Beitragsbildschirm' do
        let(:review_name) { 'Schreiben Sie einen Test für einen neuen Beitrag' }

        it 'Erfolgreich gepostet' do
            expect(page).to have_selector 'alert-success', text: 'Schreiben Sie einen Test für einen neuen Beitrag'
        end
    end

    context 'Wenn Sie den Titel nicht auf dem neuen Post-Bildschirm eingegeben haben' do
        let(:review_name) { '' }

        it 'Erhalten Sie einen Fehler' do
            within '#error_explanation' do
            expect(page).to have_content 'Bitte geben Sie einen Titel ein'
        end
      end
    end
  end
end

let ist eine Funktion, die in einem Bild verwendet werden kann, ähnlich wie "Zuweisen eines Werts zu einer Testbereichsvariablen vor der Verarbeitung" (es wird tatsächlich keine Variable erstellt). let (Definitionsname) {Inhalt der Definition}

Mit einem Matcher namens have_selector können Sie bestimmte Elemente in HTML mit Selektoren (CSS-Selektoren) angeben. have_selector

Mithilfe der darin aufgerufenen Methode können Sie den Suchbereich auf einen bestimmten Bereich auf dem Bildschirm eingrenzen, indem Sie den Inhalt der Seite innerhalb des Blocks "innerhalb" überprüfen. innerhalb eines Bereichs angeben 'do

Testen des Benutzermodells

Machen Sie einen groben Umriss mit Kommentaren

spec/models/user_spec.rb


 # validations
 describe "validations" do
   #Existenz
   describe "presence" do
     #Name, E-Mail-Adresse
     it "name and email should not ro be empty/falsy"
     #Passwort, Passwortbestätigung
     context "when password and confirmation is not present" do
       it "@user is invalid"
     end
    end
   #Anzahl der Zeichen Zeichen
   describe "charesters" do
     #Name: bis zu 20 Zeichen
     context "when name is too long"
       it "@user is inavlid"
     #Passwort, Passwortbestätigung: mindestens 6 Zeichen
     describe "when password is too short"
       it "@user is inavlid"
   end
 #E-Mail Format
 describe "email format" do
   #ungültiges Format
   context "when invalid format" do
     it "@user is inavlid"
   #gültiges Format
   context "when valid format" do
     it "@user is valid"
   end
   end
  end
end

Füllen Sie die Kommentare aus

spec/models/user_spec.rb


RSpec.describe User, type: :model do
  #Ausstehende Vorlage
  pending "add some examples to (or delete) #{__FILE__}"

 # validations
 describe "validations" do
   #Existenz
   describe "presence" do
     #Name, E-Mail-Adresse
     it { should validate_presence_of :name }
     it { should validate_presence_of :email }
     #Passwort, Passwortbestätigung
     context "when password and confirmation is not present" do
       before { user.password = user.password_confirmation = " " } 
       it { should_not be_valid }
     end
    end
   #Anzahl der Zeichen Zeichen
   describe "charesters" do
     #Name: bis zu 20 Zeichen,Passwort: Mindestens 6 Zeichen
     it { should validate_length_of(:name).is_at_most(20) }
     it { should validate_length_of(:password).is_at_least(6) }
   end
 #E-Mail Format
 describe "email format" do
   #ungültiges Format
   context "when invalid format" do
     #Ungültiges Objekt
     it "should be invalid" do
       invalid_addr = %w[user@foo,com user_at_foo.org example.user@foo. foo@bar_baz.com foo@bar+baz.com]
       invalid_addr.each do |addr|
         user.email = addr
         expect(user).not_to be_valid
       end
      end
    end
  end
   #gültiges Format
   context "when valid format" do
     #Gültige Objekte
     it "should be valid" do
       valid_addr = %w[[email protected] [email protected] [email protected] [email protected]]
       valid_addr.each do |addr|
         user.email = addr
         expect(user).to be_valid
       end
     end
   end
  end
end

↓ Testergebnis ↓

console.log


$ bundle exec rspec spec/models/user_spec.rb

User
  add some examples to (or delete) /Users/kiyokawakouji/Rails-app/book_review_app/spec/models/user_spec.rb (PENDING: Not yet implemented)
  validations
    presence
      is expected to validate that :name cannot be empty/falsy
      is expected to validate that :email cannot be empty/falsy
      when password and confirmation is not present
        example at ./spec/models/user_spec.rb:17 (FAILED - 1)
    charesters
      is expected to validate that the length of :name is at most 20
      is expected to validate that the length of :password is at least 6
    email format
      when invalid format
        should be invalid (FAILED - 2)
    when valid format
      should be valid (FAILED - 3)

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) User add some examples to (or delete) /Users/kiyokawakouji/Rails-app/book_review_app/spec/models/user_spec.rb
     # Not yet implemented
     # ./spec/models/user_spec.rb:5


Failures:

  1) User validations presence when password and confirmation is not present 
     Failure/Error: before { user.password = user.password_confirmation = " " }
     
     NameError:
       undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::Presence::WhenPasswordAndConfirmationIsNotPresent:0x00007fd1586e2770>
     # ./spec/models/user_spec.rb:16:in `block (5 levels) in <top (required)>'

  2) User validations email format when invalid format should be invalid
     Failure/Error: user.email = addr
     
     NameError:
       undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::EmailFormat::WhenInvalidFormat:0x00007fd15831d6f8>
     # ./spec/models/user_spec.rb:34:in `block (6 levels) in <top (required)>'
     # ./spec/models/user_spec.rb:33:in `each'
     # ./spec/models/user_spec.rb:33:in `block (5 levels) in <top (required)>'

  3) User validations when valid format should be valid
     Failure/Error: user.email = addr
     
     NameError:
       undefined local variable or method `user' for #<RSpec::ExampleGroups::User::Validations::WhenValidFormat:0x00007fd1582d5790>
     # ./spec/models/user_spec.rb:46:in `block (5 levels) in <top (required)>'
     # ./spec/models/user_spec.rb:45:in `each'
     # ./spec/models/user_spec.rb:45:in `block (4 levels) in <top (required)>'

Finished in 0.61427 seconds (files took 5.94 seconds to load)
8 examples, 3 failures, 1 pending

Failed examples:

rspec ./spec/models/user_spec.rb:17 # User validations presence when password and confirmation is not present 
rspec ./spec/models/user_spec.rb:31 # User validations email format when invalid format should be invalid
rspec ./spec/models/user_spec.rb:43 # User validations when valid format should be valid

** Erklärung der Testergebnisse unten ** Wie im Kommentar geschrieben, ist "panding" eine Vorlage, die zeigt, wie man RSpec schreibt (diesmal habe ich es gewagt, es aufzuwecken, ohne es zu löschen), also ist es vorbei. (FAILED-number) zeigt an, dass der Testcode fehlgeschlagen ist. Diesmal ist der Testcode an drei Stellen fehlgeschlagen. Failures: ~ gibt den entsprechenden Code und die Fehlerdetails aus, bei denen der Test fehlgeschlagen ist. Fehlerbeispiel: ~ gibt die Zeile des entsprechenden Codes in der Datei aus, in der der Test fehlgeschlagen ist, und das erwartete Verhalten. Da dies ein Modelltest ist, werden wir die Validierungen überprüfen

app/models/user.rb


class User < ApplicationRecord
 devise :database_authenticatable, :rememberable, 
        :validatable, :timeoutable, :registerable, :confirmable

 #Ist der Wert des Namens leer?
 validates :name, presence: true
 #Ist der Wert des Namens 20 Zeichen oder weniger?
 validates :name, length: { maximum: 20 }
 #Verringern Sie die E-Mail-Adresse, wenn Sie die E-Mail-Adresse in der Datenbank speichern
 before_save { self.email = email.downcase }
 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
 #Entspricht die E-Mail der Bestätigungseingabe?
 validates :email, { presence: true, format: { with: VALID_EMAIL_REGEX } }
 validates :email, :encrypted_password, confirmation: true
 #Ist der Passwortwert leer?
 validates :password, presence: true
 #Ist das Passwort 6 Zeichen oder mehr?
 validates :password, length: { minimum: 6 }
 #Benutzer verknüpfen und in der Datenbank überprüfen
 has_many :reviews, dependent: :destroy, foreign_key: :review_user_id
end

Sonderedition

** Einstellung, um nur fehlgeschlagene Tests erneut auszuführen (Option --only-failed) **

spec_helper.rb


RSpec.configure do |config|
  config.example_status_persistence_file_path = "./spec/examples.txt"
end

------------------------------------------------------------------

Wenn Sie Git verwenden.Fügen Sie gitignore auch die folgenden Einstellungen hinzu.
spec/examples.txt

$ bundle exec rspec --only-failures

rspec Optionen

Liste der Optionen für rspec
$ rspec --help

Ausgabe ohne Ausführung einer Testliste
$ rspec --dry-run

Ausgangstestwarnung
$ rspec --warnings
Dieser Befehl zeigt eine Warnung in der Spezifikationsdatei an. Wenn ein Rechtschreibfehler vorliegt, geben Sie ihn in die Warnung ein und geben Sie ihn aus

Als ich $ rsoec --warnings ausprobierte, wurde die folgende Ausgabe ausgegeben

WARN: Unresolved or ambiguous specs during Gem::Specification.reset:
      diff-lcs (>= 1.2.0, < 2.0)
      Available/installed versions of this gem:
      - 1.4
      - 1.3
WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
~~Kürzung~~

Es wird gesagt, dass dasselbe Juwel in mehreren Versionen installiert ist und es nicht möglich ist, zu entscheiden, welches auf dem System behandelt werden soll. Sie müssen die alte Version des Edelsteins entfernen und auf eine eingrenzen oder sich für eine bestimmte Version entscheiden.

Testtyp

** Gesamttest ** ・ Systemspezifikation / Funktionsspezifikation ・ Integrationstest (Anforderungsspezifikation) ・ Funktionsprüfung (Controller Spec) ** Einzelteiletest ** ・ Modell (Modellspezifikation) ・ Routing-Spezifikation · View Spec ・ Helferspez ・ Mailer (Mailer-Spezifikation) ・ Job (Jobspezifikation)

Zuverlässigkeit des Testcodes selbst

Sie müssen sicherstellen, dass der Testcode wie vorgesehen funktioniert. Dies wird auch als "Ausüben des zu testenden Codes" bezeichnet. Um zu beweisen, dass es sich nicht um ein falsches Positiv handelt, ändern Sie beispielsweise "to" in "to_not" und kehren Sie die Erwartung um.

spec/models/user_spec.rb


 #Wenn kein Name vorhanden ist, befindet er sich in einem ungültigen Zustand(Erfolg)
 it "is invalid without a first name" do
   user = User.new(first_name: nil)
   user.valid?
   expect(user.errors[:first_name]).to include("can't be blank")
 end

 #Wenn kein Name vorhanden ist, befindet er sich in einem ungültigen Zustand(Fehler)
 it "is invalid without a first name" do
   user = User.new(first_name: nil)
   user.valid?
   expect(user.errors[:first_name]).to_not include("can't be blank")
 end

Referenz

Grundlagen der Rails-RSpec-Vorbereitung und des Testcodes [Rails] Einführung "RSpec + FactoryBot + Capybara + Webdrivers" und erste Einstellung zum Testen des Schreibens Erstellen einer SystemSpec-Umgebung mit Rails + Selenium + Docker https://github.com/everydayrails/everydayrails-rspec-2017 Einführung in RSpec, das verwendet werden kann, Teil 1 "Grundlegende Syntax und nützliche Funktionen von RSpec" RSpec-Einstellungen Nützliche Optionen für Rspec Verwendung von Rails-Rückrufen, die ich nach dem Leiden endlich verstanden habe

Recommended Posts

Rails Buchbesprechung App RSpec Einführung
Rails Review 1
Rails Review 2
Rspec Einführung note_Rails
[Rails 6] cocoon_ Einführung
Rspec Basics [Rails]
[Rails5] Rspec -validierung-
[Ruby on Rails] Bis zur Einführung von RSpec
[Rails] Einführung von PAY.JP
[Schienen] Test mit RSpec
[Rails] entwickeln eine Einführungsmethode
Schienen, RSpec-Installationsverfahren
Ich habe einen Unit-Test der Rails-Anwendung mit RSpec und FactoryBot versucht
[Rails] Einführung in die Grundlagen der Entwicklung
[RSpec] Verwenden wir FactoryBot [Rails]
[Rails] Testcode mit Rspec
[Rails] Informationen zum Rspec-Antworttest
Integrieren Sie circleCI in die CircleCI Rails-App
[Rails 6] Sternförmige Überprüfung mit Raty.js