Factory girl the Story of Goldilocks and the Three Bears

Sep 29 2016

Just like in the story of Goldilocks and the Three Bears, in our code- guests are welcome, mystery guests aren't.   While we are testing our application , we need to challenge the logic and design of our code. In order to do so efficiently we will increase the power of our unitests by making it faster and by testing all parts of the code. Testing is an integral part of code writing. Unitests of Web applications need to test both the server side and the client side. The challenge of testing the server side is the decrease in performance speed due to the writing to database. As a Full Stack developer it is very important to conduct the tests in a convenient way, without compromising on quality. This is the main goal of FactoryGirl.   
  

Someone’s been sleeping in my bed

  As mentioned above, testing server side includes dealing with the Database, which significantly slows the running time of the tests, and make the tests more complicated. In order to make up the disadvantage of slowing the tests and the involvement of the database, we need to simulate data base in the most optimal way and to simplify the code.  
FactoryGirl, as Josh Jashi, the lead of the project, wrote to me in E-mail, is a great way of encapsulating data , reducing database interactions for faster tests, and encouraging removal of the "mystery guest" code smell. Like the Three Bears, we want that the code will be covered and that the mystery guest of our code- will "never returned to the home of the three bears". Using FactoryGirl we let our guest in only if it is through the front door while we are home and after it knocks on the door.  
  

I know who was sleeping in my bed

  In the following paragraphs I will try to summarize the features and methods that made FactoryGirl be such a powerful test Gem. First of all, FactoryGirl helps us bypass the validations of the creation process, by defining the factory, using the command FactoryGirl.define.  
     FactoryGirl.define do   
        factory :article do    
            title "Factory-girl"  
            text  "The Story of Goldilocks and the Three Bears"  
            published_at "2016-09-12 19:24:51"  
       end    
    end   
  

This porridge is just right

  One aspect of testing data is its' creation. FactoryGirl offers sets of methods and callbacks to simulate data creation, and helps us decide which type of creation we want, so that the "porridge" will not be too hot and not cold immediately. By using create method the instance behaves like a saved one in the database, however while we are using build method the instance behaves like an unsaved. If we want to ‘have our cake and eat it too’ we will use build_stubbed strategy, so the instance will be created  and acts as an already saved instance, although it isn't. It mimics the object having an id, so it looks like it is a record from the database, even though it never writes to the database. It results in much faster tests.   

should create an Article without saving to db  

     object = build :article   

should create an Article object and acts as an already saved Article  
     object = build_stubbed :article  
should creates an Article object and saves it to the database  
     object_save_to_db = create :article  

This chair is just right

  Another aspect of testing data that FactoryGirl gives us is the convenience. Even though there is not a shortcut to success, developing shortcuts can be a brilliant success index. FactoryGirl offers us to create a list of instances in a very convenient way by using create_list which uses build method to build list of instances. 
should create a collection of objects for a given factory
      object_save_to_db = create_list :article, 4    

Traits

  We can declare specific definitions of the instance by creating a trait that Incorporates all the required values under one definition.   
       factory :article  do  
       title "Factory-girl"            
     
      trait :published  do 
       status :published  
       published_at "2016-09-12 19:24:51"  
      end
  
      trait :unpublished  do 
       status :unpublished 
       published_at "2016-09-12 19:24:51  
      end  
       
      trait :in_the_future do  
        published_at { 2.days.from_now }  
      end  
     end
   
    object_save_to_db = create :article, :unpublished, :in_the_future  
    object_save_to_db= build :article, :published  
    object_save_to_db = build_stubbed :article, :in_the_future  
   
Generating information is also very convenient by using sequences, which helps to generate data in two steps.  
First, you need to declare which value you want to generate:  

    sequence :published_at do |n|  
         "2016-06-#{n} 15:24:51"  
      end  
  
Second, generate the required data:  

   factory :article do  
            title "Moshiko"  
            text  "Moshiko is the best!"  
            published_at {generate :published_at}  
       end 

   #=> published_at: "2016-06-1 15:24:51"   

Alias

FactoryGirl allows you to use declared model by alias. It helps you to write "self explained code" in the test suite, and in that way to simplify it.  
      factory :user, aliases: [:author, :commenter] do    
          first_name "Yariv"    
          last_name "Navon"   
          date_of_birth { 18.years.ago }    
      end  
      factory :post do    
         author   
         title "How to read a book"   
         body "There are five steps involved."   
      end    
      factory :comment do    
         commenter   
         body  "Great article!"   
      end  
  

Dynamic attributes

  While writing a lot of code with different values, which effect on all the fields of the model, you can use dynamic attributes in order to do that in a convenient way.   

    factory :article do 
       title "Joe"  
       text  { "#{title} is the best!" }  
     end  
  
      object_save_to_db = create :article, title: "Moshiko" 

#=> text: "Moshiko is the best!"   

Goldilocks was very tired by this time

  Convenience is measured in a way you can do more in less time. FactoryGirl helps us to do more in less effort, and also in a very clear way.
Associations help us organize the database associations. 


Associations

Common use of models is the association between two models, with FactoryGirl it is easy to refer between two model.  

    factory :comment, aliases: [:note] do  
         commenter "moshiko"  
         body  "This is my comment"  
         association :article, factory: :article      
    end  
 

   object_save_to_db = build :comment  
   #=> object_save_to_db.article.title: "Factory-girl"  

Just then, Goldilocks woke up and saw the three bears

  In this short session I tried to summarize the main features of FactoryGirl and to cast light on the advantages of it. Testing is a skill you learn as the time goes by. In my opinion, the challenge in tests is the running time and mocking the data. FactoryGirl answers these two main issues. It helps you organize your test suite in a very convenient way. beside that, it can upgrade your test by using build and build_stubbed methods. 

Why are you waiting?

go test it yourself :)

 

 

Tomer S.
Software Developer
Back to Blog