load fixtures in setup? (or is it test-spec's fault)

Railsters:

For various reasons, not worth discussing here, we'd really prefer to load fixtures like this:

  class MySuite < etc::TestCase     def setup       fixtures :posts, :forums, :whatnots     end     ...   end

Does anyone know how to call the same thing fixtures calls, and how to put it inside the setup?

What are the reasons? Oh, okay...

deep breath<

We have a very project with various Rails 1.2 and 2.1 applications using elaborate test fixtures that roughly correspond to established databases with hundreds of thousands of records. We have many Abstract Tests, and many of our cases have very elaborate setups. We are trying to start using test-spec, and we already use scenario-fixtures.

To clean up our testage, we would like to use test-spec like this (warning - pseudo-Ruby):

  context 'generic' do     fixtures :posts, :forums, :whatnots     setup{ foo }     specify 'foo things' { foo things}     specify 'more foo things' { more foo things}

    context 'specific' do       setup{ bar }       specify 'bar things' { foo & bar things}       specify 'more bar things' { etc}     end   end

The point (the only point of BDD I can detect so far) is (at the possible risk of less AbstractTest flexibility), we can inherit setups without the (faint) burden of excessive modules and 'include' lines.

However, my feeb experiments with test-spec show that setup{bar} cannot see the outer context's fixtures. This is either pilot error, or it is unprincipled and counterintuitive. Ideally, the fixtures should inherit and accumulate as one descends deeper into nested contexts.

Next, fixture_scenarios seems to throw an exception if we get too creative with the nested setups and fixtures. We will eventually go in after that issue.

So the easiest short-term fix to all this fun would appear to be using setups to, uh, set each test case up, the way certain industry thought- leaders intended. Putting fixtures() at class scope is syntactic sugar, and our tests can only get so sweet.

Railsters:

For various reasons, not worth discussing here, we'd really prefer to load fixtures like this:

class MySuite < etc::TestCase    def setup      fixtures :posts, :forums, :whatnots    end    ... end

Does anyone know how to call the same thing fixtures calls, and how to put it inside the setup?

Well you could look at fixtures.rb in activerecord, that's where the
magic happens. There's a setup hook in there for fixtures which might
be interesting. If I recall correctly, the fixtures method just sticks
what you give it in some class variable for the setup thing to pickup. In the interest of speed a given fixtures will only ever be loaded
once(at least in stock rails. Plugins that add to the fixtures
functionality may overhaul that)

Fred

Frederick Cheung wrote:

Well you could look at fixtures.rb in activerecord, that's where the magic happens.

You always find something in the last place you look, huh?

  def self.fixtures(*table_names)     write_inheritable_attribute("fixture_table_names", table_names)   end

  def setup     instantiate_fixtures(*fixture_table_names) if fixture_table_names   end

If that's it, how does our setup call their setup without super?

instantiate_fixtures doesn't do what I think you think it does - that's the think which creates instance variables for each loaded fixtures.

I'm not entirely sure what you're asking - is the above your proposed solution to your problem?

Fre

I'm not entirely sure what you're asking

I don't want to write this:

  fixtures :tables tables tables   def setup   end

I want to write this:

  def setup     x :tables tables tables   end

The thing that reads the YAML files and INSERTs them into the database - I called it 'x' in my pseudo-Ruby - I want to call it from inside setup, not outside.

- is the above your proposed
solution to your problem?

It's the code near self.fixtures, from fixtures.rb, that you pointed out.

For various reasons, not worth discussing here, we'd really prefer to load fixtures like this:

I whipped out some Beast, and commented 'fixtures :all' from test_helper.rb. This doesn't work:

class SessionTest < ActiveSupport::TestCase   def setup     self.class.fixtures :posts, :users   end

  def test_fixtures     p posts(:pdi_reply)     p users(:sam)   end end

It doesn't crass at the self.class.fixtures line, but then no posts nor users exist.

What is so special about self.fixtures, or whatever the fixtures, that I can't just call it wherever I like?

This doesn't work: def setup self.class.fixtures :posts, :users end

Here's how to do it. I read activerecord/test/fixtures_test.rb (following my own frequent advice that unit tests are the best documentation), and it lead me to load_extra_fixture(). Upgrading that to handle multiple fixtures gives this monstrosity:

require 'test_helper' require 'assert2'

class SessionTest < ActiveSupport::TestCase

  def nab_fixtures(*names)     names.each do |name|       fixture = create_fixtures(name)       assert fixture.is_a?(Fixtures)       @loaded_fixtures[fixture.table_name] = fixture     end     self.class.setup_fixture_accessors(names)   end

  def setup     nab_fixtures :posts, :users   end

  def test_truth     assert{ posts(:pdi_reply) }     assert{ users(:sam) }   end end

Aaaaand now I have to figure out how to get test-spec to call it...

For various reasons, not worth discussing here, we'd really prefer to load fixtures like this:

I whipped out some Beast, and commented 'fixtures :all' from test_helper.rb. This doesn't work:

class SessionTest < ActiveSupport::TestCase def setup    self.class.fixtures :posts, :users end

def test_fixtures    p posts(:pdi_reply)    p users(:sam) end end

It doesn't crass at the self.class.fixtures line, but then no posts nor users exist.

What is so special about self.fixtures, or whatever the fixtures, that I can't just call it wherever I like?

The reason that this doesn't work is that activerecord hooks into into
the setup method and inserts its fixture loading code before your
setup runs, so when you call self.class.fixtures it's too late.

Fred