eigenclass logo
MAIN  Index  Search  Changes  PageRank  Login

Running your tests automatically with autotest + wmii, emacs and ratpoison

Seeing the bar turn green is great for the morale; this is one of the several benefits of writing tests (even if you don't go fully TDD). Running tests manually can disrupt your workflow, though, so we're all using autotest to have our tests executed in the background continuously.

autotest includes a number of extensions to notify the result of the last tests in a non-intrusive manner, using growl, snarl, kdenotify... I'm using wmii (and my WM is fully scripted in Ruby), and it doesn't get less intrusive nor more readable than the bar:

autotest-wmii.png

And here's what the bar looks like when tests fail:

/hiki/autotestwmiiemacsratpoison/autotest_wmii_fail.png

I normally run autotest in a terminal right below/above the editor (in wmii's stacked mode), so when I want to read Test::Unit's messages I can switch quickly with Alt-j/k. My autotest extension also supports clicking on the button to see the messages or reset autotest, but there's no point in using the mouse anyway...

This snippet doesn't depend on ruby-wmii so it should run with the default wmiirc script. Just place this in ~/.autotest or #require it there:

# Copyright (C) 2006 Mauricio Fernandez http://eigenclass.org
# Use and distribution subject to the terms of the Ruby license.
module Autotest::WMII
  BARNAME = "009_autotest"
  system "wmiir create /bar/#{BARNAME}"
  @current_message = ""
  
  def self.colors(type)
    {
      :red   => "#ffffff #A02020 #FF0000",
      :green => "#ffffff #20A020 #00FF00",
      :info  => "#bbbbbb #222222 #000000"
    }[type] || "#bbbbbb #222222 #000000"
  end

  at_exit { system "wmiir remove /bar/#{BARNAME}" }

  def self.popup(text)
    IO.popen("xmessage -file -", "w"){|f| f.puts text; f.close_write }
  end
  
  def self.show_bar(title, msg, type = :info)
    @current_message = msg
    system "echo -n '#{title}' | wmiir write /bar/#{BARNAME}/data"
    system "echo -n '#{colors(type)}' | wmiir write /bar/#{BARNAME}/colors"
  end

  Autotest.add_hook :run do  |at|
    show_bar "Run", "Run" unless $TESTING
  end

  require 'pp'
  Autotest.add_hook :red do |at|
    failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a;  s + v.size}
    msg = <<EOF
#{failed_tests} tests failed. I will rerun these files:
#{at.files_to_test.pretty_inspect}
====
#{at.results}
EOF
    show_bar "#{failed_tests} failed", msg, :red
  end

  Autotest.add_hook :green do |at|
    msg = <<EOF
Tests passed
====
#{at.results}
EOF
    show_bar "OK", msg, :green #if at.tainted 
  end

  Autotest.add_hook :run do |at|
    show_bar "starting", "autotest starting", :info unless $TESTING
  end

  Autotest.add_hook :interrupt do |at|
    show_bar "reset", "autotest reset", :info unless $TESTING
  end

  Autotest.add_hook :quit do |at|
    show_bar "exiting", "autotest leaving", :info unless $TESTING
  end

  Autotest.add_hook :all do |at|_hook
    show_bar "ALL OK", "autotest: everything OK", :green unless $TESTING
  end


=begin
# Allows you to click on the bar to reset autotest, get the last message or
# kill it. Uncomment it if you want to use the mouse (don't).
  mypid = Process.pid
  Thread.abort_on_exception = true
  Thread.new do
    open("|wmiir read /event") do |is|
      loop do
        line = is.gets
        if md = /^BarClick #{BARNAME} (\d)/.match(line)
          case md[1].to_i
          when 1
            popup(@current_message)
          when 3
            Process.kill("INT", mypid)
          when 2
            #system "wmiir remove /bar/#{BARNAME}"
            Process.kill("HUP", mypid)
            Process.kill("HUP", Process.pid) # jisatsu
          end
        end
      end
    end
  end
=end
end

When I showed that to rubikitch, it took him no time to write his own .autotest for use with emacs:

# -*- ruby -*-
require 'autotest/timestamp'

def gnudoit(lisp)
  system "gnudoit", lisp
end
def emacs_message(*msgs)
  msg = msgs.join(": ")
  gnudoit %Q((message #{ msg.dump}))
end

Autotest.add_hook :red do |at|
  failed_tests = at.files_to_test.inject(0){ |s,a| k,v = a;  s + v.size}
  emacs_message "Tests Failed", "#{failed_tests} tests failed"
end

Autotest.add_hook :green do |at|
  emacs_message "Tests Passed", "All tests passed"
end

wmii isn't the only decent WM out there; ratpoison is rubikitch's WM of choice. He reports it only takes

 `ratpoison -c echo MESSAGE`

to have a message shown in the bottom-right corner for a few seconds.



Exception Raised - Ryan Mulligan (2006-12-12 (Tue) 13:47:18)

Hi, Big fan of your blog, first time I'm commenting though. I just started using WMII today to check it out, and it's great. I tried to get this autotest to work but when I run autotest in my rails directory it does rake test and all that but at the end it does..

/home/rmulliga/.autotest:39: undefined method `pretty_inspect' for #<Hash:0xb7ca2af8> (NoMethodError)

       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:283:in `hook'
       from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:in `inject'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:282:in `hook'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:206:in `handle_results'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:115:in `run_tests'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:100:in `get_to_green'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:84:in `run'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:82:in `run'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/lib/autotest.rb:62:in `run'
       from /usr/lib/ruby/gems/1.8/gems/ZenTest-3.4.2/bin/autotest:45
       from /usr/bin/autotest:18

The autotesting bar comes up at the bottom of my WMII but once the tests finish I get this error message. Any ideas?

mfp 2006-12-12 (Tue) 14:03:58

Kernel#pretty_inspect was added on Jun 17 2006, so it's missing in older releases (including 1.8.4).

You can just s/pretty_inspect/inspect/g; it will make no difference if you're not using the mouse and even if you were (but you aren't, right ;) it will only make the message less pretty.

If you're going to use ruby-wmii, take a look at ruby-wmii community: plugins and configurations for contributed plugins and snippets.

Ryan Mulligan 2006-12-12 (Tue) 14:43:45

thanks. That worked. I am not using a mouse (mostly) I am going to use ruby-wmii (it's great), I will check out the community.



Last modified:2006/12/12 05:35:56
Keyword(s):[blog] [ruby] [frontpage] [autotest] [wmii] [emacs] [ratpoison]
References: