Skip to content
Menu
CDhistory
CDhistory

Próximo Início

Posted on Agosto 17, 2021 by admin
  • Atualize seu Gemfile
  • Configure seu pacote de testes
  • Test::Unidade
  • Pepino
  • Spinach
  • Minitest
  • Minitest::Spec
  • minitestrails
  • Definindo fábricas
  • Utilizar fábricas
  • Atributos Dinâmicos
  • Aliases
  • Dependent Attributes
  • Transient Attributes
  • Method Name / Reserved Word Attributes
  • Inheritance
  • Associações
  • Sequências
  • Traits
  • Vallbacks
  • Modificar fábricas
  • Building ou Creating Multiple Records
  • Linting Factories
  • Construção Personalizada
  • Estratégias Personalizadas
  • Custom Callbacks
  • Métodos Personalizados para Persistir Objetos
  • Instrumentação de Apoio Ativo
  • Rails Preloaders e RSpec
  • Using Without Bundler

Atualize seu Gemfile

Se você está usando Rails, você precisará alterar a versão requerida de factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Se você não está usando Rails, você terá que alterar a versão requerida de factory_girl:

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

A partir do momento em que seu Gemfile for atualizado, você vai querer atualizar seu pacote.

Configure seu pacote de testes

Recorde para requerer o arquivo acima no seu rails_helper, já que a pasta de suporte não é carregada avidamente

require 'support/factory_girl'

Test::Unidade

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

Pepino

# 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

minitestrails

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

Se não incluir FactoryGirl::Syntax::Methods na sua suite de testes, então todos os métodos de fábrica_girl terão de ser pré-configurados com FactoryGirl.

Definindo fábricas

Cada fábrica tem um nome e um conjunto de atributos. O nome é usado para adivinhar a classe do objeto por padrão, mas é possível especificá-la explicitamente:

É altamente recomendado que você tenha uma fábrica para cada classe que forneça o conjunto mais simples de atributos necessários para criar uma instância dessa classe. Se você estiver criando objetos ActiveRecord, isso significa que você só deve fornecer atributos que são requeridos através de validações e que não tenham padrões. Outras fábricas podem ser criadas através de herança para cobrir cenários comuns para cada classe.

A tentativa de definir várias fábricas com o mesmo nome irá levantar um erro.

Fábricas podem ser definidas em qualquer lugar, mas serão automaticamente carregadas após a chamada FactoryGirl.find_definitions se as fábricas forem definidas em arquivos nos seguintes locais:

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

Utilizar fábricas

factory_girl suporta várias estratégias de construção diferentes: build, create, attributes_for e build_stubbed:

Não importa qual estratégia é usada, é possível sobrepor os atributos definidos passando um hash:

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

Atributos Dinâmicos

A maioria dos atributos de fábrica podem ser adicionados usando valores estáticos que são avaliados quando a fábrica é definida, mas alguns atributos (como associações e outros atributos que devem ser gerados dinamicamente) precisarão de valores atribuídos cada vez que uma instância for gerada. Estes atributos “dinâmicos” podem ser adicionados passando um bloco em vez de um parâmetro:

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

Por causa da sintaxe do bloco em Ruby, definir atributos como Hashes (colunas forserializadas/JSON, por exemplo) requer dois conjuntos de colchetes:

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

Aliases

factory_girl permite definir aliases para fábricas existentes para torná-las mais fáceis de reutilizar. Isto pode ser útil quando, por exemplo, o seu objeto Post tem um atributo autor que na verdade se refere a uma instância de uma classe User. Enquanto normalmente a factory_girl pode inferir o nome da fábrica a partir do nome da associação, neste caso ela vai procurar em vão por uma fábrica de autor. Então, alias sua fábrica de usuário para que possa ser usado sob alias names.

Dependent Attributes

Attributes pode ser baseado nos valores de outros atributos usando o avaliador que é cedido a blocos dinâmicos de atributos:

Transient Attributes

É possível que haja momentos em que seu código possa ser SECADO passando em atributos transitórios para fábricas.

Atributos estáticos e dinâmicos podem ser criados como atributos transitórios. Atributos transientes serão ignorados dentro dos atributos_para e não serão definidos no modelo, mesmo que o atributo exista ou você tente substituí-lo.

Com os atributos dinâmicos da factory_girl, você pode acessar atributos transientes assimétricos que você esperaria. Se você precisar acessar o avaliador em uma callback factory_girl,você precisará declarar um segundo argumento de bloco (para o avaliador) e atributos transitórios de acesso de lá.

