Skip to content
Menu
CDhistory
CDhistory

Cómo empezar

Posted on agosto 17, 2021 by admin
  • Actualiza tu Gemfile
  • Configura tu suite de pruebas
  • Test::Unit
  • Cucumber
  • Spinach
  • Minitest
  • Minitest::Spec
  • minitest-rails
  • Definiendo fábricas
  • Usando fábricas
  • Atributos dinámicos
  • Aliases
  • Atributos dependientes
  • Atributos transitorios
  • Nombre de método / Atributos de palabras reservadas
  • Herencia
  • Asociaciones
  • Secuencias
  • Traits
  • Callbacks
  • Modificación de fábricas
  • Construcción o creación de múltiples registros
  • Linting Factories
  • Construcción personalizada
  • Estrategias personalizadas
  • Custom Callbacks
  • Métodos personalizados para persistir objetos
  • Instrumentación de SoporteActivo
  • Precargadores de Rails y RSpec
  • Usando sin Bundler

Actualiza tu Gemfile

Si estás usando Rails, tendrás que cambiar la versión requerida de factory_girl_rails:

gem "factory_girl_rails", "~> 4.0"

Si no estás usando Rails, sólo tendrás que cambiar la versión requerida de factory_girl:

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

Una vez actualizado tu Gemfile, querrás actualizar tu bundle.

Configura tu suite de pruebas

Recuerda requerir el archivo anterior en tu rails_helper ya que la carpeta de soporte no se carga ansiosamente

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

Si no incluye FactoryGirl::Syntax::Methods en su conjunto de pruebas, entonces todos los métodos de factory_girl tendrán que ir precedidos de FactoryGirl.

Definiendo fábricas

Cada fábrica tiene un nombre y un conjunto de atributos. El nombre se utiliza para adivinar la clase del objeto por defecto, pero es posible especificarlo explícitamente:

Es muy recomendable tener una fábrica para cada clase que proporcione el conjunto más simple de atributos necesarios para crear una instancia de esa clase. Si está creando objetos de ActiveRecord, eso significa que sólo debe proporcionar los atributos que se requieren a través de validaciones y que no tienen valores predeterminados. Se pueden crear otras fábricas a través de la herencia para cubrir escenarios comunes para cada clase.

Intentar definir varias fábricas con el mismo nombre dará lugar a un error.

Las fábricas pueden definirse en cualquier lugar, pero se cargarán automáticamente después de llamar a FactoryGirl.find_definitions si las fábricas se definen en archivos en las siguientes ubicaciones:

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

Usando fábricas

factory_girl soporta varias estrategias de construcción diferentes: build, create, attributes_for y build_stubbed:

Independientemente de la estrategia que se utilice, es posible anular los atributos definidos pasando un hash:

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

Atributos dinámicos

La mayoría de los atributos de la fábrica pueden añadirse utilizando valores estáticos que se evalúan cuando se define la fábrica, pero algunos atributos (como las asociaciones y otros atributos que deben generarse dinámicamente) necesitarán valores asignados cada vez que se genere una instancia. Estos atributos «dinámicos» pueden añadirse pasando un bloque en lugar de un parámetro:

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

Debido a la sintaxis de bloques en Ruby, la definición de atributos como Hashes (para columnas serializadas/JSON, por ejemplo) requiere dos conjuntos de llaves:

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

Aliases

factory_girl permite definir alias a fábricas existentes para facilitar su reutilización. Esto podría ser útil cuando, por ejemplo, tu objeto Post tiene un atributo author que en realidad se refiere a una instancia de una clase User. Mientras que normalmente factory_girl puede inferir el nombre de la fábrica a partir del nombre de la asociación, en este caso buscará una fábrica de autor en vano. Por lo tanto, el alias de su fábrica de usuario para que pueda ser utilizado bajo nombres de alias.

Atributos dependientes

Los atributos pueden basarse en los valores de otros atributos utilizando el evaluadorque se rinde a los bloques de atributos dinámicos:

Atributos transitorios

Hay veces en que su código puede ser DRYed pasando en atributos transitorios a las fábricas.

Los atributos estáticos y dinámicos pueden ser creados como atributos transitorios. Los atributos transitorios serán ignorados dentro de attributes_for y no se establecerán en el modelo, incluso si el atributo existe o se intenta anularlo.

Dentro de los atributos dinámicos de factory_girl, puedes acceder a los atributos transitorios como esperarías. Si necesita acceder al evaluador en una devolución de llamada de factory_girl, tendrá que declarar un segundo argumento de bloque (para el evaluador) y acceder a los atributos transitorios desde allí.

