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
Joe Moore

Desert 0.5.2 Released

Joe Moore
Thursday, August 27, 2009

Desert 0.5.2 focuses on speed improvements and bug bixes.

Pivotal Tracker Stories:

  • “Fix mailer templates — very slow with Desert”: ActionMailer::Base.view_paths are now cached. This speeds up ActionMailer tests/specs.
  • “Plugin schema migrations should successfully convert from the ‘old’ scheme to the ‘new’ scheme”: Pulled cauta/desert at master and fixed specs.
  • “Add sweepers to Desert’s load path”: Pulled willcodeforfoo/desert at master and fixed specs.
  • “Specs should handle Rails version incompatibilities”
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Testing Desert Plugins in Isolation

Joe Moore
Saturday, August 22, 2009

At Pivotal, some of our client projects use plugins from our home-grown social networking platform and rely on Desert to tie them all together. To test this package of plugins we created a project that contains all of our Desert plugins and wrote some rake tasks that run all of their tests. Great, right?

Mostly. We want to ensure that our plugins have the absolute minimum dependencies to function. Let’s pretend we have an UserAuth plugin and a SocialPivots plugin, where UserAuth has no dependencies, but SocialPivots depends on UserAuth. We would like to test these the to plugins in isolation. But, with Desert doing it’s job so well, our UserAuth plugin could have a dependency on the SocialPivots plugins’ models or tables and we would never know it. Everything from SocialPivots is mixed-in and loaded into memory, and all of its migrations have executed, at the time we are running UserAuth’s tests.

What we need is a way to tell Desert to load only the plugin under test, plus its dependencies listed in init.rb. Hacking Desert and Rails to allow us to specify which plugins to load turned out to be pretty easy. Check it out (full gist here):

Here, we override plugin loading:

# lib/plugin_dependency_limiter.rb
class Rails::Initializer
  def load_plugins
    # Only load the plugin under test
    Rails::Plugin.new("vendor/plugins/#{ENV['PLUGIN']}").load(self)
  end

  def add_plugin_load_paths
    # Do nothing.  We'll handle plugin loading ourselves.
  end
end

We might have many plugins in vendor/plugins but we only want to test our Desert plugins. We list them in config/plugins/plugins_to_test.yml and keep track of them here:

# also in lib/plugin_dependency_limiter.rb
class Rails::Plugin
  def self.plugins_of_interest
    # Keep track of the Desert plugins we care about
    @of_interest ||= YAML.load_file(RAILS_ROOT + "/config/plugins/plugins_to_test.yml").collect
  end

  def self.tracked_plugins
    @tracked_plugins ||= []
  end

  def require_plugin_with_plugin_tracking(plugin_name)
    self.class.tracked_plugins << plugin_name if self.class.plugins_of_interest.include?(plugin_name)
    require_plugin_without_plugin_tracking(plugin_name)
  end
  alias_method_chain :require_plugin, :plugin_tracking
end

Once you can control which plugins are loaded you can expand this to dictate which routes and migrations should be run:

Routes:

# config/routes.rb
ActionController::Routing::Routes.draw do |map|
  if ENV['PLUGIN']
    Rails::Plugin.tracked_plugins.each do |plugin|
      map.routes_from_plugin(plugin)
    end
    map.routes_from_plugin(ENV['PLUGIN'])
  end
end

Migrations:

# db/migration/001_migrate_desert_plugins.rb
class MigrateDesertPlugins < ActiveRecord::Migration
  def self.up
    Rails::Plugin.tracked_plugins.each do |plugin|
      migrate_plugin(plugin, nil)
    end
    migrate_plugin(ENV['PLUGIN'], nil)
  end

  def self.down
    raise ActiveRecord::IrreversibleMigration
  end
end

Let’s run some tests! Though we don’t provide the rake task here, it runs db:drop db:create db:migrate db:test:prepare before running the plugin tests.

First, the UserAuth plugin that has no dependencies:

$ rake testspec:plugins PLUGIN=user_auth
(in /Users/pivotal/workspace/desert_plugins)
==  MigrateDesertPlugins: migrating ===========================================
==  CreateUserAuthStuff: migrating ====================================================
-- create_table(:user_auth_stuff)
   -> 0.0023s
==  CreateUserAuthStuff: migrated (0.0026s) ===========================================

==  MigrateDesertPlugins: migrated (0.0076s) ==================================

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -I"lib:test" "/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb"
....................................

Finished in 0.494227 seconds

36 examples, 0 failures

Now the SocialPivots Plugin, which relies on UserAuth:

$ rake testspec:plugins PLUGIN=social_pivots
(in /Users/pivotal/workspace/desert_plugins)
==  MigrateDesertPlugins: migrating ===========================================
# Look, the migrations from UserAuth!
# Look, the migrations from UserAuth!
# Look, the migrations from UserAuth!
==  CreateUserAuthStuff: migrating ====================================================
-- create_table(:user_auth_stuff)
   -> 0.0201s
==  CreateUserAuthStuff: migrated (0.0204s) ===========================================

==  CreateSocialPivotStuff: migrating ==============================================
-- create_table(:social_pivot_stuff)
   -> 0.0034s
==  CreateSocialPivotStuff: migrated (0.0036s) =====================================

==  MigrateDesertPlugins: migrated (0.0332s) ==================================

/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -I"lib:test" "/Library/Ruby/Gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb"
........................................................................

Finished in 1.381141 seconds

72 examples, 0 failures

I hope this code makes testing Desert plugins easier. Thanks to Pivots Adam and Edward for pairing with me through these solutions.

  • 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

Topics

  • agile (778)
  • rails (113)
  • testing (87)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (54)
  • techtalk (44)
  • rspec (38)
  • activerecord (29)
  • productivity (29)
  • gogaruco (29)
  • ironblogger (29)
  • git (28)
  • nyc (27)
  • rubymine (25)
  • mobile (22)
  • bloggerdome (21)
  • cucumber (20)
  • process (19)
  • pivotal tracker (19)
  • 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)
  • tdd (13)
  • selenium (12)
  • css (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to desert Feed
  • 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 >