Présentation de l'application de révision de livres Rails RSpec

Présentation de RSpec

Au lieu du minitest Rails standard, nous introduirons RSpec, qui a un taux d'adoption plus élevé que le minitest en pratique. Nous en apprendrons plus sur ** TDD (Test Driven Development) et BDD (Behavior Driven Development) **, qui sont des méthodes de test.

divers paramètres

Capybara ・ ・ ・ Simule le fonctionnement du navigateur d'applications Web FactoryBot ・ ・ ・ Un joyau qui prend en charge la création d'une base de données de test

Chaque installation Gem

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 Supprimer le répertoire minitest $rm -r ./test Écrivez la description suivante en .rspec afin que le résultat de l'exécution du test soit facilement visible. --format documentation coloration --color

Préparation initiale pour Capybar

spec/spec_helper.rb


require 'capybara/rspec'

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

paramètres de webdrivers

Installez des pilotes Web qui installeront facilement le pilote Chrome Ajout de gem'webdrivers' $ mkdir spec/support $ touch spec/support/driver_setting.rb

spec/support/driver_setting.rb


RSpec.configure do |config|
  config.before(:each, type: :system) do
    #Lors de l'exécution de Spec, le navigateur peut démarrer automatiquement et vérifier le comportement.
    # driven_by(:selenium_chrome)

    #Browser OFF lorsque Spec est exécuté
    driven_by(:selenium_chrome_headless)
  end
end

Préparez-vous à créer des données de test avec FactoryBot

Normalement, vous ne pouvez pas appeler une méthode sans FactoryBot user = FactoryBot.create(:user)

En ajoutant les paramètres ci-dessus, la description de FactoryBot peut être omise. user = create(:user)

spec/rails_helper.rb


require "support/factory_bot"

spec/support/factory_bot.rb


RSpec.configure do |config|
  #Simplification des appels FactoryBot
  config.include FactoryBot::Syntax::Methods

  #Empêcher l'usine de charger correctement en raison du ressort
  config.before :all do
    FactoryBot.reload
  end
end

spec/rails_helper.rb


#Décommentez ce code
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

** Définir l'usine utilisateur **

spec/factories/users.rb


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

** Définir une usine d'avis **

spec/factories/reviews.rb


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

Introduire spring-commands-rspec

Ce joyau accélère le démarrage du test

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

bundle install puis bundle exec spring binstub rspec généreront un fichier rspec dans le répertoire bin

#!/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')

Paramètres de Shoulda Matchers

Shoulda Mathers est un joyau qui permet d'écrire des tests de manière concise et intuitive en ajoutant une syntaxe de test à une ligne à RSpec et Minitest.

group :test do
  gem 'shoulda-matchers'

  #Pour rails5 ou version ultérieure
  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

Ecrire le code du test du modèle

Créez un dossier appelé models dans le dossier spec, créez un fichier user_spec.rb dans le dossier models et écrivez le code suivant $ 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
 #La langue de la description du test dépend de la syntaxe

 #exemple de syntaxe
example 'Japonais' do
  #Ecrire le code
end

  #syntaxe
it 'English' do
  #Ecrire le code
end

Si vous souhaitez tester uniquement ce fichier, vous devez spécifier le fichier $ bundle exec rspec spec/models/user_spec.rb

exemples: tests existants / échecs: tests ayant échoué / en attente: tests non exécutés

Spécification système de la fonction d'affichage de la liste d'examen

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

Tout d'abord, faites un aperçu de Spec avec des commentaires

spec/system/reviews_spec.rb


require 'rails_helper'

describe 'Fonction de gestion des revues', type: :system do
    describe 'Fonction d'affichage de liste' do
        before do 
        #Créer l'utilisateur A
        #Créer un avis dont l'auteur est l'utilisateur A
        end

context 'Lorsque l'utilisateur est connecté' do
    before do 
        #L'utilisateur A se connecte
    end

    it 'Les avis créés par l'utilisateur A sont affichés' do
        #Confirmez que le titre de l'avis créé est affiché à l'écran
    end
  end
 end
end

Dans describe, décrivez" ce que vous essayez de décrire la spécification pour "(cible du test). La description la plus externe décrit le sujet de l'ensemble du fichier Spec. Décrivez un thème plus détaillé dans la description plus approfondie.

context est utilisé pour classer le contenu du test en fonction de la variation de" statut / état ". Vous pouvez organiser et faciliter les tests pour voir que vous devez tester pour voir s'ils fonctionnent correctement dans diverses conditions.

before est l'endroit où écrire le code pour exécuter les" conditions préalables "de la zone entière. Si vous écrivez avant dans describe ou context, le code écrit dans le bloc before sera exécuté avant d'exécuter le code de test dans la zone de description ou de contexte correspondante.

it décrit le comportement attendu dans les phrases et le code dans le bloc. Si la cible fonctionne comme prévu, le test réussit.



Remplacez chaque commentaire par le code réel

