Using instantiated fixtures with multiple database access

Posted by Robert Cigán Tue, 29 Aug 2006 08:03:00 GMT

V návaznosti na implementaci projektu používající vícenásobný databázaový přístup, jsem byl nucem vytvořit adekvátní testovací prostředí. Následující text je také uveden na http://wiki.rubyonrails.com/rails/pages/HowtoUseMultipleDatabasesWithFixtures

Using instantiated fixtures with multiple databases without modifying AR

RoR testing with instantiated fixtures while using multiple databases is more possible then ever. All you need to do is just implement your own test_helper method, that load fixtures into the databases and instatiate them. Here’s my code, which i use in my project(just copy it into test_helper.rb):

cattr_accessor :classes_cache
  #class cache for storing already founded classes from models
  @@classes_cache = {}

  def load_user_fixtures(*table_names)
    fixtures = {}
    table_names = table_names.flatten.collect{|t| t.to_s}
    table_names.each do |table_name|
      unless @@classes_cache[table_name].nil?
        klas = @@classes_cache[table_name]
      else
        begin 
          #try to find class name from table name
          klas = eval(table_name.classify)
        rescue
          #go to model directory, run through all models and search for table name
          classes = Dir.entries(RAILS_ROOT + "/app/models").select{|d| d.include?(".rb")}.collect{|f| File.basename(f, ".rb").classify}
          klas_names = classes.select{|f| (eval("#{f}.table_name") rescue false)==table_name }
          klas_name = klas_names.blank? ? table_name.classify : klas_names.first
          klas = eval(klas_name)
        end
        @@classes_cache[table_name] = klas
      end
      #load fixture
      fixtures[table_name] = Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures", table_name, 
                                                      {table_name.to_sym => klas.name}){klas.connection}
    end
    #run through all fixtures and instantiate them
    fixtures.each_pair do |table_name, fixs|
      Fixtures.instantiate_fixtures(self, table_name, fixs)
    end
  end
Disable transactional and instantiated fixtures

self.use_transactional_fixtures = false
self.use_instantiated_fixtures  = false
To load your fixtures in tests use implemented helper method in your unit or functional tests like this(notice, that load_user_fixtures is instance method, but regular fixtures method is class method)

require File.dirname(__FILE__) + '/../test_helper'

class EmployeeTest < Test::Unit::TestCase
  def setup
    load_user_fixtures :employees, :users
  end 
end

AR has a small bug when asking for table_name to class, which is inherited from abstract class. So we have to set table names even if they are the same as model name.

First set abstract class as usual to define connection.

  class AnotherDatabaseConnector < ActiveRecord::Base
  self.abstract_class = true
  establish_connection "another_database_#{RAILS_ENV}" 
  # all subclasses use connection from here
end
All your subclasses accessing another database will look like this. We have to set table name for those, inherited from our abstract class.

class User < AnotherDatabaseConnector
  set_table_name "users" # we need to set this explicitly
end
I done this, because i had many tests already done, and i was too lazy to rewrite them for non-instantiated fixtures, and it works, you don’t have to change anything in AR, you don’t have to set DB connections in tests, all you have to do is just use this method to load fixtures instead of default method fixtures.

If you have any problems or suggestions, you can discuss email me robert.cigan@skvely.cz, or chat directly using ICQ 82645774

- rimmer

Posted in | no comments |

Hpricot jako funkcionální testování

Posted by Ladislav Martinčík Fri, 07 Jul 2006 20:49:33 GMT

Není to ani pár dní co vyšel nový HTML parser - Hpricot a vzápětí vyšel gem balíček (autorem je Luke Redpath), který umožňuje integrovat tento parser do testovacího jádra samotného Rails frameworku. Je to opravdu zajimavé vidět jak jednoduše lze testovat uživatelské rozhraní.

 # test_helper.rb
 require 'hpricot_test_extension'

 assert_equal "My Funky Website", tag('title')
 assert_equal 20, tags('div.boxout').size
 assert_equal 'visible',
 element('div#site_container').attributes['class']

 assert element('body').should_contain('My Funky Website')

Well done, Luke! :) I like that.

Posted in | no comments |