Refactoring

Posted on May 05, 2007

When I first started out developing, I was concern with getting things done and working as quickly as possible. I didn’t really understand the benefits of refactoring. Later on in my development career, I understood why refactoring was important, but I still couldn’t find any time to refactor – unless it was physically added to a project schedule, which wasn’t too often.

What I have finally come to understand, is that I just needed to find time to refactor. The time I spend on refactoring now, will probably save me a lot more time in the future tracking down bugs in a bloated code base. So today, when I ran into an issue because of a bloated code base I decided to refactor the code. Sure I spent all day cleaning up the code, but I feel more confident in the code base and I was able to add much more rpecs.

So, how often do you refactor? and when do you find time to refactor?

Rspec'ing Model Associations

Posted on February 27, 2007

How do you go about spec’ing model associations?

There’s an idea on the rspec mailing list.

However, I kind of like using reflect_on_association. Let’s say we have the following model:

class Product < ActiveRecord::Base

  has_and_belongs_to_many :categories
  has_many :images
  has_many :inventories
  belongs_to :designer

end

Then my context and specifications might look like:

context "Product model" do

  specify "should respond to inventories" do
    Product.reflect_on_association(:inventories).should_not_be_nil
  end

  specify "should respond to categories" do
    Product.reflect_on_association(:categories).should_not_be_nil
  end

  specify "should respond to images" do
    Product.reflect_on_association(:images).should_not_be_nil
  end

  specify "should respond to designer" do
    Product.reflect_on_association(:designer).should_not_be_nil
  end
end

This will catch the situation where an association definition is removed or changed.

Rspec'ing Rails Controllers

Posted on February 26, 2007

I’ve been using rspec for a few months now, and I really like it. I recommend trying it out if you haven’t.

I figure it might be nice to share how I organize controller specs, and get some feedback on how others might organize their specs. I like having one test per specification like so:

specify "should redirect to new session url" do
   response.should_redirect_to new_session_url
end

I also like calling the controller action in the setup method.

setup do
   ... any necessary setup info
   post :update, :id => model, :model => params
end

Here’s what a context might look like in all its glory.

context "Create with a valid product and authenticated user" do
  include ProductsControllerSpecHelper
  controller_name :products

  setup do
    @product = mock(:product, :null_object => true)
    Product.stub!(:new).and_return(@product)
    @product.should_receive(:save!).and_return(true)
    @product.should_receive(:categories).and_return([])
    authenticate_user_mock

    post :create, :product => valid_product_attributes

  end

  specify "should redirect to edit" do
    response.should_redirect_to edit_product_url(@product)
  end

  specify "should assign product" do
    assigns[:product].should_not_be_nil
  end

end

Rspec'ing Rails Views

Posted on February 12, 2007

I've been using rspec for testing rails apps for about a month now. However, I hadn't tried to spec out the views. I decided to starting specing out the views today, and ran into a small obstacle.

I am currently using restful authentication plugin and I have snippets in my view like:


    <% if logged_in? %>
         ....
    <% end %>

Everything is good, until I tried to write my first view test. Calling:

render "controller/template"

I received a missing method error on "logged_in?". The problem is that rspec views are tested in isolation from the controller. This means my include AuthenticatedSystem in the application controller doesn't get loaded and that's where the "logged_in?" method is mixed in.

I did find out that the application_helper.rb and <controller>_helper.rb (where <controller> is the current controller associated with the template being tested) get loaded, so I could define the "logged_in?" method in either of the two helper classes. But the problem with that is that I would have "logged_in?" defined in a couple of places just to run my rspecs.

Digging around in the rspec for rails code base, I found that you can get access to the controller via @controller and the template via @controller.template.

Then a light came on! I could stub out the call to logged_in? on the template like so:

   @controller.template.stub!(:logged_in?).and_return(true)

After doing that, everything worked fine. I also found it came in handy for stubbing out other template calls.