Ruby Forum RSpec > Cucumber vs Rails Fixtures

Posted by Phlip (Guest)
on 20.05.2009 19:46
(Received via mailing list)
Cucumberists:

Apologies for not jumping into some wild alternate fixture (or mock!) 
system,
but the unit tests at my new day gig are >cough< hanging by a thread as 
it is.

I need to show off some cute Cuke, _without_ rocking the boat!

How do I actually use real, pre-existing Rails fixtures, the same as the 
unit
tests use? For familiarity?

Putting this at the top of the step.rb seems just a leeettle bit 
tacky...

   $fixtures_installed ||= (
     ENV['RAILS_ENV'] = 'test'
     RAILS_ENV.replace('test')
     system('rake db:fixtures:load') )

I have attempted to load Rails Fixtures on demand before, and I'm the 
first to
admit their architecture sucks - loading them on demand ain't pretty!

And exactly why was 'rake features' running in RAILS_ENV=development 
mode? Do
developers _like_ having their scratch database screwed up each time 
they run
fixtures? Enquiring minds want to know!

--
   Phlip
Posted by Ben Mabey (mabes)
on 20.05.2009 20:05
(Received via mailing list)
Phlip wrote:
> Cucumberists:

FYI, Cucumber now has it's own mailing list:
http://groups.google.com/group/cukes
>
> Apologies for not jumping into some wild alternate fixture (or mock!) 
> system, but the unit tests at my new day gig are >cough< hanging by a 
> thread as it is.
>
> I need to show off some cute Cuke, _without_ rocking the boat!
>
> How do I actually use real, pre-existing Rails fixtures, the same as 
> the unit tests use? For familiarity?

http://wiki.github.com/aslakhellesoy/cucumber/fixtures


-Ben
Posted by Phlip (Guest)
on 21.05.2009 07:28
(Received via mailing list)
Ben Mabey wrote:

> http://wiki.github.com/aslakhellesoy/cucumber/fixtures

Ding! That would have been my next click in my Googling. Let's hope this 
thread
pushes that up.

 > http://groups.google.com/group/cukes

What, no gmane yet?? (-:

--
   Phlip
Posted by Aslak Hellesøy (aslakhellesoy)
on 21.05.2009 10:42
(Received via mailing list)
>
I would have preferred: "I have set up GMane"

Thanks Philip ;-)
Posted by Aslak Hellesøy (aslakhellesoy)
on 21.05.2009 11:48
(Received via mailing list)
>> What, no gmane yet?? (-:
>>
> I would have preferred: "I have set up GMane"
>
> Thanks Philip ;-)

Sorry about the spelling Phlip

Aklas
Posted by Phlip (Guest)
on 21.05.2009 16:35
(Received via mailing list)
aslak hellesoy wrote:

>>> http://groups.google.com/group/cukes

>> What, no gmane yet?? (-:

> I would have preferred: "I have set up GMane"

Netiquette: I would _not_ set someone else's group up on GMane - even if 
it were
just a Google Group...

--
   Phlip
   http://flea.sourceforge.net/resume.html
Posted by Wolfram Arnold (wolframarnold)
on 02.06.2009 17:53
>> How do I actually use real, pre-existing Rails fixtures, the same as 
>> the unit tests use? For familiarity?

What I was missing is the regular use of fixtures as in rspec or test 
unit, like so:

u = users(:bob)
u.email = "aaa"
u.should_not be_valid

This link
> 
> http://wiki.github.com/aslakhellesoy/cucumber/fixtures
> 
described how to get fixtures loaded for the entire suite, so that you 
can say:

u = User.find(1)

or

u = User.find_by_name("Bob")

this is kind of a drag, if you have a well formed fixture file with 
symbolic names, etc.

So I came up with this (which was developed and tested in Cucumber gem 
version 0.2.3, and I haven't tried it yet with the latest 0.3.9):

Add this to your env file:

Fixtures.reset_cache
fixtures_folder = File.join(RAILS_ROOT, 'test', 'fixtures')
fixtures = Dir[File.join(fixtures_folder, '*.yml')].map {|f| 
File.basename(f, '.yml') }
fixtures << Dir[File.join(fixtures_folder, '*.csv')].map {|f| 
File.basename(f, '.csv') }

# If your fixture files are named differently from the classes they 
refer to,
# you also need to do this:
#
#   class_table_mappings = {:table_name_in_db => class_name}
#   Fixtures.create_fixtures(fixtures_folder, fixtures, 
class_table_mappings)
#
# otherwise:

# This will populate the test database tables
Fixtures.create_fixtures(fixtures_folder, fixtures)

# The following will define methods that can access symbolic fixture 
names,
# as in users(:bob)

World do |world|

  (class << world; self; end).class_eval do
    @@fixture_cache = {}
    fixtures.each do |table_name|
      table_name = table_name.to_s.tr('.', '_')
      define_method(table_name) do |*fixture_symbols|
        @@fixture_cache[table_name] ||= {}

        instances = fixture_symbols.map do |fixture_symbol|
          if fix = 
Fixtures.cached_fixtures(ActiveRecord::Base.connection, 
table_name)[fixture_symbol.to_s]
            @@fixture_cache[table_name][fixture_symbol] ||= fix.find  # 
find model.find's the instance
          else
            raise StandardError, "No fixture with name 
'#{fixture_symbol}' found for table '#{table_name}'"
          end
        end
        instances.size == 1 ? instances.first : instances
      end
    end
  end
  world
end

Posted by Wolfram Arnold (wolframarnold)
on 02.06.2009 18:03
Posted by Wolfram Arnold (wolframarnold)
on 06.06.2009 00:27
The method I posted last week only works for Cucumber prior to 0.2.3.2.

For 0.2.3.2 and later, you cannot pass a block to the World more than 
once, and thus the new way would be (in env.rb):

module FixtureAccess

  def self.included(base)
    (class << base; self; end).class_eval do
      @@fixture_cache = {}
      fixtures.each do |table_name|
        table_name = table_name.to_s.tr('.', '_')
        define_method(table_name) do |*fixture_symbols|
          @@fixture_cache[table_name] ||= {}

          instances = fixture_symbols.map do |fixture_symbol|
            if fix = 
Fixtures.cached_fixtures(ActiveRecord::Base.connection, 
table_name)[fixture_symbol.to_s]
              @@fixture_cache[table_name][fixture_symbol] ||= fix.find 
# find model.find's the instance
            else
              raise StandardError, "No fixture with name 
'#{fixture_symbol}' found for table '#{table_name}'"
            end
          end
          instances.size == 1 ? instances.first : instances
        end
      end
    end
  end

end

... then ...

World(FixtureAccess)
Posted by Wolfram Arnold (wolframarnold)
on 06.06.2009 03:21
This still wasn't fully working; I posted too soon.  See here for the 
final and working version: 
http://wiki.github.com/aslakhellesoy/cucumber/fixtures
Posted by Yi Wen (hayafirst)
on 06.06.2009 04:08
(Received via mailing list)
I do this:

Fixtures.reset_cache
fixtures_folder = File.join(RAILS_ROOT, 'test', 'fixtures')
fixtures = Dir[File.join(fixtures_folder, '*.yml')].map {|f|
File.basename(f, '.yml') }
fixture_class_names = {} # or whatever needed
Fixtures.create_fixtures(fixtures_folder, fixtures, fixture_class_names)
Posted by Wolfram Arnold (wolframarnold)
on 07.06.2009 19:47
Yi Wen wrote:
> I do this:
> 
> Fixtures.reset_cache
> fixtures_folder = File.join(RAILS_ROOT, 'test', 'fixtures')
> fixtures = Dir[File.join(fixtures_folder, '*.yml')].map {|f|
> File.basename(f, '.yml') }
> fixture_class_names = {} # or whatever needed
> Fixtures.create_fixtures(fixtures_folder, fixtures, fixture_class_names)

Sure, that'll load fixtures and let you access them, e.g. with:

User.find(1)

What I wanted is to be able to access fixtures with:

users(:john)

Hence all the heavy lifting.  It works now as described on the github 
wiki page.