Desert Fixes

Desert has been upgraded to work with Rails 2, solving problems with ActionMailer templates and Rails load paths.

Nested Describes in RSpec

A reminder: RSpec supports nested describe blocks. This can be useful for sharing setup and also for organization (one describe per method being tested, with multiple it blocks). Some people reported that there are some issues when using nested describe blocks with fixture scenarios. There was also a report of some flakiness around a single it block being run more than once.

Yay NetBeans

One of our projects has reported that they have been using NetBeans and are happy with it.

By default, Ajax.Updater will send a POST request to whatever URL is specified. That’s fine, and it prevents certain browser caching issues, but it won’t play well with Rails’ resource routes. Rails will map POST requests to the create controller action, which is not always desirable.

For example, let’s say we have an Ajax.Updater that refreshes a list of posts (GET /posts). Unfortunately, the request that is created by default will be different (POST /posts). You can force the GET method, like so

One problem remains, however. If the URL for the remote_function and the URL for the full (html) version of the resource are the same, as they probably ought to be, and if the Ajax call is a GET request, Firefox will cache the data returned by the remote_function call as the most recent version of the page /posts. When a user navigates away from /posts, and subsequently decides to return to /posts by hitting the back button, the remote_function data will be displayed (as opposed to the full html version of the page). That’s not very user-friendly.

To avoid this, one will need to set the appropriate header:

headers["Cache-Control"] = "no-store"

Interestingly enough, IE7 appears to deal with this situation correctly.

For many projects, this may be overkill. It is useful at Pivotal, though, where many various projects may be on different rails versions, but still want to use the latest common core libraries (and monkey patches) without having to upgrade Rails for their app.

There are numerous other related topics for discussion in this area, such as the power of versions or the wisdom of freezing, but I’ll save those for future posts. Even if you do freeze the trunk of Rails/plugins/gems, since the version is included in the source, this approach should work barring any conflicts with trunk changes since the last release.

Interesting Things

IE Fun: when building a DOM tree by hand (such as in Javascript), don’t forget to add <tbody> tags in your tables! These are required in Internet Explorer 6 and 7. The tables will not appear without them.

As geeks we like science experiments. As San Franciscans (mostly) we like anything novel, particularly if it’s organic, healthy, and foreign. So, a few months ago, after realizing our employer couldn’t afford our kombucha (fermented green or black tea) habit, we started brewing our own:

Now we’ve got more “mushrooms” (actually a bacteria and yeast symbiote called a scoby). These are the “strata” in the jars above. So, if ever you’ve ever wanted to make your own kombucha (it’s easy and tasty) , or if you’ve never heard of it and the idea of a beverage somewhere between ice tea, lemonade, and beer sounds tasty, come by or paypal me postage and I’ll give you a scoby.

Interesting Things

Rails tweaking: test startup times can be very slow due to Fixture loading, especially for HABTM. We monkey-patched the Fixture-loading code that handles HABTM, resulting in a test suite performance increase of 300% for one project! We’ll submit the patch to Rails core and keep you posted.

Ask for Help

“Does anyone know an efficient algorithm for detecting overlapping rectangles made of up latitudes/longitudes… in SQL?”
Or, in other words, detecting if two selections on a map overlap. The latitudes and longitudes are stored in a MySQL database. MySQL has some GIS features that we’ll explore.

I just had to quit Firefox for the umpteenth time because it was taking up 25% of my CPU and 1.5 GB of virtual memory. It makes my lap hot and burns down my battery and activates my fan and slows down my click response time. I have no idea if it was Gmail or Google Reader or one of the other JS-heavy apps and frankly, I’m sick of guessing.

Let’s face it: the browser is an operating system. It’s time it started acting like one.

Here’s what I want my next browser to do:

Put every tab’s JS in its own thread or process space

Pause that process when I switch tabs (i.e. I don’t want Gmail to check for incoming mail or chats unless it’s in a visible tab)

Show me a list of the CPU and memory usage of each JS slice like “top” or the Windows process monitor and allow me to kill them without restarting my browser

Same goes for Flash but even moreso: I want every seizure-inducing, focus-stealing, ringtone-blaring flash app to be individually killable and blockable

Show me the content of the page now even if some stupid ad or web bug or analytics script on a different server is slow to load

And for Santa’s sake when I tell you to quit don’t swap in every little JS object and free it individually. Throw the whole heap away and quit, damn your eyes!

I’m pleased to introduce a new Test Double (or mock) framework named RR, which is short for Double Ruby.

Why a Double framework and not a Mock framework?

A mock is a type of test double. Since RR supports mocks, stubs, and proxies, it makes sense to refer to RR as a double framework. The proxy is a new usage pattern that I will introduce later in this article, and in more detail in future articles.

Unfortunately, the terminology over doubles has been contradictory depending on the framework. RR’s terminology tries to be as faithful as possible to Gerald Meszaros’ definition of test doubles. You can read more about test doubles in XUnit Test Patterns and Martin Fowler’s article, Mocks aren’t Stubs. Regretfully, this does mean that RR will have slightly different terminology than other double frameworks.

How does RR compare to other Mock frameworks?

Most double frameworks focus mainly on mocks (hence the categorization “mock framework”). RR’s focus is on enabling more double test patterns in a terse and readable syntax.

RR also does not have dedicated mock objects. It primarily uses the technique called ‘double injection’. Names that other frameworks use are ‘stub injection’, ‘mock object injection’, ‘partial mocking’, or ‘stubbing’. The term I’ll use for this is a double injection, since one or many doubles are being injected into an object’s method.

I’ll use trivial Rails examples to highlight the syntactical differences between RR, Mocha, Rspec’s mocks, and Flexmock. They may or may not be appropriate situations for mocks. The right situations for mocks is an entirely different discussion.

If there is better way to do any of the examples, please post a comment and I will gladly replace it.

Mocks

Here are the ways to mock the User.find method. The expectation is the User class object will receive a call to #find with the argument ’99’ once and will return the object represented by the variable user.

RR

mock(User).find('99') { user }

Mocha

User.expects(:find).with('99').returns(user)

spec/mocks

User.should_receive(:find).with('99').and_return(user)

Flexmock

flexstub(User).should_receive(:find).with('99').and_return(user).once

Stubs

Here are the ways to stub the User.find method. When the User class object receives a call to find with the argument ’99’ it will return user1. When User receives find with any other arg, it returns user2.

Flexmock

Proxy

A proxy used with a mock or stub causes the real method to be called. Expectations can be placed on the invocation and the return value can be intercepted. The main rationales are test clarity and you can ensure that the methods are being called correctly, even after you refactor your code. I will delve more into proxies and their usage patterns in my next article.

Mock Proxy

The following examples set an expectation that User.find(’99’) will be called once. The actual user is returned.

RR

mock.proxy(User).find('99')

Mocha

You cannot implement this in Mocha. You can do an approximation in this situation however. This technique is not always the solution you need, though.

Flexmock

instance_of

instance_of is method sugar than allows you to mock or stub instances of a particular class. The following examples mock instances of User to expect valid? with no arguments to be called once and return false.

Flexmock

More to come

This concludes the introduction to RR. RR enables some techniques, like proxying, that will make your tests clearer and less brittle. In the next article I will describe into patterns and techniques that will make mocks a more feasible tool for more situations.