Skip to content
setembro 18, 2008 / cassiomarques

Factory Girl para models com has_many

A idéia de usar fixtures para os testes no Rails parece muito boa em um primeiro momento, porém quando começamos a querer testar models com relacionamentos muito complexos manter essas fixtures se transforma em um verdadeiro inferno. Para cada fixture você acaba tendo que abrir vários arquivos e verificar na raça os valores dos ids referenciados nas demais fixtures associadas. É muito fácil se perder. Pior ainda, é totalmente improdutivo.
Para testar controllers esse problema pode e deve ser solucionado através do uso de algum framework para mocking, como o Mocha ou os recursos nativos de mocking do RSpec. Assim diminui-se a dependência dos models nos testes dos controllers e os testes executam mais rápido. Mas para os models nem sempre “mockar” todo o comportamento é uma boa solução. Muitas vezes você vai querer testar tudo que ocorre entre seus objetos e o banco de dados, incluindo os relacionamentos anteriormente citados.
Para os testes dos models tenho substituído as velhas fixtures pela utilização do factory_girl.
O que o factory_girl faz é possibilitar a criação de fábricas de objetos. Com essas fábricas, você pode gerar objetos de forma simplificada durante seus testes, elimando complemente a necessidade de utilização das fixtures. E com diversas vantagens.

Bom, eu não vou ficar falando sobre como usar o factory_girl, porque isso é realmente MUITO simples. Caso você ainda não conheça o factory_girl, basta olhar a documentação no site do projeto que com certeza você vai se virar bem.

O que eu gostaria de falar aqui é sobre como criar associações quando temos declaração do tipo :has_many em um dos nossos models. Eu tive que fuçar um pouquinho na net para conseguir encontrar essa informação, então talvez seja útil para mais alguém.

O fato é que cada vez que fazemos algo como

Factory.define :post do |p|
  p.title "Blabla"
  p.author { |author| author.association(:user) }  
end

estamos apenas usando um proxy que usa uma espécie de “lazy loading” para instanciar objetos a partir da fábrica de Users. Logo, se você possui um model User com uma declaração do tipo belongs_to :post, a coisa vai funcionar e pronto. Mas e quando tenho algo como

class Post < ActiveRecord::Base has_many :comments end [/source] como podemos "fabricar" uma instância de Post já com uma lista de comentários? Assim (supondo que já exista a factory para o model Comment): [source language="ruby"] Factory.define :post do |p| p.title "Blabla" p.author { |author| author.association(:user) } p.comments do |c| [c.association(:comment), c.association(:comment)] end end [/source] Perceberam? Cada vez que chamo o método association e passo o parâmetro :comment estou fazendo com que o factory_girl use a factory criada para o model Comment e gere uma nova instância desta classe, a qual é retornada como um elemento dentro de um array. Está feita minha fábrica com um relacionamento do tipo um-para-muitos.

4 Comentários

Deixe um comentário
  1. nofxx / out 1 2008 1:47 pm

    Eh cachorrao, escondendo o ouro dos amigos neh? To ha tempos qrendo ver essa garota ae..

    Pô mto manero… já to usando =D

    aheuahueahe

  2. nofxx / out 4 2008 2:02 pm

    Tambem mto interessante o Object Daddy:

    http://github.com/flogic/object_daddy/tree/master

    Muda que voce nao precisa setar as relations, mais flexibiidade no incrementer (ao custo de mais code tb.. um helper mais simples tipo factory girl seria interessante)

    Oh a sintaxe:

    class Objeto :next

    self.next
    @last ||= 1
    @last += 1
    end
    end

    Objeto.generate => Objeto.create(:nome => “Manoel….”)
    Objeto.generate! => Objeto.create!…..
    Objeto.spawn => Objeto.new…

  3. nofxx / out 4 2008 2:07 pm

    A proposito, no meu fork do annotate models:

    http://github.com/nofxx/annotate_models

    Ja anota Factory Girl e Object Daddy. =D

  4. Dimo / out 19 2008 3:39 am

    I don’t speak Portuguese, but this example was exactly what I was looking for. Thanks!

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: