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

Using Jasmine to test CoffeeScript in a Rails 3.1 App

Mike Gehard
Wednesday, May 11, 2011

Lately I’ve had the opportunity to use Jasmine to test drive a whole bunch of Javascript and am loving it. If you haven’t had a chance to take Jasmine for a spin, I recommend you take some time to do so.

When I heard that Rails 3.1 was going to include CoffeeScript I decided to work to figure out how I could write both my production code as well as my specs in Coffeescript.

Using this gist as a guide, I came up with these detailed instructions:

Add Guard and Guard-Coffeescript to your Gemfile and run bundle.

Run guard init to create a Guardfile and edit it to contain the following:

guard 'coffeescript', :output => 'public/javascripts/compiled' do
  watch(/^app/assets/javascripts/(.*).coffee/)
end

guard 'coffeescript', :output => 'spec/javascripts/compiled' do
  watch(/^spec/javascripts/(.*).coffee/)
end

Edit your spec/javascripts/support/jasmine.yml to have at least the following entries:

src_dir: public/javascripts/compiled
src_files:
  - **/*.js

spec_dir: spec/javascripts/compiled
spec_files:
  - **/*_spec.js

Start up the Jasmine server using rake jasmine and point your browser to http://localhost:8888. You should see 0 specs, 0 failures. Since you have changed the location that Jasmine looks for spec files, you aren’t picking up the example Jasmine specs any longer.

Create a new spec file in spec/javascripts/math_spec.coffee with the following contents:

describe 'Math:', ->
  describe 'fib()', ->
    it 'should calculate the numbers correctly up to fib(16)', ->
      fib = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
      expect(Math.fib(i)).toEqual fib[i] for i in [0..16]

Refresh your browser, you should see one failing spec. Guard has compiled your .coffee file into a .js file that Jasmine will use.

Create a new implementation file in app/assets/javascripts/math.coffee with the following contents:

Math.fib = (n) ->
    s = 0
    return s if n == 0
    if n == 1
      s += 1
    else
      Math.fib(n - 1) + Math.fib(n - 2)

Refresh your Jasmine browser window and you should see 1 passing spec. Again, Guard has compiled your implementation file and Jasmine uses it to satisfy the spec.

At some point, it would be nice to figure out a way to run Jasmine specs directly from the .coffee files and against the implementation .coffee files without having to use Guard to compile them. With the above steps, you still have to check in the compiled files into source control so your tests can be run in the CI environment. If you miss one of the compiled specs or one of the compiled implementation files, your CI environment may report improper results.

If anyone has any ideas, I’d love to hear them.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Waiting for jQuery Ajax calls to finish in Cucumber

Mike Gehard
Tuesday, May 3, 2011

You may be asking yourself why you’d want to do this in the first place. Well here’s why I would want to do it.

We had some Webdriver based Cucumber tests that passed fine locally but kept failing on our CI box. Our CI box is a bit underpowered at the moment so I thought what might be happening is that our tests weren’t waiting long enough for the Ajaxy stuff to happen because the Ajax responses were taking a long time.

After some poking around in the source code of jQuery, I found the $.active property. This property keeps track of the number of active Ajax requests that are going on and I thought this might help us out.

What I came up with was this gist:

I added this step right after my Cucumber step that caused the Ajax call so that Cucumber would wait to move on until I knew that everything was done.

This step solved our CI failures and all was good in our test suite again.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Mocking Fog when using it with Carrierwave

Mike Gehard
Thursday, April 21, 2011

There is a new kid on the block when it comes to file attachments for Rails and it is called Carrierwave.

Carrierwave gives you the ability to easily store attachments on S3 using another great gem called Fog.

Uploading files to S3 is great for many reasons but it can slow down your testing environment because it takes a while to send stuff up to S3. The Carrierwave documentation tells you how to switch the storage location over to file storage during testing but that wasn’t enough for me. I wanted to use the same storage mechanism for dev, test and production so I sought out a way to do so.

I had heard about Fog’s ability to mock itself to pretend that it was interacting with S3 so I decided to see if I could get it working with Carrierwave. This allowed me to use the same storage mechanism in test mode without slowing my tests down waiting for images to go to S3.

After a bunch of tinkering and a message on the Fog mailing list(thanks for the quick response Wesley), this is what I came up with:

The key is that you have to tell the mocked Fog that an S3 bucket exists before it will let Carrierwave put an image there. I wasn’t doing this at first and Carrierwave kept showing me a 404 error from Fog.

Drop this in a file in your spec/support and/or features/support
directories and you will have your tests thinking they are sending things to S3 without actually sending them to S3.

Now I don’t have to mess around with having a bunch of test images laying around my hard drive and I can make sure I’m using the same storage mechanism across all environments without slowing my tests down.

Your mileage may vary but I’d love to hear how this works for people and if there are any limitations. I haven’t found any yet.

UPDATE:
Check out my guest post on the Engine Yard Blog for updated details:
http://www.engineyard.com/blog/2011/mocking-fog-when-using-it-with-carrierwave/

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Making sure you implement the ActiveModel interface fully

Mike Gehard
Friday, April 8, 2011

Rails 3 brings with it ActiveModel.

ActiveModel give you a way to make non-db backed models look like db backed models to your views and controllers. See this post for a good explanation of what using ActiveModel buys you.

ActiveModel gives you a great way to test that your class implements the minimum ActiveModel interface: ActiveModel::Lint::Tests

