Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Monthly Archives: December 2007

Pivotal Labs

Introducing RR

Pivotal Labs
Monday, December 31, 2007

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.

RR
stub(User).find('99') { user1 }
stub(User).find { user2 }
Mocha
User.stubs(:find).with(anything).returns(2)
User.stubs(:find).with('99').returns(1)
spec/mocks
users = {
  '99' => user1,
  'default' => user2
}
User.stub!(:find).and_return do |id|
  users[id] || users['default']
end
Flexmock
users = {
  '99' => user1,
  'default' => user2
}
flexstub(User).should_receive(:find).and_return do |id|
  users[id] || users['default']
end

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.

user = User.find('99')
User.expects(:find).with('99').returns(user)
spec/mocks
find_method = User.method(:find)
User.should_receive(:find).with('99').and_return(&find_method)
Flexmock
find_method = User.method(:find)
User.should_receive(:find).with('99').and_return(&find_method)

Stub Proxy

The following examples intercept the return value of User.find(’99′) and stub out valid? to return false.

RR
stub.proxy(User).find('99') do |user|
  stub(user).valid? {false}
  user
end
Mocha

Again, this is an approximation, since you cannot use proxies in Mocha.

user = User.find('99')
user.stubs(:valid?).returns(false)
User.stubs(:find).with('99').returns(user)
spec/mocks
find_method = User.method(:find)
User.stub!(:find).with('99').and_return do |id|
  user = find_method.call(id)
  user.stub!(:valid?).and_return(false)
  user
end
Flexmock
find_method = User.method(:find)
flexstub(User).should_receive(:find).with('99').and_return do |id|
  user = find_method.call(id)
  flexstub(user).should_receive(:valid?).and_return(false)
  user
end

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.

RR
mock.instance_of(User).valid? {false}
Mocha
User.any_instance.expects(:valid?).returns(false)
spec/mocks
new_method = User.method(:new)
User.stub!(:new).and_return do |*args|
  user = new_method.call(*args)
  user.should_receive(:valid?).and_return(false)
  user
end
Flexmock
new_method = User.method(:new)
flexstub(User).should_receive(:new).and_return do |*args|
  user = new_method.call(*args)
  flexmock(user).should_receive(:valid?).and_return(false)
  user
end

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.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 12/28/2007

Pivotal Labs
Friday, December 28, 2007

Interesting Things

  • Rails Bug: Test::Unit seems to be broken in Rails 2.0.2 when using multiple levels of test classes (i.e. inheritance). Trunk is fixed, so Rails 2.0.3 will be fine.
  • Chad wrote a small utility for checking/comparing Rails versions which wraps the version checking part of rubygems. This, of course, requires that your Rails project uses at least one gem… that’s a pretty good bet.

    The basic technique:

    have = Rails::VERSION::STRING
    requirement = '=1.99.1'
    Gem::Version::Requirement.new([requirement]).satisfied_by?(Gem::Version.new(have))
    
  • One pivot is having trouble finding a rogue puts statement in a gem somewhere. The suggestion comes a bit late in this case, but adding some breadcrumbs may help next time:

    puts "#{__FILE__}:#{__LINE__} find me!"
    

Ask for Help

  • Does anyone have details regarding Google Maps API developer permissions? Localhost-to-localhost requests work fine, but we need to test things between machines (actually, a virtual machine client and virtual machine host).
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Column Edit Mode in VI

Pivotal Labs
Thursday, December 27, 2007

I’ve found that typing in column mode to be very useful when using editors like IntelliJ or TextMate. VI also has a column edit mode, that is a little tricky to use.

To use it, press:

  • Ctrl + V to go into column mode
  • Select the columns and rows where you want to enter your text
  • Shift + i to go into insert mode in column mode
  • Type in the text you want to enter. Dont be discouraged by the fact that only the first row is changed.
  • Esc to apply your change (or alternately Ctrl+c)

You will now see your changed applied.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Alexisms

Alex Chaffee
Wednesday, December 26, 2007

Sayings I use, only some of which are actually originally attributable to me. Anyone with research on a saying’s provenance, feel free to comment. This page, unlike a normal blog entry, will be updated as needed with stuff I find myself saying with air quotes.

A comment is a lie waiting to happen.

“Legacy” means any program that people are actually using.

(Feathers: “Legacy” means “no tests.”)

If you try hard enough, you can make anything fail.

There’s no such thing as human error. (Only system error.)

If you pay attention to something, it gets better.

It’s always a people problem. (Jerry Weinberg)

You can see a lot by looking. (Yogi Berra)

Yogi wrote a book called “You Can Observe A Lot By Watching” but I prefer to think he was misquoting himself.

Language Log has a take on this quote: She was seeing at me

