You Say Tomato

I say Pomodoro!

After a significant amount of time and effort and the gracious help of several contributors, I’m proud to officially announce tomatoi.st.

For those in a hurry

tomatoi.st is a simple timer application that helps you implement the Pomodoro Technique. You should totally use it.

The Story

While pairing with Corey Grusden a few months ago, we decided to experiment with the Pomodoro Technique. We immediately found that it helped improve our productivity and fight off project fatigue. Plus it gave Corey some officially sanctioned time in which to deal with his digital logorrhea (SMS much?). Needless to say, we were hooked!

The immediate hurdle was that the software available for doing the timing was lackluster (fwiw, decent software has since been developed). In light of this, we spent the first few days working with a simple sleep 1500 &&
growlnotify
type solutioni which was inelegant at best. More importantly, it was missing an utterly essential piece of functionality: the ability to start a timer at my desk, go to the john, and check up on the time left in a break whilst on the throne!

And so, in pursuit of this lofty goal, a tomato was born.

What it does

tomatoi.st does very little, but we like to think it does it very well. ahem.

  1. Visit http://tomatoi.st
  2. Click the “Pomodoro” button
  3. Start a focused unit of work
  4. When you hear the “ding!”, click “Short Break”
  5. Take a break, go to the john, whatever
  6. Rinse and repeat

It is suggested that you do 4 sets of Pomodoros. The first three are followed by a short break, the last by a long one. tomatoi.st makes the assumption that you’ll be doing them in that order and handily suggests the next timer you should do by highlighting it’s button in green when the previous timer expires. Your current timer is highlighted in yellow while it’s underway and then red once it’s expired. Your timer history is tracked just below the big ticker.

Timers out of sync with reality (say, after a long lunch)? Click the “Reset” button to start fresh.

Want to come back to this set of timers tomorrow? Customize the name of the timer and then “rename” it so it’s easy to remember.

What it doesn’t do

It is not intended to be a full implementation of the Pomodoro Technique. Notably absent are things like task planning and daily review.

What’s next

Coming up promptly is integration with Fluid’s javascript API to provide neat things like Growl integration.

Want to help shape the face of what tomatoi.st will become? There are a number of ways you can help do so:

Given Due Consideration

Or: Just Say No to Cukes

As alluded to by veez, the undercurrent from some of us at Hashrocket has been decidedly anti-cucumber. Here’s my brief littany:

  • A well developed cucumber suite is invariably slow to run
  • For me, at least, it makes development feel slower (this is almost certainly perceptual, but that doesn’t mean it’s not actual as well)
  • The indirection makes debugging laborious
  • Matching plain english to executable code via regular expressions just feels wrong

All of these things (and more) have been excused for quite some time because Cucumber is thought of as a necessary tax. If you want to do full stack integration testing in Ruby… this is how it’s done.

Here’s the good news: it’s not the only way! Veez has gone over the basics in the post I linked above, so I won’t belabor the setup, though I will give you the latest version. Here are the relevant bits of my spec/spec_helper.rb:

  require 'webrat'
  require 'spec/support/integration'

  Webrat.configure do |config|
    config.mode = :rails
  end

  Spec::Runner.configure do |config|
    config.include(Webrat::Matchers, :type => [:integration])
  end

  class ActionController::Integration::Session; include Spec::Matchers; end

Interleaving the above into your existing spec_helper.rb is all you need to get going.

Let’s use this user story from a project I’m working on now as the backdrop to our discussion:

In order to dissolve a business relationship
As a user
I want to be able to remove a colleague

Scenario:
Given a user with colleagues
When I click a colleagues “Remove colleague” button
Then I should be on the colleagues list
And I should not see the colleague
And the colleague should not see me in their colleague list

Here’s how you might implement that using RSpec and Webrat:

  describe "User removes colleague" do
    before do
      login_as @user
      visit colleauges_path
      click_button 'Remove colleague'
    end

    it "redirects you to the colleagues list" do
      current_url.should == colleagues_url
    end

    it "removes them from my colleagues list" do
      response.body.should_not have_tag('#colleagues .colleague')
    end

    it "removes me from their colleague list" do
      logout
      login_as(@colleague)
      visit colleauges_path
      response.body.should_not have_tag('#colleagues .colleague')
    end
  end

That’s all well and good, but you may be saying to yourself (or your co-worker, or your poor, terrified cat): “But, that doesn’t capture the plain english user story! Darn it all to Bethesda!”. And you’re absolutely right… but how’s this strike you:

  Feature "User removes colleague" do
    Given do
      login_as @user
      visit colleagues_path
      click_button 'Remove colleague'
    end

    Scenario "removal" do
      When "I press remove" do
        Then "I should be on my collegues list" do
          current_url.should == colleagues_url
        end

        And "I should not see the user in my colleagues list" do
          response.body.should_not have_tag('#colleagues .colleague')
        end

        And "My colleague should not see me in their colleague list" do
          logout
          login_as @colleague
          visit colleagues_path
          response.body.should_not have_tag('#colleagues .colleague')
        end
      end
    end
  end

@l4rk and I came up with this clever bit of aliasing to get you where you want to go. Just add this at the bottom of your spec_helper.rb:

  module Spec::DSL::Main
    alias :Feature :describe
  end

  module Spec::Example::ExampleGroupMethods
    alias :Scenario :describe
    alias :When :describe
    alias :Given :before #TODO: make Given take :before or :after and :each or :all
    alias :Then :example
    alias :And :example
  end

The failing of this technique, for the time being, is the round-trip output:

User removes colleague removal I press remove

  • I should be on my collegues list
  • I should not see the user in my colleagues list
  • My colleague should not see me in their colleague list

But we’re already scheming up a way to improve that situation, so stay tuned as the story develops.

Twiki

While pairing with @wesgibbs on a project at hashrocket, we got in the habbit of ‘testing’ our migrations by doing the following:

    rake db:migrate db:migrate:redo db:test:prepare

At some point; frazzled and dealing with a migration that kept breaking while running the above, I uttered: “db-db-db”, which was subsequently flipped around to “bidi-bidi-bidi”. Now, as a proud (well, kinda) son of the 80’s, my mind went immediately to Pamela Hensley… and soon thereafter, to Twiki of Buck Rodgers and his perennial tag line.

And so the following shell script was born (Mac only, sorry windozers):

    twiki () {
      say -v Zarvox 'beedee-beedee-beedee'
      rake db:migrate && rake db:migrate:redo && rake db:test:prepare
    }

The speed and voice aren’t quite right, but the sheer cheese factor cracks me up on the regular, so I figured I’d spread the wealth 😉

Also of note: the Twiki throwback dance mix