Skip to content
Menu
CDhistory
CDhistory

Iniziare

Posted on Agosto 17, 2021 by admin
  • Aggiorna il tuo Gemfile
  • Configura la tua suite di test
  • Test::Unit
  • Cucumber
  • Spinach
  • Minitest
  • Minitest::Spec
  • minitest-rails
  • Definizione delle fabbriche
  • Usare le fabbriche
  • Attributi dinamici
  • Alias
  • Attributi dipendenti
  • Attributi transitori
  • Nome del metodo / Attributi di parole riservate
  • Eredità
  • Associazioni
  • Sequenze
  • Traits
  • Callbacks
  • Modificare le fabbriche
  • Costruire o creare record multipli
  • Linting delle fabbriche
  • Costruzione personalizzata
  • Strategie personalizzate
  • Callback personalizzati
  • Metodi personalizzati per persistere gli oggetti
  • ActiveSupport Instrumentation
  • Preloader Rails e RSpec
  • Usando senza Bundler

Aggiorna il tuo Gemfile

Se stai usando Rails, dovrai cambiare la versione richiesta di factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Se non stai usando Rails, dovrai solo cambiare la versione richiesta di factory_girl:

gem "factory_girl", "~> 4.0"
export JRUBY_OPTS=--1.9

Una volta aggiornato il tuo Gemfile, dovrai aggiornare il tuo bundle.

Configura la tua suite di test

Ricordati di richiedere il file di cui sopra nel tuo rails_helper poiché la cartella di supporto non è caricata in modo avido

require 'support/factory_girl'

Test::Unit

class Test::Unit::TestCase include FactoryGirl::Syntax::Methodsend

Cucumber

# env.rb (Rails example location - RAILS_ROOT/features/support/env.rb)World(FactoryGirl::Syntax::Methods)

Spinach

class Spinach::FeatureSteps include FactoryGirl::Syntax::Methodsend

Minitest

class Minitest::Unit::TestCase include FactoryGirl::Syntax::Methodsend

Minitest::Spec

class Minitest::Spec include FactoryGirl::Syntax::Methodsend

minitest-rails

class ActiveSupport::TestCase include FactoryGirl::Syntax::Methodsend

Se non includete FactoryGirl::Syntax::Methods nella vostra suite di test, allora tutti i metodi factory_girl dovranno essere preceduti da FactoryGirl.

Definizione delle fabbriche

Ogni fabbrica ha un nome e un insieme di attributi. Il nome è usato per indovinare la classe dell’oggetto per default, ma è possibile specificarlo esplicitamente:

Si raccomanda vivamente di avere una factory per ogni classe che fornisca l’insieme più semplice di attributi necessari per creare un’istanza di quella classe. Se stai creando oggetti ActiveRecord, ciò significa che dovresti fornire solo gli attributi che sono richiesti attraverso le validazioni e che non hanno default. Altre fabbriche possono essere create attraverso l’ereditarietà per coprire scenari comuni per ogni classe.

Tentando di definire più fabbriche con lo stesso nome verrà generato un errore.

Le fabbriche possono essere definite ovunque, ma saranno caricate automaticamente dopo aver chiamato FactoryGirl.find_definitions se le fabbriche sono definite in file nelle seguenti posizioni:

