Skip to content
Menu
CDhistory
CDhistory

Začínáme

Posted on 17 srpna, 2021 by admin
  • Aktualizujte svůj soubor Gemfile
  • Konfigurujte sadu testů
  • Test::Unit
  • Cucumber
  • Spinach
  • Minitest
  • Minitest::Spec
  • minitest-rails
  • Definice továren
  • Použití faktorů
  • Dynamické atributy
  • Aliasy
  • Závislé atributy
  • Přechodné atributy
  • Atributy názvů metod / rezervovaných slov
  • Dědičnost
  • Asociace
  • Sekvence
  • Traity
  • Zpětná volání
  • Modifikace továren
  • Vytváření nebo vytváření více záznamů
  • Lintování továren
  • Vlastní konstrukce
  • Vlastní strategie
  • Vlastní zpětná volání
  • Vlastní metody pro perzistenci objektů
  • ActiveSupport Instrumentation
  • Rails Preloadery a RSpec
  • Používání bez Bundleru

Aktualizujte svůj soubor Gemfile

Pokud používáte Rails, budete muset změnit požadovanou verzi factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Pokud nepoužíváte Rails, stačí změnit požadovanou verzi factory_girl:

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

Po aktualizaci souboru Gemfile budete chtít aktualizovat svůj balíček.

Konfigurujte sadu testů

Nezapomeňte ve svém rails_helperu vyžadovat výše uvedený soubor, protože složka support se nenačítá eagerly

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

Pokud do testovací sady nezahrnete FactoryGirl::Syntax::Methods, pak všechny metody factory_girl budou muset být uvozeny FactoryGirl.

Definice továren

Každá továrna má název a sadu atributů. Podle názvu se ve výchozím nastavení odhaduje třída objektu, ale je možné jej explicitně zadat:

Důrazně se doporučuje, abyste pro každou třídu měli jednu továrnu, která poskytuje nejjednodušší sadu atributů potřebných k vytvoření instance dané třídy. Pokud vytváříte objekty ActiveRecord, znamená to, že byste měli poskytovat pouze atributy, které jsou vyžadovány prostřednictvím validace a které nemají výchozí hodnoty. Další továrny mohou být vytvořeny prostřednictvím dědičnosti, aby pokryly běžné scénáře pro každou třídu.

Pokus o definování více továren se stejným názvem vyvolá chybu.

Faktory lze definovat kdekoli, ale budou automaticky načteny po vyvolání FactoryGirl.find_definitions, pokud jsou faktory definovány v souborech na těchto místech:

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

Použití faktorů

factory_girl podporuje několik různých strategií sestavování: build, create, attributes_for a build_stubbed:

Nezáleží na tom, která strategie je použita, je možné nadefinované atributy přepsat předáním hashe:

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

Dynamické atributy

Většinu atributů továrny lze přidat pomocí statických hodnot, které jsou vyhodnoceny při definování továrny, ale některé atributy (například asociace a další atributy, které musí být dynamicky generovány) budou potřebovat hodnoty přiřazené při každém generování instance. Tyto „dynamické“ atributy lze přidat předáním bloku místo parametru:

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

Vzhledem k blokové syntaxi v jazyce Ruby vyžaduje definování atributů jako Hashes (například proserializované sloupce/JSON) dvě sady kudrlinkových závorek:

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

Aliasy

factory_girl umožňuje definovat aliasy k existujícím továrnám, aby bylo snazší je znovu použít. To se může hodit, když například váš objekt Post má atribut author, který ve skutečnosti odkazuje na instanci třídy User. Zatímco normálně factory_girl dokáže odvodit název továrny z názvu asociace, v tomto případě bude marně hledat továrnu author. Použijte tedy alias své továrny user, aby ji bylo možné použít pod aliasovými jmény.

Závislé atributy

Atributy mohou být založeny na hodnotách jiných atributů pomocí vyhodnocovacího nástroje, který je předáván dynamickým blokům atributů:

Přechodné atributy

Může se stát, že váš kód bude DRYed tím, že továrnám předáte přechodné atributy.

Statické a dynamické atributy lze vytvořit jako přechodné atributy. Přechodnéatributy budou v rámci atributu_for ignorovány a nebudou nastaveny v modelu,i když atribut existuje nebo se ho pokusíte přepsat.

V rámci dynamických atributů factory_girl můžete přistupovat k přechodným atributům, jak byste očekávali. Pokud potřebujete přistupovat k vyhodnocovači ve zpětném volání factory_girl,budete muset deklarovat druhý argument bloku (pro vyhodnocovač) a přistupovat k přechodným atributům z něj.

Atributy názvů metod / rezervovaných slov

