Skip to content
Menu
CDhistory
CDhistory

Kommes i gang

Posted on august 17, 2021 by admin
  • Opdatér din Gemfile
  • Konfigurer din testsuite
  • Test::Unit
  • Cucumber
  • Spinach
  • Minitest
  • Minitest::Spec
  • minitest-rails
  • Definering af fabrikker
  • Brug af factories
  • Dynamiske attributter
  • Aliases
  • Afhængige attributter
  • Transient Attributes
  • Metodenavn/reserverede ord-attributter
  • Arv
  • Associationer
  • Sekvenser
  • Traits
  • Callbacks
  • Modificering af fabrikker
  • Bygning eller oprettelse af flere poster
  • Linting Factories
  • Brugerdefineret konstruktion
  • Brugerdefinerede strategier
  • Brugerdefinerede callbacks
  • Brugerdefinerede metoder til at persistere objekter
  • ActiveSupport Instrumentation
  • Rails Preloaders og RSpec
  • Kørsel uden Bundler

Opdatér din Gemfile

Hvis du bruger Rails, skal du ændre den krævede version af factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Hvis du ikke bruger Rails, skal du blot ændre den krævede version af factory_girl:

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

Når din Gemfile er opdateret, skal du opdatere din bundle.

Konfigurer din testsuite

Husk at kræve ovenstående fil i din rails_helper, da supportmappen ikke indlæses ivrigt

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

Hvis du ikke inkluderer FactoryGirl::Syntax::Methods i din testsuite, skal alle factory_girl-metoder indledes med FactoryGirl.

Definering af fabrikker

Hver fabrik har et navn og et sæt attributter. Navnet bruges som standard til at gætte objektets klasse, men det er muligt at angive det eksplicit:

Det anbefales stærkt, at du har en fabrik for hver klasse, som giver det enkleste sæt attributter, der er nødvendige for at oprette en instans af den pågældende klasse. Hvis du opretter ActiveRecord-objekter, betyder det, at du kun bør levere attributter, der er påkrævet gennem valideringer, og som ikke har standardindstillinger. Der kan oprettes andre fabrikker gennem arv for at dække almindelige scenarier for hver klasse.

Vil du forsøge at definere flere fabrikker med det samme navn, opstår der en fejl.

Factories kan defineres hvor som helst, men vil automatisk blive indlæst efter at have kaldt FactoryGirl.find_definitions, hvis factories er defineret i filer på følgende steder:

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

Brug af factories

factory_girl understøtter flere forskellige opbygningsstrategier: build, create, attributes_for og build_stubbed:

Uanset hvilken strategi der anvendes, er det muligt at tilsidesætte de definerede attributter ved at overgive en hash:

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

Dynamiske attributter

De fleste fabriksattributter kan tilføjes ved hjælp af statiske værdier, der evalueres, når fabrikken defineres, men nogle attributter (såsom associationer og andreattributter, der skal genereres dynamisk) skal have tildelt værdier, hver gang en instans genereres. Disse “dynamiske” attributter kan tilføjes ved at overgive en blok i stedet for en parameter:

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

På grund af bloksyntaksen i Ruby kræver det to sæt krøllede parenteser at definere attributter som Hashes (forserialized/JSON-kolonner, for eksempel):

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

Aliases

factory_girl giver dig mulighed for at definere aliaser til eksisterende fabrikker for at gøre det lettere at genbruge dem. Dette kan være praktisk, når f.eks. dit Post-objekt har en author-attribut, der faktisk henviser til en instans af en User-klasse. Mens factory_girl normalt kan udlede fabriksnavnet fra associationsnavnet, vil den i dette tilfælde lede forgæves efter en author factory. Så alias din brugerfabrik, så den kan bruges under aliasnavne.

Afhængige attributter

Attributter kan baseres på værdierne af andre attributter ved hjælp af evaluatordet, der afgives til dynamiske attributblokke:

Transient Attributes

Der kan være tidspunkter, hvor din kode kan DRYed up ved at videregive transiente attributter til factories.

Statiske og dynamiske attributter kan oprettes som transiente attributter. Transientattributter vil blive ignoreret inden for attributes_for og vil ikke blive sat på modellen, selv om attributten eksisterer, eller du forsøger at tilsidesætte den.

Inden for factory_girls dynamiske attributter kan du få adgang til transientattributter, som du ville forvente. Hvis du skal have adgang til evaluatoren i et factory_girl callback, skal du erklære et andet blokargument (for evaluatoren) og få adgang til transiente attributter derfra.

Metodenavn/reserverede ord-attributter

Hvis dine attributter er i konflikt med eksisterende metoder eller reserverede ord, kan du definere dem med add_attribute.

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

