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
Pivotal Labs

Standup 3/26/2009: Testing Request Headers When Request Object Is Frozen

Pivotal Labs
Thursday, March 26, 2009

Ask for Help

“How do you test request headers? The request object is frozen…”

The team is using rspec to test an OAuth implementation and needs better access to the request object.

  • Possibly modify the request environment prior to running the test -or-
  • Instantiate a new, non-frozen request object.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

DRY, Targeted, and Reusable Testing of ActiveRecord Extensions

Joe Moore
Wednesday, March 18, 2009

At Pivotal, we are passionate about test driven development, keeping things DRY, and writing readable and understandable code. Satisfying all of these desires can be challenging, especially when writing test code. In particular, ActiveRecord extensions present several challenges: which models using an extension should we test? How do we both test our extension in isolation while also testing all model’s usage of that extension? Is it even worth it?

The answer is yes, it is worth it, and it’s also fairly easy, readable, understandable, and DRY. I will present both a common problem and a solution, using a cumulation of technologies and techniques from multiple Pivotal projects, in particular using acts_as_fu to create laser-targeted, isolated, and disposable ActiveRecord models for testing extensions and RSpec shared behaviors to minimize the amount of duplicated test code.

Often we find common patterns in ActiveRecord models and we wish to share that functionality by mixing in a module of shared code, or even mixing that module in to ActiveRecord::Base itself. How should we go about testing these ActiveRecord extensions? Not only do we want to test the extension, but also test that models using that extension are doing so properly. We’ve blogged about dynamically creating ActiveRecords to test extensions in the past, but Pivot Pat Nakajima’s acts_as_fu plugin is a far better tool for this.

The Setup

Let’s say we have three models: Pivotal, Lab, and Pivot. Both a Pivot and a Lab belongs_to Pivotal, have a name, nickname, some common validation, etc:

# app/models/pivotal.rb
class Pivotal < ActiveRecord::Base
end

# app/models/lab.rb
class Lab < ActiveRecord::Base
  RANDOM_NICKNAMES = ["New Hotness", "LOL-Cat Factory", "Tweet Machine"]
  belongs_to :pivotal
  validates_presence_of :name

  def nickname
    "#{self.name}, 'The #{RANDOM_NICKNAMES[rand(RANDOM_NICKNAMES.length)]}'"
  end
end

# app/models/pivot.rb
class Pivot < ActiveRecord::Base
  RANDOM_NICKNAMES = ["New Hotness", "LOL-Cat Factory", "Tweet Machine"]
  belongs_to :pivotal
  validates_presence_of :name

  def nickname
    "#{self.name}, 'The #{RANDOM_NICKNAMES[rand(RANDOM_NICKNAMES.length)]}'"
  end
end

The specs for Lab and Pivot might look like the following:

# spec/models/lab_spec.rb
describe Lab do
  before(:each) do
    @lab = Lab.new
  end

  it "should require name" do
    @lab.should have(1).errors_on(:name)
    @lab.name = 'Stealth Startups'
    @lab.should have(0).errors_on(:name)
  end

  it "should generate a random nickname" do
    @lab.name = 'Stealth Starup'
    @lab.nickname.should_not be_blank
    @lab.nickname.should include(@lab.name + ", 'The ")
  end

  it "should belong to Pivotal" do
    @lab.should respond_to(:pivotal)
    @lab.should respond_to(:pivotal=)
    @lab.should respond_to(:pivotal_id)
    @lab.should respond_to(:pivotal_id=)
  end
end

# spec/models/pivot_spec.rb
describe Pivot do
  before do
    @pivot = Pivot.new
  end

  it "should require name" do
    @pivot.should have(1).errors_on(:name)
    @pivot.name = 'Joe Moore'
    @pivot.should have(0).errors_on(:name)
  end

  it "should generate a random nickname" do
    @pivot.name = 'Joe Moore'
    @pivot.nickname.should_not be_blank
    @pivot.nickname.should include(@pivot.name + ", 'The ")
  end

  it "should belong to Pivotal" do
    @pivot.should respond_to(:pivotal)
    @pivot.should respond_to(:pivotal=)
    @pivot.should respond_to(:pivotal_id)
    @lab.should respond_to(:pivotal_id)
  end
