Have you tried just using fixture scenarios? Did it work?
On 5/21/07, Carl Lerche <[EMAIL PROTECTED]> wrote: > Sorry about the very long email, but this is a hairy topic that's been > annoying me for some time and I decided to try to do something about. > Also, if you got this twice, I apologize too, but it didn't seem to > have successfully gone out the first time. > > Background: > ---------- > > I've been dealing with Rails for about a year and a half now. I've > been using Rails' built in testing framework, and it's fine... until I > really have to start dealing with the fixtures. I am currently working > on an application that really focuses on selecting data using complex > logic. The only way to test the application in a meaningful way is by > using a large number of fixtures. This has become a real nightmare to > manage and I almost am spending more time keeping the fixtures up to > date than I am coding or testing. So, I took a moment, stepped back, > and took a good look at how I could I could improve fixtures to make > my life a lot easier. > > I have gotten a quick and dirty prototype of my solution running, but > before I really roll up my sleeves and start polishing it up, I > thought I would try to get some suggestions from the community. > > Overview: > --------- > > In my experience, the current fixture framework has three main problems: > > - There is no way to create different version of fixtures. What I mean > by this is that you only can have one users.yml file even if your > tests depend on different initial conditions. What this usually means > is that you will just keep tagging on to the end of users.yml even > though it is not the most efficient way to do it. > - Managing relationships between tables is a really big pain. One must > manually keep track of IDs. This can quickly become a major headache. > - There is no clean way to quickly generate data. If I want 50 > records that I could easily generate in a loop, I still gotta write > them by hand (at least, I wasn't able to figure out how to add loops > to my yaml files in a clean way). > - There is a lot of repetition. No way to follow DRY. > > Solution: > --------- > > + Versioned Fixtures > > First, to address the fixture "versions", I thought the easiest way to > do this would be scenarios (I was inspired from fixture-scenarios). > The way fixtures could be laid out is as follows: > > + specs > |- fixtures > |- global > |- only_one_signed_up_user > |- lots_of_posts_in_los_angeles > |- ... > > All global fixtures (fixtures that should be loaded before every spec) > go into global, then, for each different scenario, there is a > directory created with the relevant fixtures in there. Then, in the > specs, you could do the following > > ------------------------------- > require File.dirname(__FILE__) + '/../spec_helper' > > describe User, :when => :only_one_signed_up_user do > > it "should be the only user" do > User.count.should == 1 > end > end > ------------------------------- > > The key part here would be the :when => :scenario_name option to the > describe method. > > + Writing the fixtures > > Writing fixtures with YAML is quite ugly. I think a better way to do > it would be using a DSL, but coming up with a good syntax is hard. > This is where I am the most hesitant. I have two "options" and I was > wondering if people could comment on them and give me some feedback > and suggestions. > > - The first option is how I started out: http://pastie.caboo.se/63359 > > In this option, fixtures for multiple tables can be written in a > single file. You would start out by using the _create_ method to tell > the parser what table the fixtures are for and you could also specify > :with, which would set default attributes for fixtures. > > You could also nest fixtures in order to easily scope them (see the > last user fixture how I specified nested post fixtures). > > - The second option is what I currently prefer: http://pastie.caboo.se/63361 > > In this option, I keep the one table per file concept that is > currently used. As such, we don't need to specify what table we want > to use before hand. I make available a with_options method which lets > you set default attributes for fixtures. It's also easy to create > loops to automatically generate fixtures, as I show in the second half > of the file. The f method is the actual method for creating a fixture. > it takes a name as a string and a block in which the attributes of the > fixtures are specified. However, the method_missing method is > implemented to handle any missing methods and use that to create > fixtures too as seen with fixture_name { ... } > > + Dealing with relationships > > I think what I hate the most about fixtures right now is having to > deal with table relationships. Having to keep track of IDs myself is > horrible. So, I thought that the easiest way to do this is making the > table_name(:fixture_name) method available straight inside the > fixtures. So, if I have a user model that has a location associated > with it (let's say a zip code, longitude, and latitude), instead of > having to copy / paste that data across fixtures, I can do the > following: > > ------------------------------- > local_guy { > zip_id zips(:portland) > longitude zips(:portland).longitude > latitude zips(:portland).latitude > } > ------------------------------- > > This is much easier to deal with than the other way around. This also > introduces dependencies between fixtures, I thought the easiest way to > handle it would be adding a fixture_order configuration: > > ------------------------------- > Spec::Runner.configure do |config| > config.fixture_order = :zips, :categories, :users, :posts > end > ------------------------------- > > + What's not solved with this > > I haven't figured out a good way to handle counter_cache columns. > Right now, this would still require you to manually count how many > fixtures you have associated with a parent and add that to the > counter_cache column. Any ideas of a better way to do this? > > Well, that's all I came up with. I'm going to keep hacking away at > this and hopefully you all have some feedback to improve this concept. > > -- > EPA Rating: 3000 Lines of Code / Gallon (of coffee) > _______________________________________________ > rspec-users mailing list > [email protected] > http://rubyforge.org/mailman/listinfo/rspec-users > _______________________________________________ rspec-users mailing list [email protected] http://rubyforge.org/mailman/listinfo/rspec-users
