Rumbster has Graduated to RubyForge

Thanks to Pat Courtney, Rumbster – The Fake Email Server has graduated to RubyForge!Rumbster is a fake email server, written in Ruby. Rumbster was designed to test web based email functionality with Watir. Rumbster facilitates email testing by publishing received emails to registered observers. Rumbster currently ships with two observers; FileMessageObserver and MailMessageObserver.FileMessageObserver dumps received email messages to a file in a defined message directory. The files are named "#{@system_time.current_time_in_seconds}_#{mail.to}.txt".MailMessageObserver appends all received email messages to a message list.

message_observer = MailMessageObserver.newserver = Rumbster.newserver.add_observer(message_observer)server.add_observer(FileMessageObserver.new('message_dir'))server.start# assert message_observer.messages has your email messagesserver.stop

How do I get Rumbster?gem install rumbstersvn co http://rumbster.rubyforge.org/svn/trunkHow do I learn more about Rumbster?Read the tests. Rumbster was written test first, so the tests should tell a good story. If you would like to contribute documentation, we would be happy to have it 😉

Updated: Rumbster; Ruby Fake Email Server

Update: Rumbster has been moved to RubyForge.What is Rumbster?Rumbster is a simple SMTP server that receives email sent from a SMTP client. Received emails are published to observers that have registered with Rumbster.Updated

  • Applied patch from Pat Courtney that allowed Rumbster to handle multiple emails per session.

Downloadhttp://rumbster.rubyforge.org/svn/trunk/

ActiveScaffold – Improved Search

As I noted in my last post, I have changed projects. In my current project, we are using a combination of Ruby and Java. A small group of developers (including me) on the project were tasked with creating a set of automation tools. One of the tools we needed was a small data gathering and reporting application to help our project managers keep track of our progress. The logical choice, for us, was to implement our reporting tool in Ruby on Rails (ROR).Why ROR? One word, “Scaffolding”. If you are not a Ruby or ROR fan, you may not be familiar with Scaffolding (screencast). Scaffolding gives a developer “declarative” control over the user interface.The original scaffolding is really not meant to be a full fledge declarative user interface. It was really intended to be a starting point. The original scaffolding does not support relationships very well (as in not at all). Given this information we knew that we needed to find a rails plugin that could do more than the original. We had two choices.

  1. Streamlined – This was the first plugin that we evaluated. We really liked the interface that it generated and its configuration syntax, but we were not happy with how it allowed users to create related objects. Creating a new relationship in Streamlined is a heavy three step process.
    1. Goto related object’s page and create the new related object.
    2. Return to the parent page.
    3. Apply the relationship to the desired parent.
  2. ActiveScaffold – This was the second plugin that we evaluated. ActiveScaffold allows users to create anything and everything about a record from a single page. This was really attractive to us. ActiveScaffold allowed us to quickly add relationships without have to move to multiple parts of the application.

ActiveScaffold won the race in the end. Armed with ActiveScaffold, we were able to quickly to implement our reporting application. One criticism from our users was the somewhat weak search that ActiveScaffold exposes.The default search is a simple ‘%like%’ search on all columns in a given record. Our users wanted to be able to negate a search. Give me all records except those that contain X. What can we do? ActiveScaffold does not support this functionality. We can go hacking 😉 The module in ActiveScaffold that implements this functionality is ActiveScaffold::Finder; specifically the create_conditions_for_columns method.This is my hacked up version of create_conditions_for_columns. Negation is triggered by placing a ~ in front of a term. Example: ~adam. Fill free to take this code and do with it as you wish. Hopefully someone else can make use of it. As always, questions and comments are welcome.

def self.create_conditions_for_columns(tokens, columns,    like_pattern = '%?%')  # if there aren't any columns, then just return a nil condition  return unless columns.length > 0  tokens = [tokens] if tokens.is_a? String  phrases = []  tokens.each do |token|    where_clauses = []    not_token = /^~/.match(token)    not_clause = not_token ? 'NOT' : ''    columns.each do |column|      where_clauses <<        "LOWER(COALESCE(#{column.search_sql}, '')) REGEXP ?"    end    phrases << "(#{not_clause} (#{where_clauses.join(' OR ')}))"  end  sql = phrases.join(' AND ')  tokens = tokens.collect do |value|    value = /^~/.match(value) ? value[1..-1] : value    value = '.' if value.empty?    [value.downcase] * columns.length  end.flatten  [sql, *tokens]end

Attribute Fun with Ruby

I have been working with Ruby a lot lately. I came across something interesting today, so I thought that I would share it.Given the following code, what do you think will be printed to the screen?

class Person  attr_accessor :last_modified  def update_last_modified    last_modified = Date.today.to_s  endendperson = Person.newperson.update_last_modifiedp person.last_modified

Coming from C#, I thought that it would print today’s date. Once again, I was wrong. It prints nil. Why would it print nil?I assume Ruby thinks last_modified is a local variable and not an attr_accessor in the method update_last_modified. I guess this makes sense. How would Ruby know it was an accessor and not a variable?To get the results that I wanted the update_last_modified would have to change to the following.

def update_last_modified  self.last_modified = Date.today.to_send

It seems a little strange to see the self coming from C#. I would never put a this in front of a property setter.If you would like to see the full code snippet, you can check it out of subversion.https://esterline.devguard.com/svn/code/ruby_snippets

Watir Revisited

A few months back I wrote about our team’s experience with User Acceptance Testing (UATs) tools (WatiN, Watir and Selenium Reviewed). I did not give Watir very high marks.


Bret’s ResponseWithin a day of the review, Bret Pettichord (creator of Watir) left the following comment.

We would appreciate any leads you can give about where you found reliability problems with Watir. Our apologies for your troubles.

This is great customer service. Bret saw that our team was having problems and responded thoughtfully. I sent the following email reply.

Thanks for your comment on my blog.We were using Watir 1.4.1. We also tried upgrading to 1.5? and thesame problem existed.We saw that accessing an element while the browser was busy caused thetest to hang. This happened frequently for us as our site has lotsof ajax calls.There are two differences between Watir and WatiN that really made thedifference for our team.

  1. Problem described above, WatiN does not seem to have this problem.May be because WatiN uses STA – check this link out for moreinformation: http://watin.sourceforge.net/apartmentstateinfo.html.
  2. WatiN waits and tries again if it cannot find the element on thepage. This makes it much easier to code tests.

I am not saying that WatiN is perfect, but these two things help uskeep our tests repeatable/reliable.

The above email prompted Bret to send this email to the Watir development mailing list.

Adam Esterline recently reported some stability issues with Watir on hisblog.http://adamesterline.com/2007/04/23/watin-watir-and-selenium-reviewed/Because of them, he decided to use Watin instead, which did not have theseproblems. I asked him for more information, and he provided the following.This is something that I would like to understand better.


Watir RevisitedGiven all of the above, I decided to revisit Watir. In order to re-evaluate Watir, I did the following:

  1. I downloaded the latest development build of Watir (1.5.1.1192).
  2. I used the same set of tests from the original review.

ResultsI ran the tests several times over the last several weeks. The problems described in my email to Bret seem to be completely fixed. I even removed all of the sleeps that were originally used to help with timing issues and the tests still passed. As far as I can tell, Watir has caught up with WatiN.Will we switch back to Watir?We have considered it. It is much easier in Ruby to create a multi-threaded test suite.Today, speed is our biggest problem with our UATs. We think they may run faster if they were run in parallel. I will keep you posted on what we decide. If James has his way, we will switch to Selenium 😉


Lesson’s Learned

  1. There is a great team of developers behind Watir that really care about their product.
  2. The internet is smaller than I realized. I certainly did not think that my post would get a response from Bret and the Watir team.

Questions/Comments are always welcome.

Garage Sale Code

Scott Hanselman has a great post about “Garage Sale Code”. I decided to do my part and provide a link to my “Garage Sale Code”.https://esterline.devguard.com/svn/code/If you have any questions about the code, please feel free to ask.

Ruby – Assigning a block to a variable

On Friday, Brian and I were discussing how to assign a block to a variable in Ruby. I knew how to pass a block as a method argument def method(&proc), but I could not remember how to just assign a block to a variable. I finally looked up the syntax.

block = lambda { |word| puts word }block.call("adam")