Object-Oriented Programming is like teenage sex: everyone says they’re doing it; few actually are; and those who are rarely know what they’re doing. (Anonymous, via Misko)

Here’s a simple test for whether you’re doing it right: Is your data in the same class as the methods accessing it? Oh, really? Check again.

Double negatives are not unconfusing.

Encapsulation means putting similar things together, and keeping dissimilar things apart.

Of course, the trick of design is knowing along what axes to group or differentiate items. One rule of thumb that has served me well since the days of Gamelan — when we were sorting dozens of incoming applets per day into categories — is:

Don’t look at the item and think, “What category does this item belong in? Look at the category and think, “If I were looking for items in this category, would I want to find this item?”

In other words, make your API fit the mindset of the user, not that of the provider.

Conway’s Law: “Any piece of software reflects the organizational structure that produced it.”

Or, “The structure of the code reflects the structure of the coders.”

Read the error message.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Scrum Diagram

Alex Chaffee
Wednesday, December 26, 2007

Good Scrum diagram. Suitable for XP too (replace “sprint” with “iteration” and “daily scrum” with “daily standup”).

Courtesy of Mountain Goat Software

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

bookmark_fu: drop-in Iconistan

Joe Moore
Saturday, December 22, 2007

We just implemented bookmark_fu on Pivots and the experience was very smooth, taking only a few minutes. We how have an “Iconistan” of social bookmarking chiclets for either remembering or promoting content on Digg, reddit, del.icio.us — almost 20 sites in all.



Install via the normal plugin install process (the -x installs it as an SVN:EXTERNAL):

#> ruby script/plugin install -x svn://rubyforge.org/var/svn/pivotalrb/bookmark_fu/trunk/bookmark_fu

I did have one issue — the script/plugin install script pulled all the code down but ultimately failed because we have multiple versions of Rails on our development machine (about 5); this seemed to confuse the install script. No problem, though: I ran the install.rb script manually:

#> script/runner vendor/plugins/bookmark_fu/install.rb
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 12/21/2007

Joe Moore
Saturday, December 22, 2007

Interesting Things

  • Josh read Coda Hale’s interesting blog post about test driving (or rather, RSpec driving) his rake tasks:

    I love RSpec, and lately I’ve been making the transition from test-friendly development to full-on spec-driven development… I was working on a project recently which boiled down to “run these tasks in this order,” which is a natural fit for Rake.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 12/20/2007

Joe Moore
Friday, December 21, 2007

Interesting Things

  • Video Lunch: Once in a while, you just want to see something cool. So on days when nothing else is going on, we show interesting videos during lunch, such as TED Talks or Videos from the Googleplex. Today, we’ll watch these:
    • TED Talks: Blaise Aguera y Arcas: Jaw-dropping Photosynth demo
    • TED Talks: Aubrey de Grey: Why we age and how we can avoid it
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 12/19/2007

Joe Moore
Wednesday, December 19, 2007

Interesting Things

  • Rails Bug: composed_of seems to be broken, at least in Rails 1.99. The :mappings parameter states that it can take an array of symbol-pairs, but symbols do not work — only strings work. Example:
    Does not work:
composed_of :name
            :class_name => Name
            :mapping => [
                [:first_name, :first], # :symbol, :symbol does not work!
                [:last_name,  :last]  # :symbol, :symbol does not work!
            ]

Works!

composed_of :name
            :class_name => Name
            :mapping => [
                ['first_name', 'first'], # 'string', 'string' works!
                ['last_name',  'last']  # 'string', 'string' works!
            ]
  • Ruby ain’t Java! A recent Java-convert ran into the following: when calling a private instance method, you must not indicate self.private_method, but instead call private_method. Example:
Class PrivateCaller
    def call_private_here
        puts private_method        #=> works!
        puts self.private_method  #=> self?  uh oh!
    end

    private

    def private_method
        '*** You Called? ***'
    end
end

>> priv = PrivateCaller.new
=> #<privatecaller:0x14ec39c>
>> priv.call_private_here
*** You Called? ***
NoMethodError: private method `private_method' called for #</privatecaller:0x14ec39c><privatecaller:0x14ec39c>
        from (irb):4:in `private_caller'
        from (irb):23
        from :0
</privatecaller:0x14ec39c>
  • TextMate’s Ruby on Rails bundle does not work correctly with Rails 2.0.
  • RubyGems 0.95 is not compatable with geminstaller, written and maintained by our own Chad Woolley. Chad and the Gems folks are already on the case.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 12/18/2007

Joe Moore
Tuesday, December 18, 2007

Ask for Help

  • “Please help feed the hungry of San Francisco.”

We helped! Our barrel is over flowing.

Food donation barrel overflowing

Food donation barrel overflowing

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (780)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (20)
  • cucumber (20)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to Community Feed
  1. 1
  2. 2
  3. 3
  4. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >