Apr 222012

Sometimes I avoid learning new things because I’m lazy, pressed for time, or for some other reason couldn’t be bothered to figure them out.  I write a lot of tests these days, but I’ve been putting off figuring out how to use Mox because it was usually just as fast for me to roll my own solution and because the documentation seemed like it was written for folks who know what they are doing already and are just looking for the answer to the how question.  Let me explain Mox as I understand it and give some examples how to use it for testing applications that use web services or make remote http calls.

Let’s say you’ve got this Python Class that looks something like this:

"""Find locations."""
__author__ = 'bmichalski@gmail.com (Brian Michalski)'
import json
import urllib
class LocationFinder(object):
  """Find the geographic location of addresses."""
  def __init__(self, urlfetch):
    """Initialize a LocationFinder.
      urlfetch: Backend to use when fetching a URL.
        Should return a file-like object in response to the urlopen method.
    self.urlfetcher = urlfetch
  def find(self, address=''):
    """Find the latitude and longitude of an address.
      address:  String describing the location to lookup.
      Tuple with (latitude, longitude).
    base_url = 'https://maps.google.com/maps/api/geocode/json'
    params = urllib.urlencode({
      'sensor': 'false',
      'address': address
    url = '%s?%s' % (base_url, params)
    result = self.urlfetcher.urlopen(url)
    data = json.loads(result.read())
    location = data['results'][0]['geometry']['location']
    return (location['lat'], location['lng'])

The code is pretty simple, you can run it using something as simple as:

finder = LocationFinder(urllib)
print finder.find('1600 Amphitheatre Parkway, Mountain View, CA')

What’s important is that LocationFinder takes urllib as an argument. This is a kind of poor example because urllib isn’t another class that really needs mocking, but if you were developing on AppEngine or other environments where outbound connections weren’t as straight forward you could pass in the instance of your outbound connection library.

For demonstrative purposes, let’s pretend one of a few things is happening. 1. We can’t get an outbound internet connection to actually test against Google. 2. Google is too slow to test against. or 3. The service we’re testing against requires a complicated authentication handshake beforehand. None of these three cases are actually at play here on my laptop, but you could imagine wanting to isolate your testing from Google in the event that service goes down or is temporarily unavailable to you.

Mox to the rescue. Using Mox, we can make a fake urllib which, by default, doesn’t know anything about the existing urllib. Since we only call the urlopen function and don’t care about any other externals, all we have to do is define that method on our fake urllib and tell it what to return when it’s called. I find the syntax a bit strange, but to define the method you just call it and pass it the expected values (or matchers to broadly match your expected values) and then add .AndReturn(return value here) to wire up it’s return. When urllib.urlopen is called with the parameters you’ve specified it will return the return value you’ve stored otherwise you’ll get an error saying that the expected parameters don’t match what it’s actually being called with or the expected return doesn’t match the actual return (putting the the return from a void into a variable for example). Speaking of examples, here’s how I could quickly test the code above:

"""Testing the LocationFinder."""
__author__ = 'bmichalski@gmail.com (Brian Michalski)'
import location_finder
import mox
import StringIO
import urllib
import unittest
class TestLocationFinder(unittest.TestCase):
  def setUp(self):
    self.mox = mox.Mox()
  def tearDown(self):
  def testFinder(self):
    fetch_backend = self.mox.CreateMock(urllib)
    fake_data = StringIO.StringIO((
    finder = location_finder.LocationFinder(fetch_backend)
    result = finder.find('1600 Amphitheatre Parkway, Mountain View, CA')
    self.assertEqual(result[0], 37.42114440)
if __name__ == '__main__':

Since urlopen returns a file-like object I use a StringIO object and hardcode some output. I could have saved the result verbatim from Google in a file and put that somewhere to return. In summary, testFinder is broken down into two halves, the first have creates a fake urllib and tells it how to work responding to the one method and the second half loads the LocationFinder using the fake backend and verifies the calls worked as expected.

My old fashioned technique would have just been to write something like:

class mockurllib(object):
  def urlopen(url):
    return something

which isn’t too bad when you’re testing just 1 function like I am above, but if you’re testing different calls to different backends with different responses it can get a bit verbose and messy. I’m sure there’s room to improve my current understanding, maybe I’ll pick up some more handy testing tricks later.

The one thing I dislike about mox is the need to include urllib at all in the test (or import in Python’s case). I think there are ways to mock it out in a more generic fashion, but that feels like it might be getting sloppy. Since urllib is being imported it could still run a potentially slow initialization sequence, not applicable in this specific case but certainly something to watch out for.

Mar 132011

I found myself on a plane a few days ago and was hoping to do some work on a few of my Ruby on Rails projects, primarily some polishing of the the Community Mapping project I’m launching later this week.  Here are a few tips / tricks to developing in Ruby on Rails without internet access:

  1. Clone / Pull / Update the code for your application locally.  I do almost all of my development on remote servers so it’s rare I have the latest of anything on my hard drive.  git clone / git pull is a must to make this happen.  If you don’t have your SCM tool installed (like git, svn, hg. etc) you need to do this ASAP.
  2. Bundle. Bundler helps maintain the dependencies in your applications plugins / libraries but to do that is usually needs to download libraries from the internet unless you have them installed locally.  If you’re short on time (i.e. waiting to board the airplane) I would run bundle install from the app that has the most libraries associated with it.  Bundler will reuse things that are already installed and if you’re lucky many of your applications share common libraries.  The more wifi time you have the more applications you should bundle before you try and do it offline.
  3. Try and find any useful wiki / documentation pages that aren’t generated from source code.  These pages are likely going to include examples of implementations and features not associated with a particularly function.  In my case, I know there is a wiki page on Github that describes a “best approach” to the problem I’m having right now, but I can’t get to that in the airplane.  I tend to have the most trouble with jQuery-based documentation… when ever I need to know the syntax for a function like $.ajax I just google it.  Not possible on an airplane.  Instead of waiting til I land to quickly fire up wifi before dashing to my connecting flight (that’s my current plan), I could have been smart and downloaded the documentation first.  http://www.jqapi.com/ or http://docs.jquery.com/Alternative_Resources may be worth exploring.
  4. Don’t worry about the framework / gem documentation, at least not the function-by-function style documentation that is generated automatically.  You can regenerate it on your own if you need to.  The Ruby on Rails documentation can be generated by running `rake doc:rails` from your application directory.  You’ll find the output in your apps doc/api directory.  If you need documentation for a gem your system might already have it.  Run `gem server` to start a server with information about your gems.  If the rdoc link isn’t working for the gem you’re interested in fear not, you generate it most of the time using `gem rdoc gemname`.  I needed the documentation for CanCan so I ran `gem rdoc cancan` and presto, the server was able to point me to some moderately useful information.
  5. Hack it if you have to.  If you forget step 3 and step 4 didn’t help, you can probably write some really sloppy code to do what you’re trying to.  If you can’t (or don’t want to) write some junky code perhaps you can simulate it.  For example, I don’t know the exact call I need to figure out if I want to give the user access or not, but knowing that it will return true or false lets me very easily simulate what will happen in the rest of my application.
  6. Write lots of comments.  You’re flying in an airplane.  For all you know the baby crying behind you could be effecting your normal coding practices, it’s not going to be very easy to get back in the same mindset again so you should document what you’re doing extensively.  This applies extra if you have to use step 5.

Best of luck with your offline development, and safe travels.