Nombre de método / Atributos de palabras reservadas

Si sus atributos entran en conflicto con métodos o palabras reservadas existentes, puede definirlos con add_attribute.

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

Herencia

Puedes crear fácilmente múltiples fábricas para la misma clase sin repetir los atributos comunes anidando fábricas:

También puedes asignar el padre explícitamente:

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

Como se mencionó anteriormente, es una buena práctica definir una fábrica básica para cada clasecon sólo los atributos necesarios para crearla. A continuación, crear más specificfactories que heredan de este padre básico. Las definiciones de fábrica siguen siendo código, por lo que hay que mantenerlas DRY.

Asociaciones

Es posible establecer asociaciones dentro de las fábricas. Si el nombre de la fábrica es el mismo que el nombre de la asociación, el nombre de la fábrica se puede omitir.

factory :post do # ... authorend

También se puede especificar una fábrica diferente o anular atributos:

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

El comportamiento del método de asociación varía dependiendo de la estrategia de construcción utilizada para el objeto padre.

Para no guardar el objeto asociado, especifique la estrategia: :build en la fábrica:

Tenga en cuenta que la opción strategy: :build debe pasarse a una llamada explícita a association, y no puede usarse con asociaciones implícitas:

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

La generación de datos para una relación has_many es un poco más complicada, dependiendo de la cantidad de flexibilidad deseada, pero aquí hay un ejemplo seguro de generación de datos asociados.

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

Esto nos permite hacer:

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

La generación de datos para una relación has_and_belongs_to_many es muy similar a la relación has_many anterior, con un pequeño cambio, hay que pasar una matriz de objetos al nombre del atributo pluralizado del modelo en lugar de un solo objeto a la versión singular del nombre del atributo.

Aquí hay un ejemplo con dos modelos que están relacionados a través dehas_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

Esto nos permite hacer:

Secuencias

Los valores únicos en un formato específico (por ejemplo, las direcciones de correo electrónico) pueden begenerated utilizando secuencias. Las secuencias se definen llamando a sequence en un bloque de definición, y los valores de una secuencia se generan llamando agenerate:

Las secuencias pueden utilizarse en atributos dinámicos:

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

O como atributos implícitos:

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

Y también es posible definir una secuencia en línea que sólo se utiliza en una fábrica particular:

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

También puede anular el valor inicial:

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

Sin un bloque, el valor se incrementará a sí mismo, comenzando en su valor inicial:

factory :post do sequence(:position)end

Las secuencias también pueden tener alias. Los alias de las secuencias comparten el mismo contador:

Define los alias y utiliza el valor por defecto (1) para el contador

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

Estableciendo el valor:

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

El valor sólo necesita soportar el método #next. Aquí el siguiente valor será ‘a’, luego ‘b’, etc.

Traits

Los traits permiten agrupar atributos y luego aplicarlos a cualquier fábrica.

Los traits pueden usarse como atributos:

Los traits que definen los mismos atributos no levantarán AttributeDefinitionErrors;el trait que define el atributo más reciente tiene precedencia.

También puedes anular los atributos individuales concedidos por un trait en las subclases.

Los traits también se pueden pasar como una lista de símbolos cuando construyes una instancia desde factory_girl.

Esta capacidad funciona con build, build_stubbed, attributes_for y create.

create_list y build_list métodos también son compatibles. Sólo recuerde pasar el número de instancias a crear/construir como segundo parámetro, como se documenta en la sección «Construir o crear múltiples registros» de este archivo.

Los traits también se pueden utilizar con asociaciones fácilmente:

Cuando se utilizan nombres de asociaciones diferentes a los de la fábrica:

Los traits se pueden utilizar dentro de otros traits para mezclar sus atributos.

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

Por último, los traits pueden aceptar atributos transitorios.

Callbacks

factory_girl pone a disposición cuatro callbacks para inyectar algo de código:

Ejemplos:

Nota que tendrás una instancia del usuario en el bloque. Esto puede ser útil.

También puedes definir múltiples tipos de callbacks en la misma fábrica:

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

Las fábricas también pueden definir cualquier número del mismo tipo de callback. Estas devoluciones de llamada se ejecutarán en el orden en que se especifiquen:

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

Llamando a create se invocarán tanto las devoluciones de llamada de after_build como las de after_create.

Además, al igual que los atributos estándar, las fábricas hijas heredarán (y también pueden definir) las devoluciones de llamada de su fábrica padre.

Se pueden asignar múltiples callbacks para ejecutar un bloque; esto es útil cuando se construyen varias estrategias que ejecutan el mismo código (ya que no hay callbacks que se compartan en todas las estrategias).