end

DRYing Up the Models

Yuck, look at all that duplication! Let’s start eliminating it by pulling the common model code into an ActiveRecord extension named belongs_to_pivotal:

# lib/belongs_to_pivotal.rb
module BelongsToPivotal
  RANDOM_NICKNAMES = ["New Hotness", "LOL-Cat Factory", "Tweet Machine"]
  module ClassMethods
    def belongs_to_pivotal
      belongs_to :pivotal
      validates_presence_of :name

      instance_eval do
        include BelongsToPivotalInstanceMethods
      end
    end
  end

  module BelongsToPivotalInstanceMethods
    def nickname
      "#{self.name}, 'The #{BelongsToPivotal::RANDOM_NICKNAMES[rand(BelongsToPivotal::RANDOM_NICKNAMES.length)]}'"
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

Now our Models look like this:

# app/models/lab.rb
class Lab < ActiveRecord::Base
  belongs_to_pivotal
end

# app/models/pivot.rb
class Pivot < ActiveRecord::Base
  belongs_to_pivotal
end

You’ll need to add “ActiveRecord::Base.send :include, BelongsToPivotal” to config/initializers/new_rails_defaults.rb or some other initializer.

Testing the Extension with acts_as_fu

The models are looking better, but what about the specs? In the “old days” I would create a spec named belongs_to_pivotal_spec.rb and use one of the two Models in that spec. But, when you do that, you get all the the “baggage” from that Model, such as any other methods, associations, inherited methods and properties, etc. Let’s use acts_as_fu to write a spec that tests BelongsToPivotal in isolation.

# spec/lib/belongs_to_pivotal_spec.rb
describe BelongsToPivotal do
  before(:all) do
    # Using acts_as_fu to create a model specifically for our extension
    build_model :belongs_to_pivotal_models do
      # we will need these columns in the database
      string :name
      integer :pivotal_id

      # Call our extension here
      belongs_to_pivotal
    end
  end

  before(:each) do
    @pivotal_model = BelongsToPivotalModel.new
  end

  # Look, it's all of the model specs!
  it "should require name" do
    @pivotal_model.should have(1).errors_on(:name)
    @pivotal_model.name = 'Pivotal Model'
    @pivotal_model.should have(0).errors_on(:name)
  end

  it "should generate a random nickname" do
    @pivotal_model.name = 'Pivotal Model'
    @pivotal_model.nickname.should_not be_blank
    @pivotal_model.nickname.should include(@pivotal_model.name + ", 'The ")
  end

  it "should belong to Pivotal" do
    @pivotal_model.should respond_to(:pivotal)
    @pivotal_model.should respond_to(:pivotal=)
    @pivotal_model.should respond_to(:pivotal_id)
    @pivotal_model.should respond_to(:pivotal_id=)
  end
end

Now that our ActiveRecord extension is well tested, how do we make sure that our two models are actually using it? One technique is to check that each model responds to the specific methods added by our extension:

#spec/models/lab_spec.rb
describe Lab do
  ...
  it "should belong_to_pivotal" do
    @lab.should respond_to(:pivotal)
    @lab.should respond_to(:pivotal=)
    @lab.should respond_to(:pivotal_id)
    @lab.should respond_to(:pivotal_id=)
    @lab.should respond_to(:name)
    @lab.should respond_to(:name=)
    @lab.should respond_to(:nickname)
  end
  ...

This does not feel very satisfying. We are duplicating some of the tests from belongs_to_pivotal_spec.rb and not verifying that we are getting the validations. A crazy coincidence could result in these methods all being defined without actually using our extension.

Another technique, though some would call it a hack, is to provide a hook within the extension itself so we can check for it later:

# lib/belongs_to_pivotal.rb
module BelongsToPivotal
  ...
  module ClassMethods
    ...
    # We can check this to see if a model uses this extension
    def belongs_to_pivotal?
      self.included_modules.include?(BelongsToPivotalInstanceMethods)
    end
  end
  ...
