Archive for the ‘testing’ Category

AutoGrowling: making autotest and spectest work with Growl

I like test and feature driven development. It keeps me on track when writing ruby code. Since I work on few different projects and some of these projects use TestUnit while others use Rspec I needed the .autospec hook to handle both formats.

So here is another tutorial on how to get these things working together:

  1. Download Growl from: http://growl.info/
  2. Install the downloaded dmg
  3. Install growlnotify from Extras/growlnotify folder in the dmg
  4. Copy the folder to your desktop
    Open the terminal and run following commands.

    $ cd Desktop/growlnotify
    $ sudo sh install.sh
  5. Create
    ~/.autotest_images/

    folder.

  6. Save following images into the folder.

Install following gems: ZenTest, redgreen:

$ [sudo] gem install ZenTest
$ [sudo] gem install redgreen

Download the script below and rename the file to .autotest and place it in your home folder user folder.

##!/usr/bin/ruby
require 'autotest/redgreen'
require 'autotest/timestamp'
 
class AutoTestNotifier
  IMAGEDIR = File.expand_path("~/.autotest_images")
  FAIL_IMG = IMAGEDIR + "/rails_fail.png"
  PASS_IMG = IMAGEDIR + "/rails_pass.png"
  PEND_IMG = IMAGEDIR + "/rails_pending.png"
 
  def self.growl(data)
    AutoTestNotifier.new(data).notify
  end
 
  def initialize(data)
    @priority = nil
    @result = {}
    if data.last =~ /examples/i
      parse_spec_message(data)
    else
      parse_unit_message(data)
    end
  end
 
  def parse_spec_message(data)
    @result[:type] = :spec
    output = data.last.strip.gsub(/\e\[\d+m/, '').split(',')
    output.map do |i| 
      val, lbl = i.strip.split(" ")
      @result[lbl.to_sym] = val.to_i
    end
  end
 
  def parse_unit_message(data)
    @result[:type] = :unit
    output = data.last.chop.split(',')
    output.map do |i| 
      val, lbl = i.strip.split(" ")
      @result[lbl.to_sym] = val.to_i
    end
  end
 
  def img
    return FAIL_IMG if @result[:errors].to_i > 0 || @result[:failures].to_i > 0 
    return PEND_IMG if @result[:pending].to_i > 0 
    return PASS_IMG
  end
 
  def title
    pre = @result[:type] == :spec ? "Spec Tests" : "Unit Tests"
    return "#{pre} Failed:" if @result[:errors].to_i > 0 || @result[:failures].to_i > 0 
    return "#{pre} Pending:" if @result[:pending].to_i > 0 
    return "#{pre} Passed:"
  end
 
  def to_s
    msg = ""
    msg << "Examples: #{@result[:examples]}     " if @result[:examples]
    msg << "Tests: #{@result[:tests]}     " if @result[:tests]
    msg << "Assertions: #{@result[:assertions]}     " if @result[:assertions]
    msg << "Pending: #{@result[:pending]}      " if @result[:pending]
    msg << "Failures: #{@result[:failures]}     "
    msg << "Errors: #{@result[:errors]}" if @result[:errors]
    msg
  end
 
  def priority
    return @priority || 0
  end
 
  def stick
    return ""
  end
 
  def notify
    cmd = "growlnotify -n autotest --image #{img} -p #{priority} -m '#{to_s}' #{title} #{stick}" 
    `#{cmd}`
  end
 
end
 
module Autotest::Growl
  Autotest.add_hook :ran_command do |at|
    AutoTestNotifier.growl(at.results)
  end
end

This should take care for both the UnitTest and RSpec messages.

Rails, tests and code coverage

“If it’s not tested assume it’s broken.” This is one of the mantras in my company. Sometimes it’s easier said then done. If I always had to test everything I would be doing nothing but testing. So I employ different techniques to keep me programming and the computer to test the code I write.

One of the nice things about Rails is that you have a whole array of tools to automate testing and at least one very nice tool to let you know what’s tested and what’s not. Yes I am talking about Rcov.

Rcov has been “the bee’s knees” for code coverage awareness. Recently I have noticed Rcov has been doing more work then expected. When I ran the rcov command in a rails project it tested everything. I mean everything, including gems installed on the system.

Since everything is just a bit too much for my project I started looking for a way to limit the output. It appears I had to use -x option to stop the code coverage tool from traversing the gems. Here is the whole task:

desc 'Measures test coverage using rcov'
Rcov::RcovTask.new(:rcov) do |rcov|
  rcov.pattern    = "test/**/*_test.rb"
  rcov.rcov_opts  = [
    "-x 'gems/.*,rubygems/.*,rcov/.*'",
    "-T",
    "--rails" ]
  rcov.output_dir = "rcov/unified"
end

I hope this helps you.