views:

114

answers:

2

I've spent most of my time in statically typed languages (primarily C#). I have some bad experiences with the Active Record pattern and unit testing, because of the static methods and the mix of entities and data access code.

Since the Ruby community probably is the most test driven of the communities out there, and the Rails ActiveRecord seems popular, there must be some way of combining TDD and ActiveRecord based code in Ruby on Rails.

I would guess that the problem goes away in dynamic languages, somehow, but I don't see how. So, what's the trick?

+1  A: 

The trick is you don't need trick. You can create ActiveRecord instances in tests. Look here for some basic steps how to use simple testing in Rails.

You can read Rails official testing guide to build some imagination about TDD in Rails. Also take a look at two other popular testing frameworks RSpec (my favorite, watch mocking screencast) and Shoulda.

retro
Thanks for the links. So, it seems like it is standard practice to let the unit tests hit the database in RoR rather than mocking the data access? If that is the case I can see that there is no problem, since the problem with ActiveRecord, in my experience, is that it is very hard to mock.
Erik Öjebo
No, it is not hard to mock.And you are hitting only TEST environment database (when hitting) during tests. But you don't need to hit a database when you don't want to.
retro
An interesting article: http://misko.hevery.com/2009/05/05/the-problem%20-with-active-record/
WW
+1  A: 

The problem is that fixtures are horrible. A while ago I read an article called The Lie and it opened my eyes. This article focuses on Machinist, which I've used and liked, but currently I prefer factory_girl. Here's a basic example from their README:

You define a Factory with just enough default values to get your tests to pass:

# This will guess the User class
Factory.define :user do |u|
  u.first_name 'John'
  u.last_name  'Doe'
  u.admin false
end

And then in your tests you can override or add values as needed (contrived RSpec example)

describe User, "#is_admin?" do
  before(:each) do
    @user = Factory(:user, :admin => true, :email => '[email protected]')
  end

  it "should be true"
    @user.is_admin?.should be_true
  end
end

@user is now a real, live, working ActiveRecord model that lives (temporarily) in the test database. You can use factories in controller tests as well. You could mock them, but in my limited experience the effort is not worth the minor performance gain. Mostly I mock when I need to test a condition (save returning false even though the record is valid so that I can test the failing condition).

After using the two libraries mentioned here, you couldn't pay me to use fixtures again.

rspeicher