Replacing Ruby on Rails fixtures with Factories and Builders 1

In my current job we were facing a well known problem called Fixtures. The term Fixtures in context of Ruby On Rails framework is the default way how the testing data are prepared/created before the tests run.

Here’s the list of important reasons why Fixtures are pain:

  1. Hard to read (YAML format)
  2. Hard to define edge cases
  3. Almost impossible to modify after reaching certain size of fixtures

The only real reason for using fixtures which I can find is speed. So if you’re on small project or you really need to have tests running fast then the fixtures are good choice. But if you need to have easy to read tests with test data, possibility to easily modify them and having be able to define a lot of edge cases here’s one nice possible way to go called Design Patterns.

Factory patterns (http://en.wikipedia.org/wiki/Factory_pattern)
In these days people are already using Factory pattern as replacement for Fixtures and you can find plenty libraries to help you simplify the work:

At the end we decided to go for FactoryGirl because it’s widely used which means there’s a lot of people to help us with answering questions and fixing bugs.

Example of FactoryGirl:

1
2
3
4
5
6
7
8
9
Factory.define :invoice, :class => Invoice do |u|
  u.created_at 2.days.ago
  u.started_at 2.months.ago.beginning_of_month
  u.ended_at 2.months.ago.end_of_month
end

Factory.define :invoice_with_billing_cycle, :parent => :invoice do |u|
  u.association :billing_cycle, :factory => :billing_cycle_2_months_ago
end

Personally I also like very much Foundry by Jeremy McAnally. The only disadvantage is that it’s closely linked with Ruby On Rails named_scopes implementation.

Builder pattern (http://en.wikipedia.org/wiki/Builder_pattern)
This pattern isn’t yet widely used as Factory in Ruby On Rails community. I really don’t know why, but I didn’t find any article about using it so here we go.

I like to use this design pattern in situations when:

  • You need to create complex object structures (together with Factory)
  • You need to be flexible with creating many edge cases

The best thing about using Builder pattern is that you don’t need any library but just pure Ruby objects.

Example of Builder pattern in Ruby combined with Factory girl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class InvoiceBuilder
 
  def initialize(invoice_factory, options = {})
    @invoice_factory = invoice_factory
    @options = options
    self
  end
 
  def with_line_items(line_items)
    @line_items = line_items
    self
  end
 
  def create
    invoice = Factory(@invoice_factory.to_sym, @options)
    @line_items.each do |li|
      li_factory, li_options = li
      invoice.line_items << Factory(li_factory.to_sym,
       li_options.merge(:invoice => invoice))
    end
    invoice
  end
 
end

The code above shows very flexible way of using Builder pattern to chain your criteria as you need them. You can than write something like this:

1
InvoiceBuilder.new(:invoice_with_billing_cycle).with_line_items([ item1, item2 ]).create

Interesting articles to read:

Things to consider:

  • Try to keep your tests and Factories simple
  • Keep your data very close to your tests
  • Create complex structures with Builder pattern

Thanks for reading. Let me know what you think in comments. Any kind of feedback appreciated!

Using Null Object pattern with Ruby on Rails 1

While back ago I’ve released plugin to implement Null Object Pattern. And I’ve decided to write about it. Mostly because people are not using it or don’t know it.

What it does?

Instead of using a null reference to convey absence of an object (for instance, a non-existent customer), one uses an object which implements the expected interface, but whose method body is empty. The advantage of this approach over a working default implementation is that a Null Object is very predictable and has no side effects.

Why should I use it?

  • You will not have to prevent your code from having null reference. For example you will not have to do this:
    1
      print post.user.nil? ? 'Null user' : post.user.name

    With Null Object pattern you write just print post.user.name and you’ll get default value for Null object defined for this attribute.

  • It’s very handy if you’re doing some kind of reporting that you don’t have to deal with null reference and you have object (in SQL row reference) instead.

To install the plugin

1
ruby script/plugin install git://github.com/lacomartincik/acts_as_nullobject.git

Let’s have a look how to use it
First you’ll need to define model to acts as null object:

1
2
3
class User < ActiveRecord::Base
  acts_as_nullobject :login => 'lacomartincik', :name => 'Ladislav Martincik'
end

Than whenever you call on User class method null_object you will get instance of NullUser class with default attributes defined in User:

1
2
>> User.null_object
=> NullUser...

Now if you define relationship between say Project and User like this:

1
2
3
class Project < ActiveRecord::Base
   belongs_to_with_nullobject :user
end

Than whenever you create new Project object with null reference to User you will get NullUser instance instead of nil:

1
2
3
>> p = Project.new
>> p.user
=> NullUser

The project is available as plugin on http://github.com/lacomartincik/acts_as_nullobject.

Enjoy! Any suggestions, bug reports and comments welcomed!

Update: I had to rename plugin name from acts-as-nullobject to acts_as_nullobject otherwise it’s not going to work in Rails!

Testing your Flex app with new FunFX 19

A few weeks ago I’ve started to dig in to new funfx gem to transform our old FunFx code and get benefit of new features that new FunFX is providing. The main reasons for moving to new code are:

  1. Support for Firefox, so now we can run tests even on Linux boxes
  2. Support for AdvancedDatagrid
  3. Much better way to find components with :id and :automationName
  4. Based on Watir so we can test also IE if needed
  5. Visual recorder and component finder

Installation

You can install new funfx with just running on console command gem install funfx or you can download source code from GitHub. The funfx gem is dependent on Watir specific gem. Based on platform or preferences install either Watir (Win XP, Vista), SafariWatir (Mac OS X) or FireWatir (all platforms). NOTE: With FireWatir you’ll need to install Firefox Extension!

Installation Examples

- Using gems on Mac OS X

1
2
3
sudo gem uninstall FunFX
sudo gem install funfx
sudo gem install safariwatir

- Using source code (you’ll need Git installed)

1
2
3
4
5
6
7
8
9
sudo gem uninstall FunFX
git clone git://github.com/peternic/funfx.git
cd flex
./build.sh
cd ..
cd gem/
rake gem
rake install_gem
sudo gem install safariwatir

FunFX interface changes

Changing speed of your FunFX run
Old version was using class attribute on FunFX object like this:

1
FunFX.speed = 0.5 # half of second

New version has different class attribute name:

1
FunFX.fire_pause = 0.5

FunFX language/DSL changes
Basic components didn’t change, but arguments you’re passing changed from Hash-like style to simple arguments or vice versa.

- Finding component
For example to find component you can now use more than one identificator like :id, :automationName and so on.

Old style to find component:

1
@browser.text_area('myname')

New style:

1
@browser.text_area(:id => 'myname')

- Getting number of rows from DataGrid

Old style (as a result you will get concatenated string by comma):

1
2
@browser.data_grid('myname').tabular_data(:start => 0, :end => 2)
=> '1,Timothy Ferris,user'

New style (as a result you will get array of column values for each row):

1
2
@browser.data_grid('myname').values(0,2)
=> [['1','Timmothy Ferris','user']]

- How to find all supported methods and their arguments?
To find the right number of arguments and their meaning have a lot at elements.rb file or generate RDoc.

- Methods returning boolean
All methods returning boolean value now requires you to write question mark at the end of the method name.

Old style:

1
@browser.check_box(:id => 'myname').selected

New style:

1
@browser.check_box(:id => 'myname').selected?

- No CamelCase in method names
Old FunFX supported both styles for method calls; CamelCase and classic ruby style with underscore. New FunFX forces you to use only classic ruby style with underscore.

Old style:

1
@browser.check_box(:id => 'myname').currentState

New style:

1
@browser.check_box(:id => 'myname').current_state

Observations
Pros:

  1. Code is much cleaner and is promising much stable way for writing FunFX tests.
  2. Multiple browser’s and platforms support.
  3. Easy way to find components.

Cons:

  1. Recorder is not always useful in copy/paste scenario
  2. Visual component finder is not able to find itemRenderers inside DataGrid (you have to go through tree manually)
  3. Not much of documentation

Links and resources:
Old FunFX site: http://funfx.rubyforge.org/
Author and main contributor to FunFX: http://peternic.blogspot.com/
New FunFX GitHub repository: http://github.com/peternic/funfx/tree/master
RubyForget site: http://funfx.rubyforge.org/
Bug/Issue tracking: http://bekkopen.lighthouseapp.com/projects/20367-funfx/
Google Group: http://groups.google.com/group/funfx?pli=1

Read more »

Becaming freelancer 0

As of 31 of January, 2009 I’ll became available as freelancer for 3 days work per week. I’m interested in doing Ruby and Servers related projects. You can find my online CV at Linkedin.com. My Open source code can be found at Github.com. If you’re interested, please leave your details in comment and I’ll contact you back. Thank you

« Previous Page