end

Let’s update belongs_to_pivotal_spec.rb to test this method:

# spec/lib/belongs_to_pivotal_spec.rb
describe BelongsToPivotal do
  before(:all) do
    # Using acts_as_fu to create a model specifically for our extension
    build_model :belongs_to_pivotal_models do
      ...
    end

    # Create a model that does not use our extension
    build_model :never_belongs_to_pivotal_models do
      # do nothing
    end
  end
  ...
  it "should know if it belongs_to_pivotal" do
    BelongsToPivotalModel.belongs_to_pivotal?.should be_true
    NeverBelongsToPivotalModel.belongs_to_pivotal?.should be_false
  end
end

#spec/models/lab_spec.rb
describe Lab do
  it "should belong_to_pivotal" do
    Lab.belongs_to_pivotal?.should be_true
  end
end

#spec/models/pivot_spec.rb
describe Pivot do
  it "should belong to Pivotal" do
    Pivot.belongs_to_pivotal?.should be_true
  end
end

Using RSpec Shared Behaviors

How much further can we go? Notice that our two Model specs are 5 whole lines long! Unacceptable! All kidding aside, we can DRY this up just a bit more by using RSpec’s shared behaviors.

In spec/spec_helper.rb

# spec/spec_helper.rb
describe 'it belongs to pivotal', :shared => true do
  it "should belongs_to_pivotal" do
    described_class.belongs_to_pivotal?.should be_true
  end
end

Now we can use this shared behavior in our specs:

#spec/models/lab_spec.rb
describe Lab do
  it_should_behave_like "it belongs to pivotal"
end

#spec/models/pivot_spec.rb
describe Pivot do
  it_should_behave_like "it belongs to pivotal"
end

I hope that these techniques are helpful. Feel free to post your own!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ryan Dy

Standup 02/18/2009

Ryan Dy
Thursday, February 19, 2009

We’re looking for more information about Taste or other similar kinds of suggestion engines. What kind of experiences have people had integrating these tools into Rails applications. Are there other useful engines worth looking at?

Direct uploads to Amazon S3 service can be serviced by EC2 servers; however, there might be more direct ways of doings this with S3.

Newer versions of RubyMine have been reported having problems running the gem version of rspec but a solutions has been found. The problem comes from the way gems are specified in RubyMine. You need to add the rspec gem you are using to the Project Structure >> Ruby SDK and Gems.

Using Desert and exception notifier can cause some slow startup times. If you are seeing this problem try moving exception notifier’s sender_address inside your environment’s post-load block.

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

Standup 11/17/2008: Google Chrome Gotchas

Joe Moore
Monday, November 17, 2008

Interesting Things

  • We recently updated Pivotal Tracker‘s extensive JSUnit test suite to be compatible with the Google Chrome browser. Check out the extensive Notes on Google Chrome Compatiblity post by Pivot Chad.

  • ActiveScaffold + Rails 2.2 = BOOM. ActiveScaffold will work with Rails 2.1 if you get the version from github. Read about it.

  • Rails 2.2 + Rspec 1.11 = FAIL
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 11/10/2008: Memory profiling tools for Ruby

Pivotal Labs
Thursday, November 13, 2008

Interesting Things

  • IntelliJ IDEA 8 was officially released over the weekend.

Ask for Help

“We’re having an issue with a long running Ruby process consuming too much memory and failing. What tools are available for finding and patching Ruby memory leaks?”

Several tools were suggested:

  • Valgrind – Considered very powerful but difficult to use. “It will do what you want if you can figure out how to properly ask it to do so.”
  • BleakHouse – Ruby specific leak detection. It’s available as a gem called “bleak_house”
  • Leaks – This is native to OSX. The Google Web Toolkit uses this for leak detection.
  • DTrace – Also a native OSX tool. There was a RailsConf presentation on Everyday DTrace on OSX.

“Rake will often silently ‘fail’ when running RSpec. It will not blow up but rather silently quits in the middle of the suite. This seems to happen intermittently, usually on the first run of our test suite. If we run the suite again, it works.”

