FactoryBot, anciennement connus sous le nom de FactoryGirl, est une gem développée depuis 2010, et qui est utilisée dans les suites de test, comme rspec.
Elle permet de facilement créer des enregistrements dans la base de données, ou d’initialiser de nouveaux modèles, en facilitant la création des valeur par défaut.
Vous allez voir dans cet article comment l’installer, et l’utiliser efficacement.
Comment installer FactoryBot
Il suffit de rajouter la gem factory_bot
dans le groupe test de votre fichier Gemfile :
# Gemfile
group :test do
gem 'factory_bot'
end
Puis de mettre à jour bundle :
$ bundle install
Configuration de FactoryBot avec rspec
La configuration de FactoryBot est très simple. Il suffit de rajouter deux lignes à votre fichier rails_helper.rb :
# spec/rails_helper.rb
RSpec.configure do |config|
# FactoryBot syntax
config.include FactoryBot::Syntax::Methods
# FactoryBot load definitions
config.before(:suite) { FactoryBot.find_definitions }
end
La première instruction permet d’inclure la syntaxe de FactoryBot dans les tests. Ainsi vous aurez accès aux méthodes create
, build
, attributes_for
, et bien d’autres.
La deuxième instruction permet de charger les factories au démarrage de la suite de tests.
Définir les factories
Pour pouvoir utiliser FactoryBot, il faut lui indiquer quelles sont les valeurs par défaut des modèles, ce que vous pouvez faire en créant des factories.
Dans le répertoire spec, créez un réfectoire factories, c’est là que vous créerez vos factories.
Prenons l’exemple du modèle User
, qui nécessite la présence des champs email
et password
. Voici comment écrire la factory pour ce modèle :
# spec/factories/user.rb
FactoryBot.define do
factory :user do
email { 'email@company.com' }
password { 'debug_password' }
end
end
Utiliser les factories
À l’intérieur de vos tests, vous pouvez créer des modèles valide très simplement, dans un bloc let!
par exemple :
let!(:user) { create :user }
Cette simple instruction crée et enregistre dans la base de donnée un modèle User en utilisant les valeurs que vous avez définies dans la factory.
S’il vous voulez utiliser une valeur autre que celle définit dans la factory, il suffit simplement de la passer comme un argument supplémentaire à la méthode create
:
let!(:user) { create :user, email: 'something else' }
Prenons un exemple concret. Dans les spec du modèle User, vous vérifiez que le modèle valide la présence de son attribut email
. Voici à quoi pourrait ressembler le test :
# spec/models/user_spec.rb
RSpec.describe User, type: :model do
describe 'validate presence of email" do
context 'email is present' do
let(:user) { create :user, email: 'email@company.com' }
it { expect(user.valid?).to be(true) }
end
context 'email is absent' do
let(:user) { create :user, email: '' }
it { expect(user.valid?).to be(false) }
end
end
end
Dans chacun des deux contextes, on commence par créer un modèle user dans un bloc let!
à l’aide de sa factory, puis ensuite on procède aux tests.
Remarquez, dans le premier contexte, que même si une valeur pour email est définit dans la factory, on la redéfinit dans le bloc let!
. Ceci permet pouvoir lire le test et d’en comprendre le contexte facilement, mais surtout de s’assurer que le test continuera à fonctionner même si on modifie la syntaxe de la factory.
Quels sont les avantage d’utiliser des factories ?
Comme on vient de le voir les factories permettent de définir les champs des modèles sans que nous ayons à le refaire à chaque endroit de nos tests.
Actuellement la factory user ne définit que 2 champs, mais si dans le futur vous devez ajoute un nouveau champ au modèle, par exemple le champ name
, et que le modèle en nécessite sa présence, il suffira seulement de l’ajouter à la factory, et l’ensemble des tests continueront à fonctionner.