Capturing Output from PUTS in Ruby

When writing unit tests for my simplesem interpreter, one test in particular was problematic. In simplesem, the set write instruction prints output to the screen.

// place Hello World! on the 'write' buffer
set write, "Hello World!"

Internally, the interpreter is just passing the second parameter, “Hello World!”, to the puts method in Ruby. This makes it difficult to use traditional test/unit assertions to check that the simplesem instruction is working.

I eventually found two solutions for this. The first, suggested by David Stevenson at Pivotal Labs, is to use mocha to check that puts was called on the object.

require 'test/unit'
require 'rubygems'
require 'mocha'
 
class SimpleSemParserTest < Test::Unit::TestCase
 
  def test_set_stmt_write
    parser = SimpleSemParser.new
    parser.expects(:puts).with("Hello World!")
    parser.parse('set write, "Hello World!"').execute
  end
 
end

This solution is fine for most situations; Mocha will throw an exception if puts is not called. However in my case, it was unsuitable because puts was not being called on the SimpleSemParser object but instead on a Treetop syntax node that I did not easily have access to within the unit test.

I knew that if I could capture the output from the puts method into a variable I would be able write the test using a standard assert_equal. After some googling I discovered that this functionality is built into the ZenTest gem. After rewriting the test looked like this.

require 'test/zentest_assertions'
 
class SimpleSemParserTest < Test::Unit::TestCase
 
  def test_set_stmt_write
    out, err = util_capture do 
      parser = SimpleSemParser.new
      parser.parse('set write, "Hello World!"').execute
    end
 
    assert_equal "Hello World!\n", out.string
  end
 
end

This works great. However, should we decided that we do not want to use an external gem, with a little effort we can bypass ZenTest and implement util_capture ourselves.

Read more

Automate Updating Your Git Repositories

I have a half dozen TextMate bundles that I am grabbing the latest versions from GitHub instead of from the main TextMate subversion repository. For a long time I have been updating each of the bundles’ Git repositories by cd’ing into each directory and running git pull. Doing this over and over became silly and I was annoyed from doing all that typing.

Today, I finally wrote a basic bash script that automates updating each of the repositories. Sometimes it is surprising how simple an automated solution turns out to be.