Arv

Du kan nemt oprette flere fabrikker for den samme klasse uden at gentage fælles attributter ved at indlejre fabrikker:

Du kan også tildele den overordnede eksplicit:

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

Som nævnt ovenfor er det god praksis at definere en grundlæggende fabrik for hver klasse med kun de attributter, der er nødvendige for at oprette den. Derefter skal du oprette mere specifikke fabrikker, der arver fra denne grundlæggende forælder. Fabriksdefinitioner er stadig kode, så hold dem DRY.

Associationer

Det er muligt at opstille associationer inden for fabrikker. Hvis fabriksnavnet er det samme som associationsnavnet, kan fabriksnavnet udelades.

factory :post do # ... authorend

Du kan også angive en anden fabrik eller overskrive attributter:

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

Adfærden af associationsmetoden varierer afhængigt af den opbygningsstrategi, der anvendes for det overordnede objekt.

For ikke at gemme det tilknyttede objekt skal du angive strategi: :build i fabrikken:

Bemærk, at strategy: :build-indstillingen skal overgives til et eksplicit kald til association,og kan ikke bruges med implicitte associationer:

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

Generering af data til en has_many-relation er lidt mere indviklet,afhængigt af den ønskede fleksibilitet, men her er et sikkert eksempel på generering af tilknyttede data.

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

Dette giver os mulighed for at gøre:

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

Generering af data til et has_and_belongs_to_many-forhold er meget lig ovenstående has_many-forhold, med en lille ændring, du skal videregive et array af objekter til modellens pluraliserede attributnavn i stedet for et enkeltobjekt til den singulære version af attributnavnet.

Her er et eksempel med to modeller, der er relateret viahas_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

Det giver os mulighed for at gøre:

Sekvenser

Unique værdier i et bestemt format (f.eks. e-mail-adresser) kan genereres ved hjælp af sekvenser. Sekvenser defineres ved at kalde sequence i en definitionsblok, og værdier i en sekvens genereres ved at kaldegenerate:

Sekvenser kan bruges i dynamiske attributter:

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

Og som implicitte attributter:

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

Og det er også muligt at definere en in-line-sekvens, der kun bruges i en bestemt fabrik:

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

Du kan også tilsidesætte den oprindelige værdi:

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

Og uden en blok vil værdien øge sig selv, startende ved sin oprindelige værdi:

factory :post do sequence(:position)end

Sekvenser kan også have aliaser. Sekvensaliaserne deler den samme tæller:

Definér aliaser og brug standardværdien (1) for tælleren

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

Sæt værdien:

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

Værdien skal blot understøtte metoden #next. Her vil den næste værdi være ‘a’, derefter ‘b’ osv.

Traits

Traits giver dig mulighed for at gruppere attributter sammen og derefter anvende dem på enhver fabrik.

Traits kan bruges som attributter:

Traits, der definerer de samme attributter, vil ikke give anledning til AttributeDefinitionErrors;det trait, der senest definerer attributten, får forrang.

Du kan også tilsidesætte individuelle attributter, der er tildelt af et træk, i underklasser.

Traits kan også overføres som en liste af symboler, når du konstruerer en instans fra factory_girl.

Denne evne fungerer med build, build_stubbed, attributes_for og create.

>create_list og build_list-metoder understøttes også. Du skal blot huske at passe antallet af instanser, der skal oprettes/opbygges som anden parameter, som dokumenteret i afsnittet “Opbygning eller oprettelse af flere poster” i denne fil.

Traits kan også nemt bruges med associationer:

Når du bruger associationsnavne, der er forskellige fra fabrikkens:

Traits kan bruges inden for andre traits for at blande deres attributter.

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

Endeligt kan traits acceptere transiente attributter.

Callbacks

factory_girl stiller fire callbacks til rådighed til at injicere noget kode:

Eksempler:

Bemærk, at du har en instans af brugeren i blokken. Dette kan være nyttigt.

Du kan også definere flere typer callbacks på den samme factory:

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

Factories kan også definere et vilkårligt antal af den samme type callback. Disse callbacks vil blive udført i den rækkefølge, de er angivet:

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

Kaldes create vil både after_build og after_create callbacks blive påkaldt.

Som standardattributter vil underordnede fabrikker også arve (og kan også definere) callbacks fra deres overordnede fabrik.

Flere callbacks kan tildeles til at køre en blok; dette er nyttigt, når man opbygger forskellige strategier, der kører den samme kode (da der ikke er nogen callbacks, der deles på tværs af alle strategier).

For at tilsidesætte callbacks for alle fabrikker skal du definere dem inden for blokkenFactoryGirl.define:

Du kan også foretage callbacks, der er afhængige af Symbol#to_proc:

