[RUBY] J'ai essayé un test unitaire de l'application Rails en utilisant RSpec et FactoryBot

Aperçu

Depuis que nous avons testé l'application développée personnellement créée en tant que portfolio Je voudrais revenir sur le flux de test en tant que résultat personnel. Cette fois, ce sera le contenu de base du test lié à la validation du modèle.

supposition

Tester en programmation signifie «s'assurer que le programme fonctionne comme prévu».

environnement

Ruby 2.5.1 Rails 5.2.3

Modèle utilisateur créé à l'aide de gem'devise '

introduction

Tout d'abord, installez le Gem utilisé pour les tests.

Gem utilisé cette fois

--rspec-rails ▶ ︎RSpec, un bijou pour Rails, un langage spécialisé pour les tests --factory_bot ▶ ︎ Une gemme qui vous permet de créer facilement une instance factice

Gemfile


group :development, :test do
réduction

  gem 'factory_bot_rails'
  gem 'rspec-rails'
end

Terminal


$ bundle install

Ceci termine l'installation de la gemme.

Définir RSpec

Tout d'abord, vous devez générer un fichier pour RSpec, alors exécutez la commande suivante.

Terminal


$ rails g rspec:install

Cela générera les fichiers suivants.

Terminal


create .rspec
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb

Ajoutez la description suivante à .rspec

.rspec


--format documentation

À ce stade, vous pouvez exécuter le test avec la commande suivante.

Terminal


$ bundle exec rspec

Écrire le code de test pour la classe de modèle

J'écris enfin le code de test Placez le fichier de spécification où vous écrivez le code de test dans le répertoire nommé spec généré en cours de route. De plus, comme le fichier de spécification du modèle est rassemblé dans le répertoire du modèle, créons le répertoire et le fichier avec un éditeur de texte.

  1. Créez un répertoire appelé models sous le répertoire spec.
  2. Créez un fichier de spécification de modèle dans le répertoire spec / models.

** * La convention de dénomination des fichiers de spécification est que le fichier de spécification portera le nom de classe correspondant name_spec.rb. ** **

Cette fois, nous partirons du principe que nous effectuerons un test lié à la validation du modèle User, donc créez user_spec.rb.

Tout d'abord, nous allons tester un par un pour voir si chaque validation au moment de l'enregistrement d'un nouvel utilisateur est appliquée. Cette fois, la validation du modèle User se fait dans les conditions suivantes.

app/models/user.rb


class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  validates :nickname, :email, :password, :password_confirmation, presence: true
end

Testez les 4 colonnes sur lesquelles le valide présence: true est appliqué.


Tout d'abord, testez la validation du pseudo avec la description de base.

spec/models/user_spec.rb