spec/system/reviews_spec.rb


require 'rails_helper'

describe 'Fonction de gestion des revues', type: :system do
    describe 'Fonction d'affichage de liste' do
        before do 
        #Créer l'utilisateur A
        user_a = create(:user, name: 'Utilisateur A', email: '[email protected]')
        #Créer un avis dont l'auteur est l'utilisateur A
        create(:review, name: 'Premier examen', user: user_a)
        end

context 'Lorsque l'utilisateur est connecté' do
    before do 
        #L'utilisateur A se connecte
        visit login_path
        fill_in 'adresse mail', with: '[email protected]'
        fill_in 'mot de passe', with: 'password'
        click_button 's'identifier'
    end 

    it 'Les avis créés par l'utilisateur A sont affichés' do
        #Confirmez que le titre de l'avis créé est affiché à l'écran
        expect(page).to have_content 'Premier examen'
    end
  end
 end
end
 #Si le test échoue
$ bundle exec rspec spec/system/reviews_spec.rb

Fonction de gestion des revues
Fonction d'affichage de liste
Lorsque l'utilisateur est connecté
Les avis créés par l'utilisateur A sont affichés(FAILED - 1)

Failures:

  1)Fonction de gestion des avis Fonction d'affichage de liste Les avis créés par l'utilisateur A s'affichent lorsque l'utilisateur est connecté.
     Failure/Error: user_a = FactoryBot.create(user, name: 'Utilisateur 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_Les avis créés par l'utilisateur a sont affichés_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 #Fonction de gestion des avis Fonction d'affichage de liste Les avis créés par l'utilisateur A s'affichent lorsque l'utilisateur est connecté.

Spécifications du système pour une nouvelle fonction d'examen

spec/system/reviews_spec.rb


.
.
.
describe 'Nouvelle fonction d'examen' do
    let(:login_user) { :user_a }

    before do 
        visit new_review_path
        fill_in 'Titre', with: review_name
        click_button 'Publier'
    end

    context 'Lors de la saisie d'un titre sur l'écran du nouvel article' do
        let(:review_name) { 'Rédiger un test pour un nouveau message' }

        it 'Publié avec succès' do
            expect(page).to have_selector 'alert-success', text: 'Rédiger un test pour un nouveau message'
        end
    end

    context 'Lorsque vous n'avez pas saisi le titre sur l'écran du nouvel article' do
        let(:review_name) { '' }

        it 'Obtenez une erreur' do
            within '#error_explanation' do
            expect(page).to have_content 'Veuillez entrer un titre'
        end
      end
    end
  end
end

let est une fonction qui peut être utilisée dans une image similaire à "attribuer une valeur à une variable de portée de test avant le traitement" (elle ne crée pas réellement de variable) let (nom de la définition) {contenu de la définition}

Un matcher appelé have_selector vous permet de spécifier un élément spécifique en HTML avec un sélecteur (sélecteur CSS). have_selector

En utilisant la méthode appelée within, vous pouvez restreindre la plage de recherche à une plage spécifique à l'écran en inspectant le contenu de la page à l'intérieur du bloc within. within'spécifiez une plage 'do

Test du modèle utilisateur

Faites un aperçu avec des commentaires

spec/models/user_spec.rb


 # validations
 describe "validations" do
   #Existence
   describe "presence" do
     #Nom, adresse e-mail
     it "name and email should not ro be empty/falsy"
     #Mot de passe, confirmation du mot de passe
     context "when password and confirmation is not present" do
       it "@user is invalid"
     end
    end
   #Nombre de caractères caractères
   describe "charesters" do
     #Nom: jusqu'à 20 caractères
     context "when name is too long"
       it "@user is inavlid"
     #Mot de passe, confirmation du mot de passe: 6 caractères minimum
     describe "when password is too short"
       it "@user is inavlid"
   end
 #Format Email
 describe "email format" do
   #format invalide
   context "when invalid format" do
     it "@user is inavlid"
   #format valide
   context "when valid format" do
     it "@user is valid"
   end
   end
  end
end

Remplissez les commentaires

spec/models/user_spec.rb


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

 # validations
 describe "validations" do
   #Existence
   describe "presence" do
     #Nom, adresse e-mail
     it { should validate_presence_of :name }
     it { should validate_presence_of :email }
     #Mot de passe, confirmation du mot de passe
     context "when password and confirmation is not present" do
       before { user.password = user.password_confirmation = " " } 
       it { should_not be_valid }
     end
    end
   #Nombre de caractères caractères
   describe "charesters" do
     #Nom: jusqu'à 20 caractères,Mot de passe: 6 caractères minimum
     it { should validate_length_of(:name).is_at_most(20) }
     it { should validate_length_of(:password).is_at_least(6) }
   end
 #Format Email
 describe "email format" do
   #format invalide
   context "when invalid format" do
     #Objet invalide
     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
   #format valide
   context "when valid format" do
     #Objets valides
     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

↓ Résultat du test ↓

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

** Explication des résultats des tests ci-dessous ** Comme écrit dans le commentaire, panding est un modèle qui montre comment écrire RSpec (cette fois je l'ai réveillé sans l'effacer), donc c'est fini. (FAILED-number) indique que le code de test a échoué. Cette fois, le code de test à trois endroits a échoué. Failures: ~ affiche le code correspondant et les détails d'erreur indiquant que le test a échoué. Exemple d'échecs: ~ affiche la ligne du code correspondant dans le fichier où le test a échoué et le comportement attendu. Puisqu'il s'agit d'un test de modèle, nous vérifierons les validations

app/models/user.rb


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

 #La valeur du nom est-elle vide?
 validates :name, presence: true
 #La valeur du nom est-elle de 20 caractères ou moins?
 validates :name, length: { maximum: 20 }
 #Réduisez l'adresse e-mail lors de l'enregistrement de l'adresse e-mail dans la base de données
 before_save { self.email = email.downcase }
 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
 #L'e-mail correspond-il à l'entrée de confirmation?
 validates :email, { presence: true, format: { with: VALID_EMAIL_REGEX } }
 validates :email, :encrypted_password, confirmation: true
 #La valeur du mot de passe est-elle vide?
 validates :password, presence: true
 #La valeur du mot de passe est-elle de 6 caractères ou plus?
 validates :password, length: { minimum: 6 }
 #Lier l'utilisateur et l'examen sur la base de données
 has_many :reviews, dependent: :destroy, foreign_key: :review_user_id
end

Édition supplémentaire

** Paramètre pour réexécuter uniquement les tests ayant échoué (option --only-failures) **

spec_helper.rb


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

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

Si vous utilisez git.Ajoutez également les paramètres suivants à gitignore.
spec/examples.txt

$ bundle exec rspec --only-failures

options rspec

Liste des options pour rspec
$ rspec --help

Sortie sans exécuter une liste de tests
$ rspec --dry-run

Avertissement de test de sortie
$ rspec --warnings
Cette commande affiche un avertissement dans le fichier de spécifications. S'il y a une faute d'orthographe, mettez-la dans l'avertissement et affichez-la

Quand j'ai essayé $ rsoec --warnings, la sortie suivante était sortie

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.
~~réduction~~

On dit que la même gemme est installée dans plusieurs versions et il n'est pas possible de décider laquelle gérer sur le système. Vous devez supprimer l'ancienne version de la gemme et la réduire à une seule ou choisir une version spécifique.

Type de test

** Test global ** ・ Spécifications du système / Spécifications des fonctionnalités ・ Test d'intégration (demande de spécification) ・ Test fonctionnel (spécification du contrôleur) ** Test de pièces individuelles ** ・ Modèle (spécification du modèle) ・ Spécifications de routage · Voir les spécifications ・ Helper Spec ・ Mailer (Mailer Spec) ・ Travail (spécification du travail)

Fiabilité du code de test lui-même

Vous devez vous assurer que le code de test fonctionne comme prévu. Ceci est également connu sous le nom d '«exercice du code sous test». Pour prouver qu'il ne s'agit pas d'un faux positif, par exemple, changez to en to_not et inversez l'attente.

spec/models/user_spec.rb


 #S'il n'y a pas de nom, il est dans un état invalide(Succès)
 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

 #S'il n'y a pas de nom, il est dans un état invalide(Échec)
 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

référence

Rails RSpec Preparation and Test Code Basics [Rails] Introduction et configuration initiale de "RSpec + FactoryBot + Capybara + Webdrivers" pour tester l'écriture Création d'un environnement SystemSpec avec Rails + Selenium + Docker https://github.com/everydayrails/everydayrails-rspec-2017 Introduction à RSpec utilisable, Partie 1 «Comprendre la syntaxe de base et les fonctions utiles de RSpec» Paramètres RSpec Options utiles pour Rspec Comment utiliser les rappels Rails que j'ai finalement compris après avoir souffert

Recommended Posts

Présentation de l'application de révision de livres Rails RSpec
Rails Examen 1
Rails Revue 2
Rspec introduction note_Rails
[Rails 6] cocoon_ introduction
Principes de base de Rspec [Rails]
[Rails5] Rspec -validation-
[Ruby on Rails] Jusqu'à l'introduction de RSpec
[Rails] Présentation de PAY.JP
[Rails] Test avec RSpec
[Rails] conçoit une méthode d'introduction
Rails, procédure d'installation RSpec
J'ai essayé un test unitaire de l'application Rails en utilisant RSpec et FactoryBot
[Rails] Introduction aux principes de base du dispositif
[RSpec] Utilisons FactoryBot [Rails]
[Rails] Code de test à l'aide de Rspec
[Rails] À propos du test de réponse Rspec
Incorporer circleCI dans l'application CircleCI Rails
[Rails 6] Revue en forme d'étoile utilisant Raty.js