Method Name / Reserved Word Attributes

Se seus atributos conflitam com métodos existentes ou palavras reservadas você pode defini-los com add_attribute.

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

Inheritance

Pode facilmente criar várias fábricas para a mesma classe sem repetir atributos comuns ao aninhar fábricas:

Pode também atribuir explicitamente o pai:

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

Como mencionado acima, é boa prática definir uma fábrica básica para cada classe com apenas os atributos necessários para criá-la. Então, crie fábricas mais específicas que herdam desse pai básico. As definições de fábrica são códigos imóveis, portanto mantenha-as SECAS.

Associações

É possível criar associações dentro das fábricas. Se o nome da fábrica for o mesmo que o nome da associação, o nome da fábrica pode ser deixado de fora.

factory :post do # ... authorend

É possível também especificar uma fábrica diferente ou atributos de substituição:

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

O comportamento do método de associação varia de acordo com a estratégia de construção usada para o objeto pai.

Para não salvar o objeto associado, especifique strategy: :build in the factory:

Por favor note que a opção strategy: :build deve ser passada para uma chamada explícita para association,e não pode ser usada com associações implícitas:

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

Gerar dados para uma relação has_many é um pouco mais envolvido, dependendo da quantidade de flexibilidade desejada, mas aqui está um exemplo seguro de geração de dados associados.

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

Isso nos permite fazer:

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

Gerar dados para um relacionamento has_and_belongs_to_many é muito similar ao relacionamento has_many acima, com uma pequena mudança, você precisa passar uma análise dos objetos para o nome do atributo pluralizado do modelo ao invés de um único objeto para a versão singular do nome do atributo.

Aqui está um exemplo com dois modelos que estão relacionados 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

Isso nos permite fazer:

Sequências

Valores únicos em um formato específico (por exemplo, endereços de e-mail) podem ser gerados usando seqüências. Seqüências são definidas chamando sequence em bloco de adefinição, e valores em uma seqüência são gerados chamando generate:

Seqüências podem ser usadas em atributos dinâmicos:

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

Or como atributos implícitos:

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

E também é possível definir uma sequência em linha que só é usada numa determinada fábrica:

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

É possível também sobrepor o valor inicial:

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

Sem um bloco, o valor irá incrementar-se a si mesmo, começando pelo seu valor inicial:

factory :post do sequence(:position)end

As sequências também podem ter alias. Os aliases de seqüência compartilham o mesmo contador:

Definir aliases e usar o valor padrão (1) para o contador

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

Definir o valor:

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

O valor só precisa suportar o método #next. Aqui o próximo valor será ‘a’, depois ‘b’, etc.

Traits

Traits permitem agrupar atributos e depois aplicá-los a qualquer fábrica.

Traits podem ser usados como atributos:

Traits que definem os mesmos atributos não levantam AttributeDefinitionErrors; o traço que define o último atributo tem precedência.

Traits também podem ser passados como uma lista de símbolos quando você constrói uma instância a partir de factory_girl.

Esta habilidade funciona com build, build_stubbed, attributes_for, e create.

create_list e build_list métodos também são suportados. Basta lembrar de passar o número de instâncias para criar/construir como segundo parâmetro, como documentado na seção “Construindo ou criando múltiplos registros” deste arquivo.

Traits também podem ser usados com associações facilmente:

Quando você estiver usando nomes de associações que são diferentes da fábrica:

Traits podem ser usados com outros traços para misturar em seus atributos.

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

Finalmente, os traços podem aceitar atributos transitórios.

Vallbacks

factory_girl disponibiliza quatro callbacks para injetar algum código:

Exemplos:

Nota que você terá uma instância do usuário no bloco. Isto pode ser útil.

Você também pode definir vários tipos de callbacks na mesma fábrica:

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

Fábricas também podem definir qualquer número do mesmo tipo de callback. Estas chamadas de retorno serão executadas na ordem em que são especificadas:

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

Chamadas create invocarão ambas after_build e after_create chamadas de retorno.

Tanto, como atributos padrão, as fábricas de crianças herdarão (e também podem definir) as chamadas de retorno da sua fábrica mãe.

Vallbacks múltiplos podem ser atribuídos para executar um bloco; isto é útil na construção de várias estratégias que executam o mesmo código (já que não há callbacks que são compartilhados entre todas as estratégias).

Para sobrepor callbacks para todas as fábricas, defina-as dentro do bloco:FactoryGirl.define bloco:

Você também pode chamar callbacks que dependem de Symbol#to_proc:

