2008-05-11 14:38:18 +0000

If you are using BE DE DE or TE DE DE, then you will get situations in your specs or tests where you want to be able to just create a valid model of another type to test against. This is where factories and builders come in handy.

I can’t really say that I can give a dissertation on what exactly makes a factory a FACTORY or a builder a BUILDER, but what I do know is this:

When I am testing a model’s interactions with another class, I like to know that those interactions are being tested against exactly the class that I am using in development. If the class changes and this breaks the associations with the class I am using, then I want that test to fail fast and to show me what is going wrong so I can fix it.

Fixtures in rails help you do this, for example, you can have a fixture:

but we are not testing if bob is now the Party I/C. We are just testing to see if the user model exhibits the behaviour of having a job if it is allocated one. We picked jobs(:party) because it was there in the YAML file and it looked OK to use at this point of time.

Problem is if you go and modify your users model and decide that any job that has the word ‘Party’ in it would not be valid, then the user spec above would fail… for no good reason.

The problem is with fixtures is that you have to maintain them. And when you have 20 fixtures and all you want is a valid instance of another class, which fixture do you load? Do you want to load all those fixtures just so you could do ”@user = User.new(valid_params)” ? Probably not. What you want is a way just to tell your spec “Make me a new user instance with all the defaults so I can test against it!”

Factories/Builders/Bob the Builder (or whatever you want to call them, I like Bobs) come into play here.

And it will work… hopefully forever… but at least until you change the way your associations work (at which point you would expect it to fail.)

Doing it this way makes a lot of sense. What you do is assign to every class a ‘build_valid’ method and a ‘build_valid!’ method that is guaranteed to return a valid instance of that object, every time.

You then mix these methods into every class you have through the powers of Ruby meta programming, and voila, you can do the above.

Now, this isn’t my idea, I got it from Paul Gross and I am going to rip his code off in the true spirit of open source :) with a modification of my own below. The only real problem I found with Pauls code, is that it can lead to some method name conflicts in your ActiveRecord models, because if you had some class that was called something that is the same name as a method name within Active record (like class Name) then you get ALL sorts of weird errors, we fix this by adding ‘builder_’ to the front of our methods.

lindsaar.net is proudly bought to you by the letters l, i, n, d, s, a, r, e and t.
The comments on this site belong to Mikel Lindsaar and do not reflect the viewpoint of my employer, parents or anyone else.
Powered by Sinatra