Extracting fixtures

I’m still using fixtures. Shame, I know.

Why I do use them instead of Factory Girl or other solution like that? Well, fixtures can be much more closer to real data than mocks from Factory. How come, You ask? Fixtures are imaginary data exactly like mocks from other sources!

My answer is: that depends how You create fixtures. If You create them by hand, indeed they are disconnected from real world (like all mocks).

What is Your real data/mocks ratio?

What is Your real data/mocks ratio? CC by hsing

But I prefer to extract fixtures from real (production) database. That way I can easily pick entries created by users which are edge cases. The only trouble is with creating fixtures. For some time I’m using modified extract_fixtures rake task. I have added some conditions to extracting process – SQL condition to select only particular records and adjusted syntax to recent rake.

This is useful especially when You are about to take over application code which has no tests. Extracting real data is quick way to start write integration tests (in such case they have are most efficient – time invested and application code coverage).

How to extract fixtures without pain?

Continue reading

Test benchmark – useful gem for Rails tests

Doing TDD You need to know which tests are making whole suite slower. If time used by rake test becomes too long, You may be tempted to skip running tests… Waiting for them to complete becomes suddenly burden on Your way to next task.

Waiting... Waiting...

Waiting... Waiting... (c) Tony the Misfit

So, when You need to optimize Your test suite, test_benchmark is a way to go. Just install Rails plugin and after rake test You will get 10 slowest tests and timing of all test in test.log. Now You know where to look for a good place to start and not to wait too long…

How did I overcome TDD fear

I was using Rails for over two years, but I still was not truly converted to TDD. There was no special reason for it, I have tried few times with my own projects to take TDD approach. And I was quickly returning to plain, old code crunching.

Why? Maybe I haven’t approached TDD with enough determination to change my own habits – when I was starting new application, just write somehow seemed faster to me. Later I was creating some tests, just to check some most important (IMO) pieces of code. The thing which seemed being biggest obstacle was keeping set of fixtures to have data on which I can run tests. Problematic for me was having up to date fixtures – corresponding with current data model. I don’t know how about You, but when I approach new application I do usually have data model prepared only as very rough concept. This means that during development changes are often and notable. Editing every time set of fixtures… well each time it was reason I stopped TDD approach with my projects. I know. Maybe I should prepare data model in more detail before I start?

Recently I was preparing to bear with other type of project. For existing application I was supposed to create API providing some core features as RESTful interface. This was meant as wrap-up layer over existing code, not providing new features. But… Usually there is some but. Old code was not written by me, it was crappy and most of logic was in controllers instead of models.

I knew I need some test support (old code had no running tests – there were created at some point RSpec specifications, but models had changed since then, and RSpec was not updated). In other words – I wanted it or not, I was designated to take TDD approach.

Ride with TDD!

Ride with TDD! (c) Lachlan Hardy

But this time I got instant gratification – every test I wrote,it helped me understand what is going on in old code and let me be assured that I’m moving application logic from controllers to models without altering it. And fixtures – I have extracted them from real application data. With not changing data model two biggest obstacles were removed and… From now You can me count as another TDD zealot. Yes. I do see how much I have gained using TDD approach in this project, and could not imagine how I could work without it before. Well, we learn all the time.

Do You want to write less fixtures?

When writing functional test I would like sometimes to call methods in other controllers. Why, would You ask? Well… In most of cases it is related to fixtures or rather to my averse to maintain fixtures (I told You!). In case of API I was talking earlier, there were several models acting as helpers – they were representing some statuses of internal processes. Based on them final object was created. Sure I could write fixtures for them. But my point is – why to create those fixtures (and overhead to update them when model changes) when they can be prepared in test process?

What I’m talking about? Let’s assume we are preparing some reservations – to create Reservation based on search terms and set of available rates first we create Search (describes search terms), Result (set of matching rates with changes resulted from applied business logic – discounts, supercharges, etc). With those objects we can create final Reservation.

More – for those interim models I have wrote some tests, but treating whole process as a black box I could test it more efficient – I provide input data and I expect some final result – which is much more similar how this objects will be really used.

The only question was how to call those methods in other controllers inside of functional tests?

Methods for calling methods (put, get) available in functional test take action of current controller as argument, not path to run through Rails routing system. After short googling and looking into ActionController::TestCase I have noticed that current controller is defined by @controller variable (given method is just send to @controller). So, changing @controller is enough (storing it earlier for later usage):

class ExampleControllerTest < ActionController::TestCase
    def setup
      @controller = ExampleController.new
      @request    = ActionController::TestRequest.new
      @response   = ActionController::TestResponse.new
    end
    
  should "call other controller before main test" do
   orig_controller = @controller
   @controller = SomeOtherController.new
   post :action_in_some_other_controller, {:argument => "value"}
   #get some data from @response
   #.....
   #now we can return to original controller - just re-run setup
   @controller = orig_controller
   #let's tests begin!
  end
end

As You can see I’m shoulda plugin fan :)

It has worked for me. What are pitfalls of this approach? I did not encounter any problems, but YMMV – I expect that re-using @response and @request can lead to some problems.

What else can be done to make fixtures more robust tool

I’m aware of Factory Girl, but from simple test I was conducting it is not huge time saver (however fixtures are in nicer format). I will take look at Machinist and try to write here more about FG and Machinist.

Any other ideas? Maybe there is some totally different way to accomplish my goal and I’m just not aware of it? I would appreciate Your opinions in comments.

Shoulda You abandon Test::Unit?

I was not very keen on RSpec. Well to be honest I had some problems with writing tests at all. Fortunately old and bad times are gone. I mean writing test is now much more natural and has become second nature. That way I don’t need to force myself to write them. You know, attacking new ideas is much more sexier than boring (most of time) tests ;)

As freelancer I do often jump into some established project, with long history and different tools used. This has advantage I can watch other developers how theirs code looks, and learn from it how things can be done (there are always exceptions).

In one of such projects I’ve found Shoulda plugin. This plugin adds to Test::Unit bunch of nifty helpers, making live much easier.

First, stop writing those damn underscores and make tests much more readable:

context "Facebook app" do
    context "when removed " do
      setup do
         #some init code
      end
      
      should "accept only HTTP post" do
          #request and assertions
      end
      
      should "clear FB bindings" do
         #request and assertions
      end
    end
end

context allow to group tests and provide some common setup phase. Naming tests is much more easier and allow DRY, making test titles much more compact. However when running tests it will output names of tests (when some errors/failures) perpending them with all context names.

"Facebook app when removed should accept only HTTP post"
"Facebook app when removed should clear FB bindings"

More readable? You bet! But that is not all! Helpers to make even more less typing, this time with assertions. Just check docs for this plugin (note there is also non-rails version, Shoulda gem, which provides cut-down features, but is not coupled with Rails, so can be used in other projects using Test::Unit).

For me, RSpec is still not test framework of choice. Maybe the other day I will drink RSpec’s Kool-Aid, but for now I prefer Test::Unit + Shoulda plugin.

If there are some RSpec zealots, what is reason for You to choose it over Test::Unit?