Modificering af fabrikker

Hvis du får et sæt fabrikker (f.eks. fra en gem-udvikler), men ønsker at ændre dem, så de passer bedre ind i dit program, kan du modificere den pågældende fabrik i stedet for at oprette en underordnet fabrik og tilføje attributter der.

Hvis en gem giver dig en brugerfabrik:

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

I stedet for at oprette en child factory, der tilføjer yderligere attributter:

kan du ændre denne fabrik i stedet.

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

Når du ændrer en fabrik, kan du ændre alle de attributter, du ønsker (bortset fra callbacks).

FactoryGirl.modify skal kaldes uden for en FactoryGirl.define blok, da den opererer anderledes på factories.

En advarsel: Du kan kun ændre factories (ikke sekvenser eller traits), og callbacks sammensættes stadig som de normalt ville gøre. Så hvis den fabrik, du ændrer, definerer en after(:create) callback, vil du, hvis du definerer en after(:create), ikke tilsidesætte den, den vil bare blive kørt efter den første callback.

Bygning eller oprettelse af flere poster

I nogle tilfælde vil du oprette eller bygge flere instanser af en fabrik på én gang.

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

Disse metoder opbygger eller opretter et bestemt antal fabrikker og returnerer dem som et array. for at indstille attributterne for hver af fabrikkerne kan du sende en hash, som du normalt ville gøre.

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

build_stubbed_list giver dig fuldt ud stubbed out-instanser:

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

Der er også et sæt *_pair-metoder til at oprette to poster ad gangen:

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

Hvis du har brug for flere attribut-hashes, genererer attributes_for_list dem:

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

Linting Factories

factory_girl giver mulighed for linting af kendte fabrikker:

FactoryGirl.lint

FactoryGirl.lint opretter hver fabrik og fanger eventuelle undtagelser, der opstår under oprettelsesprocessen. FactoryGirl::InvalidFactoryError bliver rejst med en liste over fabrikker (og tilsvarende undtagelser) for fabrikker, som ikke kunne oprettes.

Anbefalet brug af FactoryGirl.lint er at køre dette i en opgave, før din testsuite udføres.Hvis du kører den i en before(:suite), vil det have en negativ indvirkning på dine testers ydeevne, når du kører enkelte tests.

Eksempel på Rake-opgave:

Når du kalder FactoryGirl.lint, vil du sandsynligvis ønske at tømme databasen, da der højst sandsynligt vil blive oprettet poster. Ovenstående eksempel bruger database_cleaner-gem’en til at rydde databasen; sørg for at tilføje gem’en til din Gemfile under de relevante grupper.

Du kan lintes fabrikker selektivt ved kun at videregive fabrikker, du vil have lintet:

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

Dette vil lintes alle fabrikker, der ikke er præfikseret med old_.

Traits kan også lintes. Denne indstilling verificerer, at hver enkelt egenskab i en fabrik genererer et gyldigt objekt i sig selv.Dette slås til ved at overgive traits: true til lint-metoden:

FactoryGirl.lint traits: true

Dette kan også kombineres med andre argumenter:

FactoryGirl.lint factories_to_lint, traits: true

Du kan også angive den strategi, der anvendes til linting:

FactoryGirl.lint strategy: :build

Brugerdefineret konstruktion

Hvis du ønsker at bruge factory_girl til at konstruere et objekt, hvor nogle attributter er overgivet til initialize, eller hvis du ønsker at gøre noget andet end blot at kalde new på din byggeklasse, kan du tilsidesætte standardadfærden ved at definere initialize_with på din factory. Eksempel:

Selv om factory_girl er skrevet til at fungere med ActiveRecord out of the box, kan den også fungere med enhver Ruby-klasse. For at opnå maksimal kompatibilitet med ActiveRecord opbygger standardinitialisatoren alle instanser ved at kalde new på din byggeklasse uden nogen argumenter. Den kalder derefter attributskrivermetoder for at tildele alle attributværdierne. Mens det fungerer fint for ActiveRecord, fungerer det faktisk ikke for næsten alle andre Ruby-klasser.

Du kan overskrive initialisatoren for at:

  • Byg ikke-ActiveRecord-objekter, der kræver argumenter til initialize
  • Brug en anden metode end new til at instantiere instansen
  • Gør skøre ting som at dekorere instansen, efter at den er bygget

Når du bruger initialize_with, behøver du ikke at deklarere selve klassen, når du kalder new; skal alle andre klassemetoder, du vil kalde, dog kaldes eksplicit på klassen.

For eksempel:

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

Du kan også få adgang til alle offentlige attributter inden for initialize_with-blokken ved at kalde attributes:

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

