Playing with Unit::Test, Shoulda, Factory Girl, autotest, growl and redgreen

Since my first steps with rails I was used to write rspec tests / specifications. I was never that happy about it. Can’t say exactly why. I think it was just a “personal” thing. About two weeks ago I finally gave shoulda and his buddies a try. So here’s what I have done.

Installation

First I had to install all the gems required:

sudo gem install ZenTest thoughtbot-shoulda thoughtbot-factory_girl redgreen webrat cucumber

Everything should work fine. No big deal about that. To use shoulda, factory-girl, cucumber and webrat in your testing environment add the following lines in your config/environments/test.rb:

Shoulda and factory girl

1
2
3
4
config.gem 'thoughtbot-shoulda', :lib => 'shoulda', :source => 'http://gems.github.com', :version => ">= 2.10.1"
config.gem 'thoughtbot-factory_girl', :lib => 'factory_girl', :source => 'http://gems.github.com', :version => ">= 1.2.1"
config.gem 'webrat', :lib => false, :version => '>=0.4.3'
config.gem 'cucumber', :lib => false, :version => '>=0.2.2'

So you ensure that shoulda, factory-girl, cucumber and webrat get loaded in your test env.

Shoulda and factory-girl are really nice tools. For example you have a message model your factory (the cool way to handle messy fixtures) would look like:

1
2
3
4
5
6
Factory.define :message do |f|
  f.subject 'my subject for my message'
  f.text 'text for my message'
  f.association :sender, :factory => :sedcard
  f.association :receiver, :factory => :sedcard
end

In my case I only have a subject, text, sender and receiver. As you can see associations are alos possible. They just require other factories to be present. Ryan Bates made a great railscast on factory-girl.

Shoulda comes in with beauty and shortness. Let’s see what we have to do to check out our model. A sample unit test file for the message could be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require File.dirname(__FILE__) + '/../test_helper'
 
class MessageTest < ActiveSupport::TestCase
 
  should_have_db_column :subject, :sender_id, :sender_type, :receiver_id, :receiver_type
  should_have_db_column :deleted_by_sender, :deleted_by_receiver, :created_at, :updated_at, :read, :last_action_at
 
  context "a message" do
    setup do
      @message_part = Factory(:message_part)
      @message = @message_part.message
    end
 
    should_validate_presence_of :subject, :sender, :receiver, :text
    should_allow_values_for :subject, "Hallo", "Wie gehts?", "Model gesucht!", "รค ist cool", "Dieser Text ist nicht zu lang", "Hallo.", "Du?", "Neu!"
    should_not_allow_values_for :subject, "...", "H",  "---", "Wie gehts?"
 
  end
end

You see there’s some stuff going on in this unit test but I think it’s quite self-explanatory, isn’t it? I’m checking the presence of columns, presence of attributes and (not) allowed values for the message’s subject.

Autotest, growl and redgreen

You’ll get an ‘autotest’ command after installing ZenTest gem. If you already have some tests written your bash output may look like:
autotest on bash

What’s next? Now you have to watch your console to know if everything is fine or not. Not that cool, hummhhh … Let’s use growl to notify you about your test results. Follow the ‘Setting up growl’-part of http://www.gluedtomyseat.com/2008/5/12/configuring-autotest-and-growl-in-osx-leopard if you don’t have growlnotify installed on your mac. Next step is to create a .autotest file in your home. Mine is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module Autotest::Growl
  def self.growl title, msg, img, pri=0, sticky=""
    system "growlnotify -n autotest --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"
  end
 
  Autotest.add_hook :ran_command do |at|
    image_root = "~/.autotest_images" 
    output = at.results.last.slice(/(\d+)\stests,\s(\d+)\sassertions,\s(\d+)\sfailures,\s(\d+)\serrors/)
 
    if ($~[3].to_i > 0) or ($~[4].to_i > 0)
      growl "FAIL", "#{output}", "#{image_root}/fail.png", 2
    else
      growl "Pass", "#{output}", "#{image_root}/pass.png" 
    end
  end
end

I have a .autotest_images directory where my autotest images are stored. Running your tests again now shows you a growl notification (depends on your settings how this looks like):

growl-fail
growl-success

I recognized that the growl notification doesn’t work correctly and shows up every time. Read more on this issue and how to probably fix it.

Redgreen

After adding

1
require 'redgreen' unless ENV['TM_MODE']

in your test_helper.rb your bash output get’s some coloring:

autotest with redgreen coloring

The if statement is required that redgreen doesn’t mess up your test output if running within textmate. There are several other ways to integrate redgreen and to customize the output. Just check out redgreen documentation how to get this done.

Summary

I just gave a quick overview how to set up my environment. If you experience some problems or want to know more about the techniques and tools presented just check out the links for this post or ask google :)

Links:
http://railscasts.com/episodes/158-factories-not-fixtures
http://thoughtbot.com/projects/shoulda/
http://thoughtbot.com/projects/factory_girl
http://www.gluedtomyseat.com/2008/5/12/configuring-autotest-and-growl-in-osx-leopard
http://blog.internautdesign.com/2006/11/12/autotest-growl-goodness
http://blog.hasmanythrough.com/2007/9/10/it-s-easy-being-redgreen

One Comment

  1. Dombi Attila sagt:

    Hi!

    Thanks for this nice setup, i’m looking for this tools to be setted up together.

Leave a Reply