Check out this gist for the details for using these tests in RSpec:

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Using Firebug with WebDriver in Capybara/Cucumber – New and Improved

Mike Gehard
Monday, March 21, 2011

Forget the steps I published earlier…just install the capybara-firebug gem and away you go.

Thanks jfirebaugh!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Testing OmniAuth based login via Cucumber

Mike Gehard
Thursday, March 3, 2011

If you haven’t looked at OmniAuth for authentication with sites like Google, Github and Facebook, then you should take a look. It is pretty killer.

This morning we needed to write a Cucumber scenario to test that a user could log into the system using Google Apps.

We did a quick spike on getting OminAuth integrated, which was a super simple process, and poked around in the browser to make sure it was working OK.

Thanks to Jose Valim for providing some guidance, via the Devise test suite, on how to get this all up and running.

The basics can be found in this Gist:

I put that code in /features/support/omniauth.rb and then all I need to do is label any scenarios that need to deal with login with an @omniauth_test tag and we are all set.

As our features count grows, I could see us doing this before/after all Cucumber scenarios.

Note: You need to be using 0.2.0.beta5 of OmniAuth to get this to work. Earlier versions don’t have the testing functionality built in.

Also Note: This same functionality can be used in good, old RSpec integration tests or Steak tests as well.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Using Cucumber/Capybara with SauceLabs SauceOnDemand

Mike Gehard
Wednesday, March 2, 2011

SauceLabs is a cloud based way to test your site against different browsers.

Up until now, they only supported the older Selenium RC based tests.

For those of us using Capybara, we were out of luck because Capybara uses Webdriver.

Well that just changed, they now support Webdriver. Check out the instructions on how to get is set up here.

The one thing that I disagree with in that post is setting the default Capybara driver to :sauce (Capybara.default_driver = :sauce). This seems a little heavy handed to me since I may not want to run all of my scenarios through the Sauce driver.

Upon further review of the source code, it looks like after installing the sauce gem, they redirect any scenarios tagged with @selenium to the Sauce driver. I like this better so if you don’t want to switch over all of your scenarios over to Sauce, you can just ignore the line mentioned above and simply tag the scenarios you want to run on Sauce with @selenium.

I haven’t had a lot of time to play with this but at least it is a start in getting Capybara based Cucumber scenarios to run against Sauce Labs.

My next step is to figure out how to run one Cucumber scenario to run against multiple browsers on Sauce.

Another thing I’d like to figure out how to do is only run Selenium based tests on demand so they don’t run on Sauce every time I run my Cucumber suite. That could run up a decent Sauce bill, especially if you had multiple developers running Cucumber scenarios multiple times a day.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Riak Overview and Schema design posted

Mike Gehard
Tuesday, January 11, 2011

Our first tech talk from our Boulder office is now up. You can check it out here:
http://pivotallabs.com/talks/121-riak-overview-and-schema-design

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Are Rails plugins still necessary?

Mike Gehard
Monday, December 6, 2010

Back in the day, plugins were an acceptable way to extend Rails because gems were hard to create and publish. It was easier to just put up a public repo and have people pull a plugin from there.

In Rails 3, I think that we’ve got a good solution to these problems. Bundler allows us to type bundle gem and quickly get the skeleton of a gem. Bundler also also allows us to easily pull in unpublished gems via the :git option from any public git repo. The new rubygems.org allows us to easily publish gems that are ready for prime time.

Yes plugin maintainers will need to take a little time to update their plugins to be gems but I think that time is outweighed by the benefits of less code in Rails (because the plugin architecture code will be removed), possibly increased startup time because less code is running and adhernace to a standard way of loading Ruby extensions via the gem mechanism.

What do people think?

A lot of hard work has gone into modularizing the Rails3 codebase to make it easier to work with and faster.

Do we continue the spring cleaning and get rid of other remnants from the past?

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Devise 1.1.3 gotcha…

Mike Gehard
Friday, November 5, 2010

In the continued saga that is the Rails 2.3.10 to Rails 3.0.1 upgrade, I found this little nugget today…you want to add a custom action to a controller that inherits from a Devise controller. Here are the steps that you need to follow:

1) Create a custom controller that overrides some out of the box Devise actions as well as adds a new method.

class RegistrationsController < Devise::RegistrationsController
  def update
     # do something different here
  end

  def deactivate_owner
    # deactivate code here
  end
end

2) You have to tell Devise to use the new controller in routes.rb as well as add the new route to the new action.

devise_for :owners, :controllers => { :registrations => "registrations" } do
  post "deactivate_owner", :to => "registrations#deactivate_owner", :as => "deactivate_owner_registration"
end

When we initially implemented this, our route definition looked like this:

post "deactivate_owner", :to => "registrations#deactivate_owner", :as => "deactivate_owner_registration"
devise_for :owners, :controllers => { :registrations => "registrations" }

When it was implemented this way, we kept getting a AbstractController::ActionNotFound exception. Once we passed the block to devise_for seen in #2, everything worked fine.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Mike Gehard

Mike Gehard
Boulder

Subscribe to Mike's Feed

Author Topics

coffeescript (1)
rails3 (10)
capybara (6)
cucumber (12)
javascript (2)
jquery (1)
webdriver (5)
carrierwave (1)
fog (1)
s3 (2)
testing (1)
rspec2 (3)
omniauth (1)
ruby (5)
devise (1)
aruba (2)
generators (2)
solr (1)
sunspot (1)
concerns (1)
mixins (1)
resque (1)
thin (1)
  • 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 >