It was suggested that this might be a Rake version issue since there have been other test suite problems with Rake 0.8.3. Though, this particular type of problem was not identical to previous Rake versioning issues and may be something altogether different.

Keep reading for a more detailed description of this weird RSpec + Rake issue.

More on the RSpec + Rake issue:

“It always manages to go through the integration tests, but when it hits the main tests, it will randomly quit (without a failure or error message) before all the tests are complete. At this point it’ll give us a summary message (X tests run, X tests passed) as if no other tests exist. We’ve worked on the problem a little bit this morning and tried the following things, all without success: >1) upgraded to the latest version of rspec and rspec-rails (1.1.11)
2) downgraded from rake 0.8.3 to 0.8.1
3) tried running with rspec and rspec-rails gems only
4) tried running with rspec and rspec-rails plugins only.

We’ve tried it on another machine with similar results. Right now, I want to say it only happens when we’ve modified a file in the project, but that may be confirmation bias (we ran about 60 full rakes on one machine where we have not been mucking about in the codebase and it seems to have successfully run all of them).

There was one other mention of this online in this ticket: http://rspec.lighthouseapp.com/projects/5645/tickets/587-conflict-with-loadby-and-reverse#ticket-587-3, paraphrased below:

‘This was caused by an error in handling a certain mal-formed spec; it was causing rspec to exit silently in the middle of one spec file. As I would edit files, –loadby mtime would cause them to load in different orders, which would then run different #s of examples because it would hit the file, and then quit silently, in different places’

You can close this one, I’ll report another bug that’s appropriate for the silent-exit-without-exception problem.”

Anyways, at this point we’re out of ideas and are leaving the problem behind for now, but we’d love to fix it, as it makes testing somewhat unpredictable.”

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Sean Beckett

Standup 08/08/2008

Sean Beckett
Friday, August 8, 2008

Interesting Things

  • When using time zones in Rails 2.1, if you specify a zone, any datetime ActiveRecord attributes will be returned in that zone. E.g. if you specify Eastern Time, and then later request changed_at from an ActiveRecord, it will be returned in ET. However, if you ask for Time.now it is always returned in the local time zone, regardless of TZ settings. This isn’t necessarily bad or unexpected behavior, but it can lead to test failures if you save a time to an ActiveRecord, get it back, and then compare the values. One workaround is to use Time.zone.now, which will always respect the current time zone, although this doesn’t help with large existing codebases.

Ask for Help

“We’re FlexMock for some of our Test::Unit unit tests, and recently added some new tests; nothing that is exercising new parts of the code or creating new mocks. However, for some reason when we call previously existing mocks we get errors from Rspec. These are not exceptions or assertion failures, but full-stop errors as if there were a syntax error. Turns out Rspec reopens the Test::Unit::TestCase class and overwrites some behavior, although the cause of the errors remain entirely unclear. Anyone know why it would do that and how to prevent it in the future?”

A few people mumbled about Rspec magic, but actual help was not immediately forthcoming.

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

Taking a break from Rspec

Pivotal Labs
Friday, August 17, 2007

On my next new project, I think I’m going back to Test::Unit. I’ve lost patience with Rspec, and it seems like I’m not alone. But I’ve spent more time praising and lobbying for it than some of its other current detractors, so I feel an explanation of my reversal is in order. First, I’ll start off with what I like about Rspec, what got me to spend the time and energy switching to it to begin with.

I’ve always stressed that Rspec brings nothing fundamentally new to the table. For **’s sake, it’s a testing framework. Setup. Teardown. Mocking. There’s not a hell of a lot more to see. And that’s okay. What’s great about Rspec is that it lets you use real strings to label your test fixtures and cases. When I learned about it, I was struggling to name my test cases like sentences.

test_that_foo_does_bar_when_it_has_been_bazzed

