Wednesday, May 16, 2012

Unit testing Blather applications using RSpec

Blather is an easy to use XMPP client library written in Ruby. It seems to be actively developed and supported, as opposed to its competition XMPP4R library. I am using it in an application that has thousands of users interacting with it in real time.

Refer to for more details about the library.

This post demonstrates one way of writing concise tests for Blather based applications using RSpec.

There are different ways of writing Blather applications as shown in

I have chosen the following approach of subclassing the Blather client, as it led to readable clients and simple tests.

#!/usr/bin/env ruby

require "blather/client/client"

class OurClient < Blather::Client
  def initialize

    register_handler :subscription, :request? do |stanza|

    register_handler :message, :chat?, :body do |stanza|

  def on_subscription(stanza)
    write stanza.approve!   # Approve the subscription request.
    write stanza.request!   # Request subscription in turn.

  def on_message(stanza)
    # Echo the received message back to the sender.
    write stanza.from, "You sent: #{stanza.body}"

if __FILE__ == $0
  trap(:INT) { EM.stop }
  trap(:TERM) { EM.stop }

  client = OurClient.setup "@", "", "", 5222 { }

The application above demonstrates handling of subscription requests (invitations to add as a friend) and incoming messages. These are the two major interactions that a typical XMPP client engages in.

On receiving an invitation, our client simply accepts the invitation and sends a similar request to the sender. At the end of it, both the invitee and our client are subscribed to each other.

On receiving a message, our client simply echoes the message back, as an acknowledgement of the message.

Writing specs for this client is as simple:

require "spec_helper"
require "our_client"

describe OurClient do
  let(:client) { }
  before { client.stub!(:write) }

  describe "#initialize" do
    it "registers a handler for subscriptions." do
      stanza =,

      client.send :call_handler_for, :subscription, stanza

    it "registers a handler for messages." do
      stanza =, random_string)

      client.send :call_handler_for, :message, stanza

  describe "#on_subscription" do
    it "approves the subscription request." do
      stanza =,


    it "sends a subscription request." do
      stanza =,


  describe "#on_message" do
    it "echoes the response back." do
      body = random_string
      sender = random_email
      stanza =, body)

      client.should_receive(:write) do |message| == sender
        message.body.should == "You sent: #{body}"

Sharing Your Mac OS X Desktops Using Google Drive

Here is what my Macbook Desktop looks like:

My iMac desktop in my office also looks exactly like the above. In fact, when I create a file on my Macbook desktop at home, it magically appears on my iMac desktop in the office.

My desktop now lives in the Cloud, thanks to Google Drive. There is no "special folder" that I have to remember putting my files into for them to be synced across all my machines.

How did I do this? Read on!

First, you have to install Google Drive. Go to and log into your Google account. Click on the "Get started with 5 GB free" button on the top.
Click on "Download Google Drive" link at the bottom of the left menu and follow instructions to download and install the DMG for Google Drive.

Launch Google Drive from your Application Menu (or Launchpad on OS X Lion) and sign in using your Google account.

Next, launch a terminal and change your Desktop to use Google Drive instead as follows:

$ cd
$ mv Desktop/* Google\ Drive/
$ rm -r Desktop
$ ln -s Google\ Drive/ Desktop

Log out and log back in.

Now your Desktop should start syncing and showing all your files in Google Docs. Any new files or folders that you create in your Desktop from now on will be synced across all machines that have Google Drive set up.

Repeat the aforementioned instructions for all machines which you want to keep in sync and enjoy the ride!