Modificar fábricas

Se você receber um conjunto de fábricas (digamos, de um desenvolvedor de gemas) mas quiser alterá-las para se encaixar melhor na sua aplicação, você pode modificar essa fábrica ao invés de criar uma fábrica infantil e adicionar atributos lá.

Se uma gem lhe fosse dada uma fábrica do usuário:

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

Em vez de criar uma fábrica filha que adicionasse atributos adicionais:

Você poderia modificar essa fábrica em vez disso.

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

Ao modificar uma fábrica, você pode alterar qualquer um dos atributos que quiser (além de callbacks).

>FactoryGirl.modify deve ser chamado fora de um bloco FactoryGirl.define como opera em fábricas de forma diferente.

Uma advertência: você só pode modificar fábricas (não seqüências ou traços) e callbacks ainda compostos como eles normalmente fariam. Então, se a fábrica que você está modificando define um after(:create) callback, você definindo um after(:create) não irá substituí-lo, ele apenas será executado após o primeiro callback.

Building ou Creating Multiple Records

Sometimes, você vai querer criar ou construir múltiplas instâncias de uma fábrica ao mesmo tempo.

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

Estes métodos irão construir ou criar uma quantidade específica de fábricas e retorná-las como um array.Para definir os atributos para cada uma das fábricas, você pode passar em um hash como você normalmente faria.

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

build_stubbed_list lhe dará instâncias totalmente confusas:

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

Também há um conjunto de *_pair métodos para criar dois registros de cada vez:

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

Se você precisar de hashes de múltiplos atributos, attributes_for_list irá gerá-los:

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

Linting Factories

factory_girl permite a impressão de fábricas conhecidas:

FactoryGirl.lint

FactoryGirl.lint cria cada fábrica e captura quaisquer excepções levantadas durante o processo de criação. FactoryGirl::InvalidFactoryError é levantado com uma lista de fábricas (e correspondentes exceções) para fábricas que não puderam ser criadas.

uso recomendado de FactoryGirl.lint é para executar isto em uma tarefa antes da sua suíte de testes ser executada.Executando-a em um before(:suite), irá impactar negativamente a performance de seus testes quando executando testes únicos.

Example Rake task:

Após chamar FactoryGirl.lint, você provavelmente irá querer limpar a base de dados, já que os registros provavelmente serão criados. O exemplo fornecido acima usa a gem database_cleaner para limpar a base de dados; certifique-se de adicionar ogem ao seu Gemfile sob os grupos apropriados.

Você pode linchar fábricas seletivamente passando apenas fábricas que você quer linted:

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

Isso lincharia todas as fábricas que não são prefixadas com old_.

Traits também podem ser linted. Esta opção verifica que cada característica de uma fábrica gera um objeto válido por si só.Isto é ligado passando traits: true para o método lint:

FactoryGirl.lint traits: true

Isto também pode ser combinado com outros argumentos:

FactoryGirl.lint factories_to_lint, traits: true

Você também pode especificar a estratégia usada para a impressão:

FactoryGirl.lint strategy: :build

Construção Personalizada

Se você quiser usar factory_girl para construir um objeto onde alguns atributos são passados para initialize ou se você quiser fazer algo que não seja simples chamada new na sua classe de construção, você pode sobrescrever o comportamento padrão definindo initialize_with na sua fábrica. Exemplo:

Embora factory_girl seja escrito para trabalhar com o ActiveRecord fora da caixa, ele também pode trabalhar com qualquer classe Ruby. Para máxima compatibilidade com o ActiveRecord,o inicializador padrão constrói todas as instâncias chamando new na sua classe de compilação sem quaisquer argumentos. Ele então chama os métodos do attribute writer para atribuir todos os valores do atributo. Enquanto isso funciona bem para o ActiveRecord, na verdade não funciona para quase nenhuma outra classe Ruby.

Você pode sobrescrever o inicializador de modo a:

  • Build non-ActiveRecord objects that require arguments to initialize
  • Utilizar um método diferente de new para instanciar a instância
  • Fazer coisas loucas como decorar a instância depois de construída

Quando usar initialize_with, você não precisa declarar a própria classe quando chamar new; no entanto, quaisquer outros métodos de classe que você queira chamar terão de ser chamados explicitamente na classe.

Por exemplo:

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

Você também pode acessar todos os atributos públicos dentro da classe initialize_with chamando bloco a bloco attributes:

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