require 'rails_helper'
describe User do
  describe '#create' do
    it "Impossible de s'inscrire sans pseudo" do
     user = User.new(nickname: "", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
     user.valid?
     expect(user.errors[:nickname]).to include("can't be blank")
    end
  end
end

La première ligne décrit le fichier à lire pour le test. La deuxième ligne décrit la classe de modèle. La troisième ligne décrit le nom de l'action à tester.

La chaîne qui se termine entre la 4e et la 8e ligne est le code de test pour chacune. La 4ème ligne décrit le contenu à tester. La 5ème ligne décrit la création d'une instance, mais elle est décrite avec une hypothèse réaliste sauf que le surnom est vide. Dans la 6ème ligne, si vous écrivez une méthode? Valide dans l'instance créée, vous pouvez vérifier "si elle ne peut pas être sauvegardée par validation" lors de l'enregistrement d'une instance d'une classe qui hérite d'ActiveRecord :: Base. .. La 7ème ligne décrit les résultats de test attendus pour le contenu de la 6ème ligne. La valeur de retour de la méthode? Valide est true ou false, mais si vous utilisez la méthode des erreurs pour une instance qui utilise la méthode? Valide, vous pouvez vérifier pourquoi elle ne peut pas être enregistrée si elle ne peut pas être enregistrée en raison de la validation. Dans ce cas, nous utilisons la matrice d'inclusion ci-dessous pour prédire qu'un "message d'erreur" ne peut pas être vide "apparaîtra".

Zackri en japonais "Parce que le surnom de l'utilisateur est vide, écrivez une attente que vous obtiendrez l'erreur" Je ne peux pas le vider "." C'est comme

Faisons le test ici

Terminal


$ bundle exec rspec

1 example, 0 failures

Si vous voyez le message "0 échecs pour un test" comme indiqué ci-dessus, c'est OK.

Je testerai également d'autres validations, En utilisant le factory_bot introduit en premier, le code de test de la partie de création d'instance utilisateur peut être partagé, ce qui est assez pratique.

Utiliser factory_bot

Commençons par créer un répertoire appelé usines sous le répertoire spec. Créez-y un fichier appelé users.rb. ** * La dénomination des fichiers est unifiée avec plusieurs noms de modèles **

Ensuite, dans un fichier vide, décrivez les parties communes pour créer une instance de modèle.

spec/factories/users.rb


FactoryBot.define do

  factory :user do
    nickname              {"Taro Tanaka"}
    email                 {"[email protected]"}
    password              {"1234567"}
    password_confirmation {"1234567"}
  end

end

Je n'ai rien à expliquer de particulier Lorsque vous créez une instance du modèle utilisateur avec le code de test, elle sera exécutée à chaque fois avec le contenu décrit.

#C'est
user = User.new(nickname: "Taro Tanaka", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
#Ceci peut être réalisé
user = FactoryBot.build(:user)

Quelle simplification supplémentaire de ce code. Il y a une description de read'rails_helper'in user_spec.rb, Faites quelques modifications dans ce fichier rails_helper.rb.

spec/rails_helper.rb


#réduction
RSpec.configure do |config|
  #Ajout de la description suivante
  config.include FactoryBot::Syntax::Methods

  #réduction

end

Maintenant, vous êtes prêt à partir. Alors ...

#C'est
user = User.new(nickname: "Taro Tanaka", email: "[email protected]", password: "1234567", password_confirmation: "1234567")
#Ceci peut être réalisé
user = FactoryBot.build(:user)
#Peut être omis davantage
user = build(:user)

La quantité de code est considérablement réduite ...

Quand j'ai appris cela pour la première fois, je mets des valeurs dans toutes les colonnes, mais puis-je reproduire une colonne vide lors du test de validation? Il y avait une question ➡︎ Vous pouvez le faire sans problème

Regardons le reste du code de test.

spec/models/user_spec.rb


require 'rails_helper'

describe User do
  describe '#create' do
    it "Impossible de s'inscrire sans pseudo" do
      user = build(:user, nickname: "")
      user.valid?
      expect(user.errors[:nickname]).to include("can't be blank")
    end

    it "Impossible de s'inscrire sans e-mail" do
      user = build(:user, email: "")
      user.valid?
      expect(user.errors[:email]).to include("can't be blank")
    end
    
    it "Impossible de s'inscrire sans mot de passe" do
      user = build(:user, password: "")
      user.valid?
      expect(user.errors[:password]).to include("can't be blank")
    end

    it "mot de passe même si le mot de passe existe_Impossible de s'inscrire sans confirmation" do
      user = build(:user, password_confirmation: "")
      user.valid?
      expect(user.errors[:password_confirmation]).to include("doesn't match Password")
    end
    
    it "Impossible de s'inscrire si le mot de passe est de 5 caractères ou moins" do
      user = build(:user, password: "00000", password_confirmation: "00000")
      user.valid?
      expect(user.errors[:password]).to include("is too short (minimum is 6 characters)")
    end

    #Nous effectuons également des tests lorsque l'inscription est possible
    it "pseudo et email, mot de passe et mot de passe_Si la confirmation existe, vous pouvez vous inscrire" do
      user = build(:user)
      expect(user).to be_valid
    end

    it "Vous pouvez vous inscrire si le mot de passe contient 6 caractères ou plus" do
      user = build(:user, password: "000000", password_confirmation: "000000")
      user.valid?
      expect(user).to be_valid
    end
  end
end

L'explication ci-dessus

user = build(:user)
user = build(:user, nickname: "")

En spécifiant à nouveau le nom et la valeur de la colonne comme dans la deuxième ligne Vous pouvez écraser la valeur prédéfinie. Dans le cas de cet exemple, le surnom: "Ichiro Tanaka" est remplacé par le surnom: "". En faisant cela, vous pouvez modifier la valeur prédéfinie de manière flexible (nil est également acceptable).

it "mot de passe même si le mot de passe existe_Impossible de s'inscrire sans confirmation" do
      user = build(:user, password_confirmation: "")
      user.valid?
      expect(user.errors[:password_confirmation]).to include("doesn't match Password")
    end

En outre, ce qui précède comprend une partie matcher Comme "ne peut pas être vide" Le message d'erreur "ne correspond pas au mot de passe" D'où êtes-vous? Je pense écrire quelque chose comme ça Si vous ne savez pas depuis le début, vous ne pouvez pas prédire le message d'erreur ...?

Il fut un temps où je le pensais ** (Note: je suis encore un débutant) **


Bien que ces messages d'erreur soient fournis à l'origine par Rails Gem En fin de compte, vous pouvez toujours exécuter le test

.to include("")

Ensuite, le résultat de l'exécution du test sera affiché dans le terminal. Vous vous attendiez à recevoir le message d'erreur "", mais le message d'erreur réel était "ne correspond pas au mot de passe"! Sera retourné.

Puis Ah! Oui oui! C'est ce que Wai voulait écrire dans le test! Tu comprends

Vous pouvez également ouvrir la console pour vérifier et confirmer le flux, Je pense que cette méthode est suffisante si la quantité de tests des applications développées personnellement est faible au niveau débutant. (Il a l'air en colère)

De plus, les deux derniers tests sont des tests lorsque l'enregistrement de l'utilisateur est possible. Il existe un matcher be_valid. Ceci est utilisé lorsque vous dites "cela effacera toutes les validations".

Enfin, essayez d'exécuter le test

Terminal


$ bundle exec rspec

7 example, 0 failures

Si le nombre d'échecs est égal à 0 pour le nombre de tests, c'est OK.

Résumé

En utilisant RSpec et FactoryBot, je suis revenu sur un simple test de modèle de Rails. Le test que j'ai effectué cette fois n'est qu'une partie, mais j'ai écrit le flux de base et de petites histoires, donc j'espère qu'il aidera ceux qui sont nouveaux dans l'apprentissage.
De plus, si vous trouvez des lacunes dans le contenu, veuillez nous en informer. Enfin, je voudrais mentionner l'article Qiita auquel j'ai fait référence au cours de mon étude. Merci beaucoup.

Article de référence

Recommended Posts

J'ai essayé un test unitaire de l'application Rails en utilisant RSpec et FactoryBot
À propos du test d'application RSpec (test unitaire)
[RSpec] Test unitaire (avec gem: factory_bot)
[Android] J'ai quitté SQLite et essayé d'utiliser Realm
J'ai essayé d'utiliser Gson
J'ai essayé d'utiliser TestNG
J'ai essayé d'utiliser Galasa
[Rails] De la préparation du test au test unitaire du modèle [RSpec]
[Rails / RSpec] Ecrire un test de modèle (avec Shoulda Matchers / FactoryBot)
J'ai essayé d'utiliser YOLO v4 sur Ubuntu et ROS
[Rails] J'ai essayé d'utiliser la méthode button_to pour la première fois
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Ce à quoi j'étais accro en utilisant rspec sur des rails
[RSpec] Utilisons FactoryBot [Rails]
J'ai essayé d'utiliser azure cloud-init
J'ai essayé Rails débutant [Chapitre 1]
[Rails] Code de test à l'aide de Rspec
J'ai essayé d'utiliser Apache Wicket
J'ai essayé d'utiliser Java REPL
J'ai essayé Rails débutant [Chapitre 2]
J'ai essayé d'intégrer parfaitement Docker et Maven / Netbean en utilisant Jib
J'ai essayé de créer une application simple en utilisant Dockder + Rails Scaffold
J'ai essayé d'utiliser anakia + Jing maintenant
J'ai essayé d'utiliser Spring + Mybatis + DbUnit
Présentation de l'application de révision de livres Rails RSpec
J'ai essayé d'utiliser JOOQ avec Gradle
[Rails] J'ai essayé de supprimer l'application
[Rails5] Rspec -Test d'unité lors de l'imbrication-
J'ai essayé d'utiliser l'API Java8 Stream
J'ai essayé d'utiliser JWT en Java
[Android] J'ai essayé d'utiliser la disposition du coordinateur.
J'ai essayé d'utiliser le conteneur Pari gp
J'ai essayé d'utiliser WebAssembly Stadio (version 2018/4/17)
J'ai essayé d'utiliser le mémo Java LocalDate
[rails] Faisons un test unitaire avec Rspec!
J'ai essayé d'utiliser Google HttpClient de Java
Mode API Rails J'ai essayé d'implémenter la fonction de recherche multiple par mot-clé à l'aide de tableaux et d'un traitement itératif.
J'ai présenté WSL2 + Ubuntu à Window10 et essayé d'utiliser GDC, DMD, LDC
J'ai créé et défini mon propre dialecte avec Thymeleaf et j'ai essayé de l'utiliser
J'ai essayé de créer mon propre guide de transfert en utilisant OpenTrip Planner et GTFS
Redirection et test unitaire à l'aide de la lunette Spring Flash
J'ai essayé d'utiliser l'API Elasticsearch en Java
J'ai essayé d'utiliser Realm avec Swift UI
Introduire RSpec et écrire le code de test unitaire
J'ai essayé d'utiliser l'outil de diagnostic Java Arthas
J'ai essayé d'utiliser UICollectionViewListCell ajouté à partir de Xcode12.
J'ai essayé d'utiliser Scalar DL avec Docker
J'ai essayé d'utiliser OnlineConverter avec SpringBoot + JODConverter
C'est nouveau, mais j'ai essayé d'utiliser Groonga
J'ai essayé d'utiliser OpenCV avec Java + Tomcat
Remarque lors de la création d'une usine plusieurs-à-plusieurs avec Rspec et des tests avec SystemSpec [RSpec, FactoryBot]
J'ai essayé d'utiliser "nifty cloud mobile backend" et l'authentification "Firebase" sur Kotlin + Android
[JDBC ③] J'ai essayé d'entrer à partir de la méthode principale en utilisant des espaces réservés et des arguments.