Para anular las devoluciones de llamada de todas las fábricas, defínelas dentro del bloqueFactoryGirl.define:

También puede llamar a las devoluciones de llamada que dependen de Symbol#to_proc:

Modificación de fábricas

Si le dan un conjunto de fábricas (digamos, de un desarrollador de gemas) pero quiere cambiarlas para que se adapten mejor a su aplicación, puede modificar esa fábrica en lugar de crear una fábrica hija y añadirle atributos.

Si una gema te diera una fábrica de usuario:

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

En lugar de crear una fábrica hija que añadiera atributos adicionales:

Podrías modificar esa fábrica en su lugar.

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

Al modificar una fábrica, puedes cambiar cualquiera de los atributos que quieras (aparte de los callbacks).

FactoryGirl.modifyDebe ser llamado fuera de un bloque FactoryGirl.define ya que opera en las fábricas de manera diferente.

Una advertencia: sólo puede modificar las fábricas (no secuencias o rasgos) y callbacks todavía compuesto como lo haría normalmente. Por lo tanto, si la fábrica que está modificando define una devolución de llamada after(:create), la definición de un after(:create) no lo anulará, sólo se ejecutará después de la primera devolución de llamada.

Construcción o creación de múltiples registros

A veces, usted querrá crear o construir múltiples instancias de una fábrica a la vez.

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

Estos métodos construirán o crearán una cantidad específica de fábricas y las devolverán como un array.Para establecer los atributos de cada una de las fábricas, puedes pasar un hash como harías normalmente.

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

build_stubbed_listTambién hay un conjunto de métodos *_pair para crear dos registros a la vez:

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

Si necesitas múltiples hashes de atributos, attributes_for_list los generará:

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

Linting Factories

factory_girl permite el linting de fábricas conocidas:

FactoryGirl.lint

FactoryGirl.lintcrea cada fábrica y atrapa cualquier excepción planteadadurante el proceso de creación. FactoryGirl::InvalidFactoryErrorSe levanta con una lista de fábricas (y las excepciones correspondientes) para las fábricas que no pudieron ser creadas.

El uso recomendado de FactoryGirl.lintes ejecutar esto en una tarea antes de que se ejecute su conjunto de pruebas.Ejecutarlo en una tarea before(:suite), tendrá un impacto negativo en el rendimiento de sus pruebas cuando se ejecuten pruebas individuales.

Ejemplo de tarea de Rake:

Después de llamar a FactoryGirl.lint, es probable que quiera limpiar la base de datos, ya que es muy probable que se creen registros. El ejemplo anterior utiliza la gema database_cleaner para limpiar la base de datos; asegúrese de añadir la gema a su archivo de gemas bajo los grupos apropiados.

Puede limpiar las fábricas de forma selectiva pasando sólo las fábricas que desee limpiar:

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

Esto limpiará todas las fábricas que no lleven el prefijo old_.

Los rasgos también se pueden limpiar. Esta opción verifica que cada rasgo de una fábrica genera un objeto válido por sí mismo.Esto se activa pasando traits: true al método lint:

FactoryGirl.lint traits: true

También se puede combinar con otros argumentos:

FactoryGirl.lint factories_to_lint, traits: true

También se puede especificar la estrategia utilizada para el linting:

FactoryGirl.lint strategy: :build

Construcción personalizada

Si quieres usar factory_girl para construir un objeto en el que se pasen algunos atributos a initialize o si quieres hacer algo distinto a simplemente llamar a new en tu clase de construcción, puedes anular el comportamiento por defecto definiendo initialize_with en tu fábrica. Ejemplo:

Aunque factory_girl está escrita para trabajar con ActiveRecord, también puede funcionar con cualquier clase Ruby. Para una máxima compatibilidad con ActiveRecord, el inicializador por defecto construye todas las instancias llamando a new en su clase de construcción sin ningún argumento. A continuación, llama a los métodos de escritura de atributos para asignar todos los valores de los atributos. Aunque esto funciona bien para ActiveRecord, en realidad no funciona para casi ninguna otra clase Ruby.

Puedes anular el inicializador para:

  • Construir objetos que no sean ActiveRecord y que requieran argumentos para initialize
  • Utilizar un método distinto de new para instanciar la instancia
  • Hacer cosas locas como decorar la instancia después de construirla

Cuando se utiliza initialize_with, no hay que declarar la clase misma al llamar a new; sin embargo, cualquier otro método de la clase que desee llamar tendrá que ser llamado en la clase explícitamente.

Por ejemplo:

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

También puedes acceder a todos los atributos públicos dentro del bloque initialize_withllamando a attributes:

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

Esto construirá un hash de todos los atributos que se pasarán a new. No incluirá los atributos transitorios, pero se pasará todo lo demás definido en la fábrica (asociaciones, secuencias evaluadas, etc.)

Puede definir initialize_with para todas las fábricas incluyéndolo en el bloqueFactoryGirl.define:

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

Cuando se utiliza initialize_with, los atributos a los que se accede desde el bloque initialize_with se asignan sólo en el constructor; esto equivale aproximadamente al siguiente código:

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

Esto evita la asignación duplicada; en las versiones de factory_girl anteriores a la 4.0, se ejecutaría esto:

Estrategias personalizadas

Hay ocasiones en las que puede querer ampliar el comportamiento de factory_girl añadiendo una estrategia de construcción personalizada.

Las estrategias definen dos métodos: association y result. associationrecibe una instancia FactoryGirl::FactoryRunner, sobre la que se puede llamarrun, anulando la estrategia si se desea. El segundo método, result, recibe una instancia FactoryGirl::Evaluation. Proporciona una manera de desencadenar callbacks (con notify), object o hash (para obtener la instancia de resultado o ahash basado en los atributos definidos en la fábrica), y create, que ejecuta el callback to_create definido en la fábrica.

Para entender cómo factory_girl utiliza las estrategias internamente, es probablementemás fácil ver la fuente para cada una de las cuatro estrategias por defecto.

Aquí hay un ejemplo de composición de una estrategia usandoFactoryGirl::Strategy::Create para construir una representación JSON de su modelo.

Para que factory_girl reconozca la nueva estrategia, puedes registrarla:

FactoryGirl.register_strategy(:json, JsonStrategy)

Esto te permite llamar

FactoryGirl.json(:user)

Por último, puedes anular las estrategias propias de factory_girl si lo deseas registrando un nuevo objeto en lugar de las estrategias.

Custom Callbacks

Se pueden definir callbacks personalizados si utilizas estrategias personalizadas:

Métodos personalizados para persistir objetos

Por defecto, la creación de un registro llamará a save! en la instancia; como esto puede no ser siempre ideal, puede anular ese comportamiento definiendoto_create en la fábrica:

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

Para desactivar el método de persistencia por completo en la creación, puede skip_createpara esa fábrica:

factory :user_without_database do skip_createend

Para anular to_create para todas las fábricas, defínalo dentro del bloqueFactoryGirl.define:

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

Instrumentación de SoporteActivo

Para rastrear qué fábricas se crean (y con qué estrategia de construcción), se incluye ActiveSupport::Notifications para proporcionar una forma de suscribirse a las fábricas que se ejecutan. Un ejemplo sería el seguimiento de las fábricas basado en un umbral de tiempo de ejecución.

Otro ejemplo sería el seguimiento de todas las fábricas y cómo se utilizan a través de su conjunto de pruebas. Si utilizas RSpec, es tan sencillo como añadir un before(:suite) y un after(:suite):

Precargadores de Rails y RSpec

Cuando se ejecuta RSpec con un precargador de Rails como spring o zeus, es posible encontrar un error ActiveRecord::AssociationTypeMismatch al crear una fábrica con asociaciones, como se indica a continuación:

El error se produce durante la ejecución de la suite de pruebas:

Las dos soluciones posibles son ejecutar la suite sin el precargador, o añadir FactoryGirl.reload a la configuración de RSpec, así:

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

Usando sin Bundler

Si no estás usando Bundler, asegúrate de tener la gema instalada y llama:

require 'factory_girl'

Una vez requerido, asumiendo que tienes una estructura de directorios de spec/factories otest/factories, todo lo que tendrás que hacer es ejecutar

FactoryGirl.find_definitions

Si estás usando una estructura de directorios separada para tus fábricas, puedes cambiar las rutas de los archivos de definición antes de intentar encontrar las definiciones:

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

Si no tienes un directorio separado de fábricas y quieres definirlas en línea, también es posible:

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

Deja una respuesta Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Entradas recientes

  • Acela está de vuelta: NYC o Boston por 99 dólares
  • Entrada OMIM – # 608363 – SÍNDROME DE DUPLICACIÓN DEL CROMOSOMA 22q11.2
  • Los padres de Kate Albrecht – Conoce más sobre su padre Chris Albrecht y su madre Annie Albrecht
  • Temple Fork Outfitters
  • Burr (novela)

Archivos

  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • junio 2021
  • mayo 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