test/factories.rbspec/factories.rbtest/factories/*.rbspec/factories/*.rb

Usare le fabbriche

factory_girl supporta diverse strategie di costruzione: build, create, attributes_for e build_stubbed:

Non importa quale strategia sia usata, è possibile sovrascrivere gli attributi definiti passando un hash:

# Build a User instance and override the first_name propertyuser = build(:user, first_name: "Joe")user.first_name# => "Joe"

Attributi dinamici

La maggior parte degli attributi di fabbrica possono essere aggiunti usando valori statici che sono valutati quando la fabbrica è definita, ma alcuni attributi (come le associazioni e altri attributi che devono essere generati dinamicamente) avranno bisogno di valori assegnati ogni volta che un’istanza viene generata. Questi attributi “dinamici” possono essere aggiunti passando un blocco invece di un parametro:

factory :user do # ... activation_code { User.generate_activation_code } date_of_birth { 21.years.ago }end

A causa della sintassi dei blocchi in Ruby, definire attributi come Hashes (per colonne serializzate/JSON, per esempio) richiede due serie di parentesi graffe:

factory :program do configuration { { auto_resolve: false, auto_define: true } }end

Alias

factory_girl ti permette di definire alias a factory esistenti per renderle più facili da riutilizzare. Questo potrebbe essere utile quando, per esempio, il tuo oggetto Post ha un attributo author che in realtà si riferisce ad un’istanza della classe User. Mentre normalmente factory_girl può dedurre il nome del factory dal nome dell’associazione, in questo caso cercherà invano un factory autore. Quindi, date un alias alla vostra fabbrica utente in modo che possa essere usata sotto nomi di alias.

Attributi dipendenti

Gli attributi possono essere basati sui valori di altri attributi usando il valutatore che viene fornito ai blocchi di attributi dinamici:

Attributi transitori

Ci possono essere momenti in cui il vostro codice può essere DRYED up passando attributi transitori alle fabbriche.

Gli attributi statici e dinamici possono essere creati come attributi transitori. Gli attributi transitori saranno ignorati all’interno di attributes_for e non saranno impostati sul modello, anche se l’attributo esiste o si tenta di sovrascriverlo.

Negli attributi dinamici di factory_girl, si può accedere agli attributi transitori come ci si aspetterebbe. Se avete bisogno di accedere al valutatore in una callback di factory_girl, dovrete dichiarare un secondo argomento di blocco (per il valutatore) e accedere agli attributi transitori da lì.

Nome del metodo / Attributi di parole riservate

Se i vostri attributi sono in conflitto con metodi esistenti o parole riservate, potete definirli con add_attribute.

factory :dna do add_attribute(:sequence) { 'GATTACA' }endfactory :payment do add_attribute(:method) { 'paypal' }end

Eredità

Puoi facilmente creare più factory per la stessa classe senza ripetere attributi comuni annidando le factory:

Puoi anche assegnare il genitore esplicitamente:

factory :post do title "A title"endfactory :approved_post, parent: :post do approved trueend

Come detto sopra, è buona pratica definire una factory di base per ogni classe con solo gli attributi richiesti per crearla. Poi, creare factory più specifiche che ereditano da questo genitore di base. Le definizioni di fabbrica sono ancora codice, quindi mantenetele DRY.

Associazioni

È possibile impostare associazioni all’interno delle fabbriche. Se il nome della fabbrica è lo stesso dell’associazione, il nome della fabbrica può essere omesso.

factory :post do # ... authorend

Puoi anche specificare una fabbrica diversa o sovrascrivere gli attributi:

factory :post do # ... association :author, factory: :user, last_name: "Writely"end

Il comportamento del metodo dell’associazione varia a seconda della strategia di costruzione usata per l’oggetto padre.

Per non salvare l’oggetto associato, specificare la strategia: :build nella fabbrica:

Si noti che l’opzione strategy: :build deve essere passata a una chiamata esplicita a association, e non può essere usata con associazioni implicite:

factory :post do # ... author strategy: :build # <<< this does *not* work; causes author_id to be nil

Generare dati per una relazione has_many è un po’ più complesso, a seconda della quantità di flessibilità desiderata, ma ecco un esempio sicuro di generazione di dati associati.

FactoryGirl.define do # post factory with a `belongs_to` association for the user factory :post do title "Through the Looking Glass" user end # user factory without associated posts factory :user do name "John Doe" # user_with_posts will create post data after the user has been created factory :user_with_posts do # posts_count is declared as a transient attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do posts_count 5 end # the after(:create) yields two values; the user instance itself and the # evaluator, which stores all values from the factory, including transient # attributes; `create_list`'s second argument is the number of records # to create and we make sure the user is associated properly to the post after(:create) do |user, evaluator| create_list(:post, evaluator.posts_count, user: user) end end endend

Questo ci permette di fare:

create(:user).posts.length # 0create(:user_with_posts).posts.length # 5create(:user_with_posts, posts_count: 15).posts.length # 15

Generare dati per una relazione has_and_belongs_to_many è molto simile alla precedente relazione has_many, con un piccolo cambiamento, è necessario passare una serie di oggetti al nome dell’attributo pluralizzato del modello piuttosto che un singolo oggetto alla versione singola del nome dell’attributo.

Ecco un esempio con due modelli correlati tramitehas_and_belongs_to_many:

FactoryGirl.define do # language factory with a `belongs_to` association for the profile factory :language do title "Through the Looking Glass" profile end # profile factory without associated languages factory :profile do name "John Doe" # profile_with_languages will create language data after the profile has # been created factory :profile_with_languages do # languages_count is declared as an ignored attribute and available in # attributes on the factory, as well as the callback via the evaluator transient do languages_count 5 end # the after(:create) yields two values; the profile instance itself and # the evaluator, which stores all values from the factory, including # ignored attributes; `create_list`'s second argument is the number of # records to create and we make sure the profile is associated properly # to the language after(:create) do |profile, evaluator| create_list(:language, evaluator.languages_count, profiles: ) end end endend

Questo ci permette di fare:

Sequenze

I valori unici in un formato specifico (per esempio, gli indirizzi e-mail) possono essere generati usando sequenze. Le sequenze sono definite chiamando sequence nel blocco di definizione, e i valori in una sequenza sono generati chiamandogenerate:

Le sequenze possono essere usate in attributi dinamici:

factory :invite do invitee { generate(:email) }end

O come attributi impliciti:

factory :user do email # Same as `email { generate(:email) }`end

E’ anche possibile definire una sequenza in linea che è usata solo in una particolare fabbrica:

factory :user do sequence(:email) { |n| "person#{n}@example.com" }end

Puoi anche sovrascrivere il valore iniziale:

factory :user do sequence(:email, 1000) { |n| "person#{n}@example.com" }end

Senza un blocco, il valore aumenterà da solo, partendo dal suo valore iniziale:

factory :post do sequence(:position)end

Le sequenze possono anche avere alias. Gli alias delle sequenze condividono lo stesso contatore:

Definire gli alias e usare il valore predefinito (1) per il contatore

factory :user do sequence(:email, aliases: ) { |n| "person#{n}@example.com" }end

Impostare il valore:

factory :user do sequence(:email, 'a', aliases: ) { |n| "person#{n}@example.com" }end

Il valore deve solo supportare il metodo #next. Qui il prossimo valore sarà ‘a’, poi ‘b’, ecc.

Traits

ITraits ti permettono di raggruppare gli attributi e poi applicarli a qualsiasi factory.

I traits possono essere usati come attributi:

Traits che definiscono gli stessi attributi non solleveranno AttributeDefinitionErrors; il trait che definisce l’ultimo attributo ha la precedenza.

Puoi anche sovrascrivere singoli attributi concessi da un tratto nelle sottoclassi.

I tratti possono anche essere passati come lista di simboli quando costruisci un’istanza da factory_girl.

Questa capacità funziona con build, build_stubbed, attributes_for e create.

create_list e build_list sono supportati anche i metodi. Ricordati solo di passare il numero di istanze da creare/costruire come secondo parametro, come documentato nella sezione “Costruire o creare record multipli” di questo file.

I tratti possono essere usati facilmente anche con le associazioni:

Quando stai usando nomi di associazioni che sono diversi dalla fabbrica:

I tratti possono essere usati all’interno di altri tratti per mescolare i loro attributi.

factory :order do trait :completed do completed_at { 3.days.ago } end trait :refunded do completed refunded_at { 1.day.ago } endend

Infine, i tratti possono accettare attributi transitori.

Callbacks

factory_girl rende disponibili quattro callback per iniettare del codice:

Esempi:

Nota che avrai un’istanza dell’utente nel blocco. Questo può essere utile.

Puoi anche definire più tipi di callback sulla stessa fabbrica:

factory :user do after(:build) { |user| do_something_to(user) } after(:create) { |user| do_something_else_to(user) }end

Le fabbriche possono anche definire qualsiasi numero dello stesso tipo di callback. Queste callback saranno eseguite nell’ordine in cui sono specificate:

factory :user do after(:create) { this_runs_first } after(:create) { then_this }end

Chiamando create saranno invocate entrambe le callback after_build e after_create.

Inoltre, come gli attributi standard, le fabbriche figlie ereditano (e possono anche definire) callback dalla loro fabbrica madre.

Multipli callback possono essere assegnati per eseguire un blocco; questo è utile quando si costruiscono varie strategie che eseguono lo stesso codice (dato che non ci sono callback condivisi tra tutte le strategie).

Per sovrascrivere le callback per tutte le fabbriche, definiscile all’interno del bloccoFactoryGirl.define:

Puoi anche chiamare callback che si basano su Symbol#to_proc:

Modificare le fabbriche

Se ti viene dato un insieme di fabbriche (per esempio, da uno sviluppatore di gemme) ma vuoi cambiarle per adattarle meglio alla tua applicazione, puoi modificare quella fabbrica invece di creare una fabbrica figlia e aggiungerci gli attributi.

Se una gemma vi desse una fabbrica Utente:

FactoryGirl.define do factory :user do full_name "John Doe" sequence(:username) { |n| "user#{n}" } password "password" endend

Invece di creare una fabbrica figlia che aggiunga ulteriori attributi:

Potreste invece modificare quella fabbrica.

FactoryGirl.modify do factory :user do full_name "Jane Doe" date_of_birth { 21.years.ago } gender "Female" health 90 endend

Quando modificate una fabbrica, potete cambiare tutti gli attributi che volete (a parte i callback).

FactoryGirl.modify deve essere chiamato al di fuori di un blocco FactoryGirl.define perché opera sulle fabbriche in modo diverso.

Un avvertimento: potete modificare solo le fabbriche (non le sequenze o i tratti) e le callback continuano a comporre come farebbero normalmente. Quindi, se la fabbrica che stai modificando definisce un callback after(:create), definendo un after(:create) non lo sovrascriverai, verrà semplicemente eseguito dopo il primo callback.

Costruire o creare record multipli

A volte, vorrai creare o costruire istanze multiple di una fabbrica in una volta sola.

built_users = build_list(:user, 25)created_users = create_list(:user, 25)

Questi metodi costruiranno o creeranno un numero specifico di factory e li restituiranno come array.per impostare gli attributi per ciascuna delle factory, puoi passare un hash come faresti normalmente.

twenty_year_olds = build_list(:user, 25, date_of_birth: 20.years.ago)

build_stubbed_list vi darà istanze completamente stubbate:

stubbed_users = build_stubbed_list(:user, 25) # array of stubbed users

C’è anche una serie di metodi *_pair per creare due record alla volta:

built_users = build_pair(:user) # array of two built userscreated_users = create_pair(:user) # array of two created users

Se avete bisogno di più hash di attributi, attributes_for_list li genererà:

users_attrs = attributes_for_list(:user, 25) # array of attribute hashes

Linting delle fabbriche

factory_girl permette il linting delle fabbriche note:

FactoryGirl.lint

FactoryGirl.lint crea ogni fabbrica e cattura qualsiasi eccezione sollevata durante il processo di creazione. FactoryGirl::InvalidFactoryError viene sollevato con una lista di fabbriche (e le eccezioni corrispondenti) per le fabbriche che non possono essere create.

L’uso raccomandato di FactoryGirl.lintè di eseguirlo in un task prima che la vostra suite di test venga eseguita.Eseguirlo in un before(:suite), avrà un impatto negativo sulle prestazioni dei vostri test quando si eseguono test singoli.

Esempio di task Rake:

Dopo aver chiamato FactoryGirl.lint, probabilmente vorrete svuotare il database, dato che molto probabilmente verranno creati dei record. L’esempio fornito sopra usa la gemma database_cleaner per ripulire il database; assicurati di aggiungere la gemma al tuo Gemfile sotto i gruppi appropriati.

Puoi fare il linting dei factory selettivamente passando solo i factory che vuoi listare:

factories_to_lint = FactoryGirl.factories.reject do |factory| factory.name =~ /^old_/endFactoryGirl.lint factories_to_lint

Questo linting di tutti i factory che non hanno il prefisso old_.

I tratti possono anche essere lincerati. Questa opzione verifica che ogni tratto di una fabbrica generi da solo un oggetto valido.Si attiva passando traits: true al metodo lint:

FactoryGirl.lint traits: true

Questo può anche essere combinato con altri argomenti:

FactoryGirl.lint factories_to_lint, traits: true

Si può anche specificare la strategia usata per il linting:

FactoryGirl.lint strategy: :build

Costruzione personalizzata

Se vuoi usare factory_girl per costruire un oggetto in cui alcuni attributi sono passati a initialize o se vuoi fare qualcosa di diverso dal chiamare semplicemente new sulla tua classe di build, puoi sovrascrivere il comportamento predefinito definendo initialize_with sulla tua factory. Esempio:

Anche se factory_girl è scritto per funzionare con ActiveRecord, può anche funzionare con qualsiasi classe Ruby. Per la massima compatibilità con ActiveRecord, l’inizializzatore predefinito costruisce tutte le istanze chiamando new sulla tua classe di costruzione senza alcun argomento. Poi chiama i metodi di scrittura degli attributi per assegnare tutti i valori degli attributi. Mentre questo funziona bene per ActiveRecord, in realtà non funziona per quasi tutte le altre classi Ruby.

Puoi sovrascrivere l’inizializzatore per:

  • Costruire oggetti non ActiveRecord che richiedono argomenti per initialize
  • Utilizzare un metodo diverso da new per istanziare l’istanza
  • Fare cose folli come decorare l’istanza dopo che è stata costruita

Quando usi initialize_with, non devi dichiarare la classe stessa quando chiami new; tuttavia, qualsiasi altro metodo di classe che volete chiamare dovrà essere chiamato esplicitamente sulla classe.

Per esempio:

factory :user do name "John Doe" initialize_with { User.build_with_name(name) }end

Puoi anche accedere a tutti gli attributi pubblici all’interno del blocco initialize_with chiamando attributes:

factory :user do transient do 5 end name "John Doe" initialize_with { new(attributes) }end

Questo costruirà un hash di tutti gli attributi da passare a new. Non includerà gli attributi transitori, ma tutto il resto definito nel factory sarà passato (associazioni, sequenze valutate, ecc.)

Puoi definire initialize_with per tutte le factory includendolo nel bloccoFactoryGirl.define:

FactoryGirl.define do initialize_with { new("Awesome first argument") }end

Quando usi initialize_with, gli attributi accessibili dall’interno del blocco initialize_with sono assegnati solo nel costruttore; questo equivale all’incirca al seguente codice:

FactoryGirl.define do factory :user do initialize_with { new(name) } name { 'value' } endendbuild(:user)# runsUser.new('value')

Questo previene l’assegnazione duplicata; nelle versioni di factory_girl precedenti alla 4.0, verrebbe eseguito questo:

Strategie personalizzate

Ci sono momenti in cui si potrebbe voler estendere il comportamento di factory_girl aggiungendo una strategia di costruzione personalizzata.

Le strategie definiscono due metodi: association e result. associationriceve un’istanza FactoryGirl::FactoryRunner, sulla quale potete chiamarerun, sovrascrivendo la strategia se volete. Il secondo metodo, result, riceve un’istanza FactoryGirl::Evaluation. Fornisce un modo per innescare i callback (con notify), object o hash (per ottenere l’istanza del risultato o un ahash basato sugli attributi definiti nella factory), e create, che esegue il callback to_create definito nella factory.

Per capire come factory_girl usa le strategie internamente, è probabilmente più semplice visualizzare il sorgente per ciascuna delle quattro strategie di default.

Ecco un esempio di composizione di una strategia usandoFactoryGirl::Strategy::Create per costruire una rappresentazione JSON del modello.

Per far sì che factory_girl riconosca la nuova strategia, puoi registrarla:

FactoryGirl.register_strategy(:json, JsonStrategy)

Questo ti permette di chiamare

FactoryGirl.json(:user)

Infine, puoi sovrascrivere le strategie di factory_girl se vuoi registrando un nuovo oggetto al posto delle strategie.

Callback personalizzati

I callback personalizzati possono essere definiti se stai usando strategie personalizzate:

Metodi personalizzati per persistere gli oggetti

Di default, la creazione di un record chiamerà save! sull’istanza; poiché questo non è sempre ideale, si può sovrascrivere questo comportamento definendo to_create sulla fabbrica:

factory :different_orm_model do to_create { |instance| instance.persist! }end

Per disabilitare del tutto il metodo di persistenza sulla creazione, si può skip_createper quella fabbrica:

factory :user_without_database do skip_createend

Per sovrascrivere to_create per tutte le fabbriche, definirlo all’interno del bloccoFactoryGirl.define:

FactoryGirl.define do to_create { |instance| instance.persist! } factory :user do name "John Doe" endend

ActiveSupport Instrumentation

Al fine di tracciare quali fabbriche sono create (e con quale strategia di costruzione), ActiveSupport::Notifications sono inclusi per fornire un modo per sottoscrivere le fabbriche in esecuzione. Un esempio potrebbe essere quello di tracciare le fabbriche basate su una soglia di tempo di esecuzione.

Un altro esempio potrebbe essere quello di tracciare tutte le fabbriche e come sono usate nella tua suite di test. Se state usando RSpec, è semplice come aggiungere unbefore(:suite) e after(:suite):

Preloader Rails e RSpec

Quando si esegue RSpec con un preloader Rails come spring o zeus, è possibile incontrare un errore ActiveRecord::AssociationTypeMismatch quando si crea una fabbrica con associazioni, come sotto:

L’errore si verifica durante l’esecuzione della suite di test:

Le due possibili soluzioni sono o eseguire la suite senza il preloader, o aggiungere FactoryGirl.reload alla configurazione di RSpec, così:

RSpec.configure do |config| config.before(:suite) { FactoryGirl.reload }end

Usando senza Bundler

Se non stai usando Bundler, assicurati di avere la gemma installata e chiama:

require 'factory_girl'

Una volta richiesto, assumendo che tu abbia una struttura di directory di spec/factories otest/factories, tutto quello che dovrai fare è eseguire

FactoryGirl.find_definitions

Se stai usando una struttura di directory separata per i tuoi factory, puoi cambiare i percorsi dei file di definizione prima di cercare le definizioni:

FactoryGirl.definition_file_paths = %w(custom_factories_directory)FactoryGirl.find_definitions

Se non avete una directory separata di fabbriche e volete definirle in linea, anche questo è possibile:

require 'factory_girl'FactoryGirl.define do factory :user do name 'John Doe' date_of_birth { 21.years.ago } endend

Lascia un commento Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Articoli recenti

  • Acela è tornato: NYC o Boston per $99
  • I genitori di Kate Albrecht – Per saperne di più sul padre Chris Albrecht e la madre Annie Albrecht
  • Temple Fork Outfitters
  • Burr (romanzo)
  • Trek Madone SLR 9 Disc

Archivi

  • Febbraio 2022
  • Gennaio 2022
  • Dicembre 2021
  • Novembre 2021
  • Ottobre 2021
  • Settembre 2021
  • Agosto 2021
  • Luglio 2021
  • Giugno 2021
  • Maggio 2021
  • Aprile 2021
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語
©2022 CDhistory | Powered by WordPress & Superb Themes