Luckily, I’m a Dvorak typist so the underbar is close at hand, but not being able to freely compose descriptions of what I’m testing in a natural way can be very limiting. Writing helps me gather my thoughts, so the act of labelling the test can really help me. I take special pride in well written “it” strings. The describe block strings are also helpful, but not as big a deal to me. The clever assertion hacks are also cute and fun to write. The built in mocking is nice, but I’m not a big mockofascist, so I don’t get too excited about it.

And… that’s basically it. My appreciation for Rspec can be broken down as follows:

  • 70%: String test fixture and case names
  • 20%: .should be_valid etc
  • 10%: Mocking

Now, what sucks about Rspec snuck up on me. It boils down to 2 things:

  1. The framework is too f-ing complicated in its implementation.
  2. The framework is too presumptive about how I wish to organize my tests.

The second is an aesthetic gripe, which I insist is fair game, since the framework’s merits are mainly aesthetic anyways. The first is a much deeper issue. The semantics of a Test::Unit test fixture are straightforward. The test fixture is a class. It contains methods beginning with the word test. A seperate instance of the class is created, in which each test runs. A setup and teardown method run before and after each method invocation.

And that is more or less all I need to know. There’s some stuff I’d like to have, like a global setup / teardown akin to before(:all), but I can what’s there without really understanding anything about the framework’s implementation. It rides on the semantics of Ruby, and I understand Ruby because I use it every day.

Rspec, on the other hand, sends me down a labyrinthine path full of Ruby meta-object-protocol tricks to accomplish even the simplest of tasks. And trust me, I have a pretty solid grasp of the MOP. I love it, use it, and cringe when people refer to it as “magic” (it’s like assembly programmers calling a for loop magic or something). But there’s use and then there’s overuse. I myself can be accused of both. The eval family of methods is great. Therein lies the power to implement DSL’s with their own semantics that can diverge quite dramatically from Ruby. Therein also lies the problem. I like classes. I like inheritance. I like the object oriented model. So if software written in an object oriented language can get away with employing the basic object oriented tools to accomplish its mission, well then it by all means should. I don’t have time to dig around the BehaviorEvalModule, or whatever else I’ve looked at in myriad diversions to get Rspec to do something of medium hardness.

So I guess that’s it. Rspec does the basics really well. Ridiculously beautiful stuff. But venture beyond the limited tracks they’ve laid and you’re in the jungle. So anyway. I’m not ready to write the whole thing off yet, but I am going to revisit Test::Unit for a while, see if I might not give myself what I miss from Rspec atop its simpler implementation. We’ll see if I come back.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

doing it again and again

Alex Chaffee
Wednesday, August 8, 2007

Here’s an RSpec trick I discovered yesterday. Sometimes when you’re writing a test you want to loop over some precondition data. But if you do a loop inside your test (or spec), then all the cases will be subsumed in a single test method (or “it” block). This means you’ll have the following problems:

  • The first case to fail will cause the rest of the cases not to run. It’d be nice to see them all in a single test run.
  • You won’t take advantage of RSpec’s cool self-documenting trick of labeling each it block with a full description of the failure, and it’ll be harder to debug which case failed.
  • If you’re calling into Rails (e.g. in a View spec), you’ll only be able to call certain methods — especially render — once per test method. That means that you simply can’t use a loop inside a method to collapse redundant tests into a single block.

Ruby to the rescue! Instead of looping inside your it block, loop outside your it block.

require 'hpricot'

describe "navbar" do

  TABS = ["Home", "Articles", "Comments", "Preferences"]
  TABS.each do |tab|
    it "selects tab #{tab}" do
      assigns[:current_navbar_tab] = tab
      render "/shared/_navbar.mab"
      doc = Hpricot(response.body)
      doc.at("//li[@class=active]/a").inner_html.should == tab
    end
  end

end

When I mentioned this at standup, Nathan mentioned the eval module… maybe he or someone else can add more detail in a comment?

Note that this technique should be used sparingly. It’s kind of a test smell to have loops, but it’s useful in certain cases… In this example it’s actually different code rendering each separate tab. If we spent a bit more time and extracted a Tab object then we could possibly get away with just unit testing that class and trusting it to render properly on the page for each actual tab.

  • 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 rspec Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 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 >