Factory Girl – The Story of Goldilocks & the Three Bears

By Tomer S.

Sep 29, 2016

Just as in the story of Goldilocks and the Three Bears, in our code guests are welcome; mystery guests are not.

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 unit tests by making them faster and by testing all parts of the code.

Testing is an integral part of code writing. Unit tests of web apps 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 the 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 run time of the tests, and makes them more complicated. In order to make up the disadvantage of slowing the tests and the involving the database, we need to simulate the database in the most optimal way and to simplify the code.  

FactoryGirl, as Josh Jashi, the lead of the project, wrote to me in an email, is a great way of encapsulating data, reducing database interactions for faster tests, and encouraging the 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 return 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 turned FactoryGirl into such a powerful test Gem. First of all, FactoryGirl helps us bypass the validations of the creation process by defining the factory and using the command, FactoryGirl.define. Take a look:   
     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. It also helps us decide which type of creation we want, so that the “porridge” will not be too hot or too cold.

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 will act 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. This results in much faster tests.   

It should create an article without saving to the database:   

     object = build :article   

It should create an article object and act as an already saved article:  

  object = build_stubbed :article  

It should create an article object and save 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 convenience. Even though there is no shortcut to success, developing shortcuts can be a brilliant success index. FactoryGirl allows us to create a list of instances in a very convenient way by using create_list which uses build method to build a list of instances. 

It 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 a declared model by alias. It helps you to write “self explained code” in the test suite, and in that way allows you 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 affects all the fields of the model, you can use dynamic attributes 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 that you can do more in less time. FactoryGirl helps us to do more with 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 models:  

    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 brief blog post, I tried to summarize the main features of FactoryGirl and to cast light on its advantages. Testing is a skill you can learn as time goes on. 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. Besides that, it can upgrade your test by using build and build_stubbed methods. 

So, what are you waiting for?

Go test it yourself 🙂

Leave a Reply

Your email address will not be published.