Pokud vaše atributy kolidují s existujícími metodami nebo rezervovanými slovy, můžete je definovat pomocí add_attribute.

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

Dědičnost

Snadno můžete vytvořit více továren pro stejnou třídu bez opakování společných atributů vnořením továren:

Můžete také explicitně přiřadit rodiče:

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

Jak bylo uvedeno výše, je dobrým zvykem definovat základní továrnu pro každou třídu pouze s atributy potřebnými k jejímu vytvoření. Poté vytvořte specifičtějšítovárny, které dědí z tohoto základního rodiče. Definice továren jsou stále kódem, takže je udržujte DRY.

Asociace

V rámci továren je možné nastavit asociace. Pokud je název továrny stejný jako název asociace, lze název továrny vynechat.

factory :post do # ... authorend

Můžete také určit jinou továrnu nebo přepsat atributy:

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

Chování metody asociace se liší v závislosti na použité strategii sestavení rodičovského objektu.

Chcete-li asociovaný objekt neukládat, zadejte v továrně strategii: :build:

Upozorňujeme, že volba strategy: :build musí být předána explicitnímu volání association,a nelze ji použít s implicitními asociacemi:

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

Generování dat pro vztah has_many je trochu složitější,v závislosti na požadované míře flexibility, ale zde je jistý příklad generování asociovaných dat.

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

Tímto způsobem můžeme udělat:

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

Generování dat pro vztah has_and_belongs_to_many je velmi podobné výše uvedenému vztahu has_many, s malou změnou, je třeba předat pole objektů k plurálovému názvu atributu modelu místo jednoho objektu k singulární verzi názvu atributu.

Tady je příklad se dvěma modely, které jsou propojeny prostřednictvímhas_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

To nám umožňuje:

Sekvence

Jednotlivé hodnoty ve specifickém formátu (například e-mailové adresy) lze vytvářet pomocí sekvencí. Sekvence se definují voláním sequence v adefiničním bloku a hodnoty v sekvenci se generují volánímgenerate:

Sekvence lze použít v dynamických atributech:

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

Nebo jako implicitní atributy:

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

A také je možné definovat řádkovou sekvenci, která se používá pouze v určité továrně:

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

Můžete také přepsat počáteční hodnotu:

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

Bez bloku se hodnota inkrementuje sama, počínaje počáteční hodnotou:

factory :post do sequence(:position)end

Sekvence mohou mít také aliasy. Aliasy sekvencí sdílejí stejný čítač:

Definice aliasu a použití výchozí hodnoty (1) pro čítač

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

Nastavení hodnoty:

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

Hodnota musí pouze podporovat metodu #next. Zde bude další hodnota ‚a‘, pak ‚b‘ atd.

Traity

Traity umožňují seskupit atributy dohromady a pak je použítna libovolnou továrnu.

Traity lze použít jako atributy:

Traity, které definují stejné atributy, nebudou vyvolávat chyby AttributeDefinitionErrors;přednost má trait, který definuje atribut nejpozději.

V podtřídách můžete také přepsat jednotlivé atributy udělené rysem.

Traity lze také předat jako seznam symbolů při konstrukci instance z factory_girl.

Tato schopnost funguje s build, build_stubbed, attributes_for a create.

create_list a build_list Podporovány jsou také metody. Jen nezapomeňte jako druhý parametr předat počet instancí, které chcete vytvořit/vytvořit, jak je zdokumentováno v části „Vytvoření nebo vytvoření více záznamů“ tohoto souboru.

Traity lze snadno použít i s asociacemi:

Pokud používáte názvy asociací, které se liší od továrních:

Traity lze použít v rámci jiných traitů a míchat jejich atributy.

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

Nakonec mohou traity přijímat přechodné atributy.

Zpětná volání

továrna_girl zpřístupňuje čtyři zpětná volání pro injektování nějakého kódu:

Příklad:

Všimněte si, že v bloku budete mít instanci uživatele. To může být užitečné.

Ve stejné továrně můžete také definovat více druhů zpětných volání:

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

Továrny mohou také definovat libovolný počet stejných druhů zpětných volání. Tato zpětná volání budou provedena v pořadí, v jakém jsou zadána:

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

Volání create vyvolá jak after_build, tak after_create zpětné volání.

Stejně jako standardní atributy i podřízené továrny dědí (a mohou také definovat) zpětná volání od své rodičovské továrny.

Pro spuštění bloku lze přiřadit více zpětných volání; to je užitečné při vytváření různých strategií, které spouštějí stejný kód (protože neexistují zpětná volání, která by byla společná pro všechny strategie).

Chcete-li přepsat zpětná volání pro všechny továrny, definujte je v rámci blokuFactoryGirl.define:

Můžete také volat zpětná volání, která se spoléhají na Symbol#to_proc:

Modifikace továren

Pokud dostanete sadu továren (například od vývojáře drahokamů), ale chcete je změnit tak, aby lépe vyhovovaly vaší aplikaci, můžete tuto továrnu modifikovat, místo abyste vytvořili podřízenou továrnu a přidali do ní atributy.

Pokud by vám vývojář drahokamu dal továrnu User:

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

Místo vytvoření podřízené továrny, která by přidala další atributy:

Můžete místo toho tuto továrnu upravit.

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

Při úpravě továrny můžete změnit libovolné atributy (kromě zpětných volání).

FactoryGirl.modify musí být volán mimo blok FactoryGirl.define, protože pracuje s továrnami jinak.

Upozornění: můžete měnit pouze továrny (nikoli sekvence nebo rysy) a zpětná volání se stále skládají jako obvykle. Pokud tedy továrna, kterou upravujete, definuje zpětné volání after(:create), definování after(:create) ji nepřepíše, pouze se spustí po prvním zpětném volání.

Vytváření nebo vytváření více záznamů

Někdy budete chtít vytvořit nebo sestavit více instancí továrny najednou.

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

Tyto metody sestaví nebo vytvoří určitý počet továren a vrátí je jako pole. pro nastavení atributů každé z továren můžete předat hash jako obvykle.

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

build_stubbed_list vám poskytne plně odříznuté instance:

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

K dispozici je také sada metod *_pair pro vytvoření dvou záznamů najednou:

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

Pokud potřebujete více hashů atributů, attributes_for_list je vygeneruje:

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

Lintování továren

factory_girl umožňuje lintování známých továren:

FactoryGirl.lint

FactoryGirl.lint vytvoří každou továrnu a zachytí všechny výjimky vyvolanéběhem procesu vytváření. FactoryGirl::InvalidFactoryError je vyvolán seznam továren (a odpovídajících výjimek) pro továrny, které nemohly být vytvořeny.

Doporučené použití FactoryGirl.lintje spustit tuto funkci v úlozepřed spuštěním testovací sady.Spuštění v before(:suite),bude mít negativní vliv na výkon vašich testůpři spouštění jednotlivých testů.

Příklad úlohy Rake:

Po zavolání FactoryGirl.lint budete pravděpodobně chtít vymazatdatabázi, protože se pravděpodobně vytvoří záznamy. Výše uvedený příklad používá k vymazání databáze gem database_cleaner; nezapomeňte tento gem přidat do svého souboru gemů pod příslušné skupiny.

Faktory můžete lintovat selektivně tak, že předáte pouze ty, které chcete lintovat:

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

Tímto způsobem byste lintovali všechny faktory, které nemají předponu old_.

Lintovat lze také vlastnosti. Tato volba ověřuje, zda každáa každá vlastnost továrny generuje platný objekt sama o sobě.Zapíná se předáním traits: true metodě lint:

FactoryGirl.lint traits: true

Tuto funkci lze také kombinovat s dalšími argumenty:

FactoryGirl.lint factories_to_lint, traits: true

Můžete také určit strategii použitou pro lintování:

FactoryGirl.lint strategy: :build

Vlastní konstrukce

Pokud chcete použít factory_girl pro konstrukci objektu, kde jsou některé atributypředávány initialize, nebo pokud chcete udělat něco jiného než prosté volání new na vaší konstrukční třídě, můžete přepsat výchozí chování definováním initialize_with na vaší továrně. Příklad:

Ačkoli je factory_girl napsána pro práci s ActiveRecord out of box, může také pracovat s jakoukoli třídou Ruby. Pro maximální kompatibilitu s ActiveRecord,výchozí inicializátor sestaví všechny instance voláním new na vaší třídě factorybez jakýchkoli argumentů. Poté zavolá metody atributového zapisovatele, aby přiřadil všechny hodnoty atributů. Zatímco pro ActiveRecord to funguje dobře, pro téměř jakoukoli jinou třídu Ruby to ve skutečnosti nefunguje.

Inicializátor můžete přepsat, aby:

  • Vytvořit objekty jiné než ActiveRecord, které vyžadují argumenty initialize
  • Použít jinou metodu než new k instanciaci instance
  • Dělat šílené věci, jako je zdobení instance po jejím vytvoření

Při použití initialize_with nemusíte při volání new deklarovat samotnou třídu; nicméně všechny ostatní metody třídy, které chcete volat, budou muset být volány explicitně na třídě.

Například:

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

V rámci bloku initialize_with můžete také přistupovat ke všem veřejným atributům voláním attributes:

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

Tím se vytvoří hash všech atributů, který se předá do new. Nebude zahrnovat přechodné atributy, ale vše ostatní definované v továrně bude předáno (asociace, vyhodnocené sekvence atd.)

Můžete definovat initialize_with pro všechny továrny tak, že jej zahrnete do blokuFactoryGirl.define:

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

Při použití initialize_with se atributy, k nimž se přistupuje z bloku initialize_with, přiřazují pouze v konstruktoru; to odpovídá zhruba následujícímu kódu:

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

Tím se zabrání duplicitnímu přiřazení; ve verzích factory_girl před 4. verzí se atributy přiřazují pouze v konstruktoru.0 by to probíhalo takto:

Vlastní strategie

V některých případech můžete chtít rozšířit chování factory_girl přidáním vlastní strategie sestavení.

Strategie definují dvě metody: association a result. associationpřijímá instanci FactoryGirl::FactoryRunner, na kterou můžete zavolat run a případně strategii přepsat. Druhá metoda, result,přijímá instanci FactoryGirl::Evaluation. Poskytuje způsob, jak spustit zpětné volání (pomocí notify), object nebo hash (pro získání výsledné instance nebo ahash na základě atributů definovaných v factory) a create, kterývykoná zpětné volání to_create definované na factory.

Chcete-li pochopit, jak factory_girl interně používá strategie, je asi nejjednodušší prostě si prohlédnout zdrojový kód každé ze čtyř výchozích strategií.

Tady je příklad sestavení strategie pomocíFactoryGirl::Strategy::Create pro vytvoření reprezentace JSON modelu.

Aby factory_girl rozpoznala novou strategii, můžete ji zaregistrovat:

FactoryGirl.register_strategy(:json, JsonStrategy)

To vám umožní volat

FactoryGirl.json(:user)

Nakonec můžete přepsat vlastní strategie factory_girl, pokud chcete, zaregistrováním nového objektu místo strategií.

Vlastní zpětná volání

Vlastní zpětná volání můžete definovat, pokud používáte vlastní strategie:

Vlastní metody pro perzistenci objektů

Ve výchozím nastavení se při vytváření záznamu zavolá save! na instanci; protože to nemusí být vždy ideální, můžete toto chování přepsat definicíto_create na továrně:

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

Chcete-li metodu perzistence při vytváření úplně zakázat, můžete skip_createpro tuto továrnu:

factory :user_without_database do skip_createend

Chcete-li přepsat to_create pro všechny továrny, definujte ji v blokuFactoryGirl.define:

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

ActiveSupport Instrumentation

Aby bylo možné sledovat, jaké továrny jsou vytvářeny (a s jakou strategií sestavení),ActiveSupport::Notifications jsou zahrnuty, aby poskytovaly způsob, jak se přihlásit ke spuštění továren. Jedním z příkladů by bylo sledování faktorů na základě prahové hodnoty času provedení.

Dalším příkladem by bylo sledování všech faktorů a jejich použití v celé sadě testů. Pokud používáte RSpec, je to stejně jednoduché jako přidání before(:suite) a after(:suite):

Rails Preloadery a RSpec

Při spuštění RSpec s Rails preloaderem, jako je spring nebo zeus, je možnépři vytváření faktoru s asociacemi narazit na chybu ActiveRecord::AssociationTypeMismatch, jak je uvedeno níže:

K chybě dojde během běhu sady testů:

Dvě možná řešení jsou buď spustit sadu bez předzavaděče, nebo přidat FactoryGirl.reload do konfigurace RSpec, například takto:

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

Používání bez Bundleru

Pokud Bundler nepoužíváte, ujistěte se, že máte gem nainstalovaný a zavoláte:

require 'factory_girl'

Pokud je vyžadován, za předpokladu, že máte adresářovou strukturu spec/factories nebotest/factories, stačí spustit

FactoryGirl.find_definitions

Pokud pro své továrny používáte samostatnou adresářovou strukturu, můžete před pokusem o nalezení definic změnit cesty k souborům s definicemi:

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

Pokud nemáte samostatný adresář s továrnami a chcete je definovat inline, je to také možné:

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

.

Napsat komentář Zrušit odpověď na komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *

Nejnovější příspěvky

  • Acela je zpět:
  • OMIM záznam – # 608363 – CHROMOSOM 22q11.2 DUPLICATION SYNDROME
  • Rodiče Kate Albrechtové – více o jejím otci Chrisu Albrechtovi a matce Annie Albrechtové
  • Temple Fork Outfitters
  • Burr (román)

Archivy

  • Únor 2022
  • Leden 2022
  • Prosinec 2021
  • Listopad 2021
  • Říjen 2021
  • Září 2021
  • Srpen 2021
  • Červenec 2021
  • Červen 2021
  • Květen 2021
  • Duben 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