Dette vil opbygge en hash af alle attributter, der skal overføres til new. Det vil ikke omfatte transiente attributter, men alt andet, der er defineret i fabrikken, vil blive videregivet (associationer, evaluerede sekvenser osv.).)

Du kan definere initialize_with for alle fabrikker ved at inkludere det i blokkenFactoryGirl.define:

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

Når du bruger initialize_with, tildeles attributter, der tilgås fra initialize_withblokken, kun i konstruktøren; det svarer til nogenlunde følgende kode:

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

Dette forhindrer dobbelttildeling; i versioner af factory_girl før 4.0, ville den køre således:

Brugerdefinerede strategier

Der er tidspunkter, hvor du måske ønsker at udvide opførslen af factory_girl ved at tilføje en brugerdefineret opbygningsstrategi.

Strategier definerer to metoder: association og result. associationmodtager en FactoryGirl::FactoryRunner-instans, som du kan kalderun og overstyre strategien, hvis du ønsker det. Den anden metode, result,modtager en FactoryGirl::Evaluation-instans. Den giver mulighed for at udløsecallbacks (med notify), object eller hash (for at få resultatinstansen eller ahash baseret på de attributter, der er defineret i fabrikken) og create, som udfører to_create callback defineret på fabrikken.

For at forstå, hvordan factory_girl bruger strategier internt, er det nok lettest blot at se kilden for hver af de fire standardstrategier.

Her er et eksempel på sammensætning af en strategi ved hjælp afFactoryGirl::Strategy::Create for at opbygge en JSON-repræsentation af din model.

For at factory_girl kan genkende den nye strategi, kan du registrere den:

FactoryGirl.register_strategy(:json, JsonStrategy)

Dette giver dig mulighed for at kalde

FactoryGirl.json(:user)

Endeligt kan du tilsidesætte factory_girls egne strategier, hvis du ønsker det, ved at registrere et nyt objekt i stedet for strategierne.

Brugerdefinerede callbacks

Der kan defineres brugerdefinerede callbacks, hvis du bruger bruger brugerdefinerede strategier:

Brugerdefinerede metoder til at persistere objekter

Som standard kalder oprettelsen af en post save! på instansen.Da dette måske ikke altid er ideelt, kan du tilsidesætte denne adfærd ved at definereto_create på fabrikken:

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

For at deaktivere persistensmetoden helt og holdent på create kan du skip_createfor den pågældende fabrik:

factory :user_without_database do skip_createend

For at tilsidesætteto_createfor alle fabrikker skal du definere det i blokkenFactoryGirl.define:

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

ActiveSupport Instrumentation

For at spore, hvilke fabrikker der oprettes (og med hvilken opbygningsstrategi), er ActiveSupport::Notifications medtaget for at give en måde at abonnere på fabrikker, der køres. Et eksempel kunne være at spore fabrikker baseret på en tærskel for udførelsestid.

Et andet eksempel kunne være at spore alle fabrikker, og hvordan de bruges i hele testsuiten. Hvis du bruger RSpec, er det så enkelt som at tilføje enbefore(:suite)ogafter(:suite):

Rails Preloaders og RSpec

Når du kører RSpec med en Rails Preloader som spring eller zeus, er det muligtat støde på en ActiveRecord::AssociationTypeMismatch fejl, når du opretter en fabrik med associationer, som nedenfor:

Fejlen opstår under kørslen af testsuiten:

De to mulige løsninger er enten at køre suiten uden preloader ellerat tilføje FactoryGirl.reload til RSpec-konfigurationen, som her:

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

Kørsel uden Bundler

Hvis du ikke bruger Bundler, skal du sørge for at have perlen installeret og kalde:

require 'factory_girl'

Når det er påkrævet, forudsat at du har en mappestruktur på spec/factories ellertest/factories, skal du blot køre

FactoryGirl.find_definitions

Hvis du bruger en separat mappestruktur til dine fabrikker, kan du ændre stierne til definitionsfilerne, før du forsøger at finde definitioner:

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

Hvis du ikke har en separat mappe med fabrikker og gerne vil definere dem inline, så er det også muligt:

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

Skriv et svar Annuller svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *

Seneste indlæg

  • Acela er tilbage:
  • OMIM Entry – # 608363 – CHROMOSOM 22q11.2 DUPLIKATIONSSYNDROM
  • Kate Albrechts forældre – Få mere at vide om hendes far Chris Albrecht og mor Annie Albrecht
  • Temple Fork Outfitters
  • Burr (roman)

Arkiver

  • februar 2022
  • januar 2022
  • december 2021
  • november 2021
  • oktober 2021
  • september 2021
  • august 2021
  • juli 2021
  • juni 2021
  • maj 2021
  • april 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