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"  

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    


  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"  
      trait :unpublished  do 
       status :unpublished 
       published_at "2016-09-12 19:24:51  
      trait :in_the_future do  
        published_at { 2.days.from_now }  
    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"  
Second, generate the required data:  

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

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


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 }    
      factory :post do    
         title "How to read a book"   
         body "There are five steps involved."   
      factory :comment do    
         body  "Great article!"   

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!" }  
      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. 


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      

   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