Unit testing by simplifying the problem: memoization

I see unit testing as a way to test each possible snippet of functionality and route the code in question can take. With Ruby being such a dynamic language and allowing shortcuts to common problems, sometimes it can seem somewhat of a mystery, how to test these snippets of functionality.
Using Memoization as an example:


class MyClass
  def lazy_initialized_value
    @lazy_initialized_value ||= Expensive.request
  end
end

There are actually 3 separate snippets of functionality that need testing here, however it is not immediately obvious from the example. Lets be slightly more verbose about what is actually happening:


class MyClass
  def lazy_initialized_value
    @lazy_initialized_value = Expensive.request unless @lazy_initialized_value
    @lazy_initialized_value
  end
end

Now it is much easier to see the 3 steps the code should take:
* Store result of expensive request in instance variable
* Leave instance variable alone when it is already set
* Return the value of the instance variable
Now we have this information, our tests become (using Mocha to mock external methods):


class Expensive; end
module Tests::MyClass
  # lazy_initialized_value
  # ----------------------
  class LazyInitializedValueTest < Test::Unit::TestCase
    def test_should_respond
      assert_respond_to MyClass.new, :lazy_initialized_value
    end
    def test_should_store_result_of_expensive_request_in_instance_variable
      instance = MyClass.new
      Expensive.stubs(:request).with().returns('expensive value')
      instance.lazy_initialized_value
      assert_equal 'expensive value', instance.instance_variable_get('@lazy_initialized_value')
    end
    def test_should_return_value_of_instance_varable
      instance = MyClass.new
      instance.instance_variable_set '@lazy_initialized_value', 'the value'
      Expensive.stubs(:request)
      assert_equal 'the value', instance.lazy_initialized_value
    end
    def test_should_maintain_existing_instance_variable_value_when_already_set
      instance = MyClass.new
      instance.instance_variable_set '@lazy_initialized_value', 'existing value'
      Expensive.stubs(:request)
      instance.lazy_initialized_value
      assert_equal 'existing value', instance.instance_variable_get('@lazy_initialized_value')
    end
  end
end

Now we have these tests in place, we can go back and refractor the code ’til our heart’s content using all the tricks in the book but by simplifying the problem in the first place, it gives us a solid test suite and the confidence to make changes without breaking functionality.
If you were solving this problem test-first then you wouldn’t (but more likely, shouldn’t) have written the first example until re-factoring stage anyway, however when these shortcuts become engrained in your brain, it’s all too easy to forget what they are _actually_ doing.
So there we go, simplify the initial implementation, get a solid test suite in order, _then_ re-factor.

Stubbing case statements with Mocha

I was happily mocking away with Mocha, then I passed a stub to a case statement at which point I was a little flummoxed.
The Ruby documentation clearly states that the ‘when’ in a ‘case’ statement uses the ‘===’ method for comparing the subject so I couldn’t work out why something like the following wasn’t working:


# Code
class A; end
def foo(instance)
  case instance
    when A : 'an A instance'
    else 'not an A instance'
  end
end
# Test
a = stub_everything
a.stubs(:===).with(A).returns(true)
assert_equal 'an A instance', foo(a)

So I had a little play around in irb and found the following:


class A; end
a = A.new
a === A #=> false
A === a #=> true

This revealed that I was actually stubbing the wrong side of the operator, I changed this to the following and voila!


# Code
class A; end
def foo(instance)
  case instance
    when A : 'an A instance'
    else 'not an A instance'
  end
end
# Test
a = stub_everything
A.stubs(:===).with(a).returns(true)
assert_equal 'an A instance', foo(a)

Looks obvious now but certainly wasn’t at the time!

Git – setting up a remote repository and doing an initial push

There is a great deal of documentation and many posts on Git out there, so this is more of a note to self as I keep forgetting the steps needed to set up a remote repository and doing an initial “push”.
So, firstly setup the remote repository:


ssh git@example.com
mkdir my_project.git
cd my_project.git
git init --bare
git update-server-info # If planning to serve via HTTP
exit

On local machine:


cd my_project
git init
git add *
git commit -m "My initial commit message"
git remote add origin git@example.com:my_project.git
git push -u origin master

Done!
Team members can now clone and track the remote repository using the following:


git clone git@example.com:my_project.git
cd my_project

Bonus

To have your terminal prompt display what branch you are currently on in green, add the following to your ~/.bash_profile (I have my current directory displayed in cyan):


function git-branch-name {
  git symbolic-ref HEAD 2>/dev/null | cut -d"/" -f 3
}
function git-branch-prompt {
  local branch=`git-branch-name`
  if [ $branch ]; then printf " [%s]" $branch; fi
}
PS1="\u@\h \[\033[0;36m\]\W\[\033[0m\]\[\033[0;32m\]\$(git-branch-prompt)\[\033[0m\] \$ "

Testing private class methods in Ruby

I generally make a point of not unit testing private methods however in some circumstance I find it necessary to do so. One example of this is when a class method is to be documented in the API of a library, only for use when declaring a descendent class (the Rails validates_* macros could be private for example).
Testing of private instance methods has already been documented by Jay Fields, however testing private class methods requires a little more work:


class Class
  def publicize_private_class_methods
    saved_instance_methods = (class << self; private_instance_methods.sort; end)
    saved_instance_methods.each { |method| public_class_method method }
    yield self
  ensure
    saved_instance_methods.each { |method| private_class_method method }
  end
end

This allows you to do the following:


class Foo
  class << self
    private
    def foo
      'bar'
    end
  end
end
Foo.publicize_private_class_methods do |klass|
  assert_equal 'bar', klass.foo
end

The same would work for protected methods by changing all instances of the word ‘private’ with ‘protected’.
All this could probably be merged into the original method by Jay, however I will leave that as an exercise for the reader.