Isso irá construir um hash de todos os atributos a serem passados para new. Ele não incluirá atributos transitórios, mas tudo o resto definido na fábrica será bepassed (associações, sequências avaliadas, etc.).)

Pode definir initialize_with para todas as fábricas incluindo-o no blocoFactoryGirl.define:

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

Ao usar initialize_with, atributos acessados de dentro do bloco initialize_with são atribuídos somente no construtor; isto equivale aproximadamente ao seguinte código:

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

Previne a atribuição duplicada; em versões de factory_girl antes de 4.0, ele deveria executar isto:

Estratégias Personalizadas

Há momentos em que você pode querer estender o comportamento da factory_girl, adicionando uma estratégia de construção personalizada.

Estratégias definem dois métodos: association e result. associationrecebe uma instância FactoryGirl::FactoryRunner, sobre a qual você pode chamarrun, anulando a estratégia se você quiser. O segundo método, result, recebe uma instância de FactoryGirl::Evaluation. Ele fornece uma forma de triggercallbacks (com notify), object ou hash (para obter a instância de resultado ou ahash baseado nos atributos definidos na fábrica), e create, o que quer que seja que reduza a to_create callback definida na fábrica.

Para entender como a factory_girl usa as estratégias internamente, é provavelmente mais fácil apenas visualizar a fonte para cada uma das quatro estratégias padrão.

Aqui está um exemplo de como compor uma estratégia usandoFactoryGirl::Strategy::Create para construir uma representação JSON do seu modelo.

Para que a factory_girl reconheça a nova estratégia, você pode registrá-la:

FactoryGirl.register_strategy(:json, JsonStrategy)

Isso permite que você chame

FactoryGirl.json(:user)

Finalmente, você pode substituir as próprias estratégias da factory_girl se você quiser registrar um novo objeto no lugar das estratégias.

Custom Callbacks

Custom Callbacks podem ser definidos se você estiver usando estratégias personalizadas:

Métodos Personalizados para Persistir Objetos

Por padrão, criar um registro chamará save! na instância; como isto pode não ser sempre o ideal, você pode substituir esse comportamento definindoto_create na fábrica:

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

Para desabilitar o método de persistência totalmente na criação, você pode skip_create para aquela fábrica:

factory :user_without_database do skip_createend

Para anular to_create para todas as fábricas, defina-o dentro doFactoryGirl.define bloco:

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

Instrumentação de Apoio Ativo

Para rastrear quais fábricas são criadas (e com qual estratégia de construção),ActiveSupport::Notifications são incluídas para fornecer uma forma de subscrever as fábricas que estão sendo executadas. Um exemplo seria rastrear fábricas com base no tempo de execução.

Um outro exemplo seria rastrear todas as fábricas e como elas são usadas através da sua suíte de testes. Se você estiver usando RSpec, é tão simples quanto adicionar um before(:suite) e after(:suite):

Rails Preloaders e RSpec

Ao executar o RSpec com um pré-carregador Rails como spring ou zeus, é possível encontrar um erro ActiveRecord::AssociationTypeMismatch ao criar uma fábrica com associações, como abaixo:

O erro ocorre durante a execução da suite de teste:

As duas soluções possíveis são executar a suite sem o pré-carregador, ou adicionar FactoryGirl.reload à configuração do RSpec, assim:

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

Using Without Bundler

Se você não estiver usando o Bundler, certifique-se de ter a gem instalada e ligue:

require 'factory_girl'

Once necessário, assumindo que você tenha uma estrutura de diretório de spec/factories ou test/factories, tudo que você precisará fazer é executar

FactoryGirl.find_definitions

Se você estiver usando uma estrutura de diretório separada para suas fábricas, você pode mudar os caminhos dos arquivos de definição antes de tentar encontrar definições:

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

Se você não tem um diretório separado de fábricas e gostaria de defini-las em linha, isso também é possível:

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

Deixe uma resposta Cancelar resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Artigos recentes

  • Acela está de volta: NYC ou Boston por $99
  • Entrada OMIM – # 608363 – CHROMOSOME 22q11.2 SÍNDROME DE DUPLICAÇÃO
  • Kate Albrecht’s Parents – Learn More About Her Father Chris Albrecht And Mother Annie Albrecht
  • Temple Fork Outfitters
  • Burr (romance)

Arquivo

  • Fevereiro 2022
  • Janeiro 2022
  • Dezembro 2021
  • Novembro 2021
  • Outubro 2021
  • Setembro 2021
  • Agosto 2021
  • Julho 2021
  • Junho 2021
  • Maio 2021
  • Abril 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