`
firebody
  • 浏览: 40765 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

PATCH for restore fixtures data after every test running

阅读更多
rails的fixtures有一个令人讨厌的地方:

fixtures 的数据不会在测试结束后自动清除 ,这样就使得fixtures遗留的数据影响到后来的测试。

相关的争论也持续了很久 ,具体的连接请看  http://dev.rubyonrails.org/ticket/2404

里面的 Rick的patch我在rspec下用了,不见好用,我只能自己搞了一个patch,在rspec的 spec_helper.rb下引入
,解决了这个问题 。

patch主要的思路是: 每次测试setup运行前插入fixture的数据,保证这个插入 fixtures数据的事务和test运行时的事务是同一个 ,teardown结束前,清空一些类变量, 原有的teardown运行的时候会作事务回滚的动作,这样就可以保证每次测试都回滚圆来插入的 fixtures的数据。

相关的配置 :
  config.use_transactional_fixtures = true
  config.use_instantiated_fixtures  = false



module Test #:nodoc:
  module Unit #:nodoc:
    class TestCase #:nodoc:
      alias_method : old_setup_with_fixtures, :setup_with_fixtures unless method_defined?(: old_setup_with_fixtures)
      alias_method : old_teardown_with_fixtures, :teardown_with_fixtures unless method_defined?(: old_teardown_with_fixtures)
      def setup_with_fixtures

        if use_transactional_fixtures?

          ActiveRecord::Base.send :increment_open_transactions
          ActiveRecord::Base.connection.begin_db_transaction
          close_original_activerecord_transaction_methods
        end
        old_setup_with_fixtures
        if use_transactional_fixtures?
          open_original_activerecord_transaction_methods
        end
        
      
      end
      
      def teardown_with_fixtures
        if use_transactional_fixtures?
          clear_fixtures_states_when_use_transactional_fixtures
        end
        old_teardown_with_fixtures       
      end      
      #prevent the next code:alias_method from trigger invoking the self.method_added introspected method
      class<<TestCase
        alias old_method_added method_added
        def method_added(m) 
          #do nothing
        end
      end

      alias_method :setup,:setup_with_fixtures
      alias_method :teardown,:teardown_with_fixtures
      #reopen the introspector class method:method_added
      class<<TestCase
        alias method_added old_method_added
      		
      end
      
      private
      def clear_fixtures_states_when_use_transactional_fixtures
        @@already_loaded_fixtures.clear if @@already_loaded_fixtures
        @loaded_fixtures.clear if  @loaded_fixtures

      end
      def close_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias old_increment_open_transactions increment_open_transactions
          		def increment_open_transactions
          			#do nothing
      			end
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method : old_begin_db_transaction,:begin_db_transaction
          	def begin_db_transaction
          		#do nothing
      		end
          ])
        
      end
      
      def open_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias increment_open_transactions old_increment_open_transactions
          		
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method :begin_db_transaction,: old_begin_db_transaction
          	
          ])
      end
    end
  end
end
分享到:
评论
3 楼 firebody 2007-12-13  
Readonly 写道
你这个方法好,在9月份的时候有过类似讨论:
http://www.iteye.com/topic/51922

你可以把这个方法提交到ror的issue tracker上了。
发上去了。两年多了,居然没有引起足够的注意。
看来rails 测试的观点和方式很不一样啊。
2 楼 Readonly 2007-12-11  
你这个方法好,在9月份的时候有过类似讨论:
http://www.iteye.com/topic/51922

你可以把这个方法提交到ror的issue tracker上了。
1 楼 firebody 2007-12-09  
更新了 rails 2.0.1后,跑 rspec 发现一大堆失败,看 activerecord的fixtures.rb代码,发现新版的 activerecord为了提升性能,在Fixtures里用一个类变量缓存了connection, 意味着所有的关于fixtures的插入都是使用同一个connection, 走我的代码的逻辑的话,会因为这个cached connection已经被rollback而导致后续的测试都失败。 还好 Fixtures类也相应增加了一个类方法 : reset_cache. 只要在teardown_with_fixtures调用这个reset_cache就行了。

修改后的代码 如下:
module Test #:nodoc:
  module Unit #:nodoc:
    class TestCase #:nodoc:
      alias_method : old_setup_with_fixtures, :setup_with_fixtures unless method_defined?(: old_setup_with_fixtures)
      alias_method : old_teardown_with_fixtures, :teardown_with_fixtures unless method_defined?(: old_teardown_with_fixtures)
      def setup_with_fixtures
        if use_transactional_fixtures?

          ActiveRecord::Base.send :increment_open_transactions
          ActiveRecord::Base.connection.begin_db_transaction
          close_original_activerecord_transaction_methods
        end
        old_setup_with_fixtures
        if use_transactional_fixtures?
          open_original_activerecord_transaction_methods
        end
        
      
      end
      
      def teardown_with_fixtures
        if use_transactional_fixtures?
        	Fixtures.send :reset_cache  if Fixtures.respond_to?(:reset_cache)
          clear_fixtures_states_when_use_transactional_fixtures
        end
        old_teardown_with_fixtures       
      end      
      #prevent the next code:alias_method from trigger invoking the self.method_added introspected method
      class<<TestCase
        alias old_method_added method_added
        def method_added(m) 
          #do nothing
        end
      end

      alias_method :setup,:setup_with_fixtures
      alias_method :teardown,:teardown_with_fixtures
      #reopen the introspector class method:method_added
      class<<TestCase
        alias method_added old_method_added
      		
      end
      
      private
      def clear_fixtures_states_when_use_transactional_fixtures
        @@already_loaded_fixtures.clear if @@already_loaded_fixtures
        @loaded_fixtures.clear if  @loaded_fixtures

      end
      def close_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias old_increment_open_transactions increment_open_transactions
          		alias old_decrement_open_transactions decrement_open_transactions
          		def increment_open_transactions
          			#do nothing
      			end
      			def decrement_open_transactions
          			#do nothing
      			end
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method : old_begin_db_transaction,:begin_db_transaction
          	alias_method : old_commit_db_transaction,:commit_db_transaction
          	def begin_db_transaction
          		#do nothing
      		end
      		def commit_db_transaction
          		#do nothing
      		end
          ])
        
      end
      
      def open_original_activerecord_transaction_methods
        self.class.class_eval(%Q[
          	class<<ActiveRecord::Base
          		alias increment_open_transactions old_increment_open_transactions
          		alias decrement_open_transactions old_decrement_open_transactions
      		end
          ])
        ActiveRecord::Base.connection.class.class_eval(%Q[
          	alias_method :begin_db_transaction,: old_begin_db_transaction
          	alias_method :commit_db_transaction,: old_commit_db_transaction
          	
          ])
      end
    end
  end
end

相关推荐

    Object Restore for Active Directory_10

    大家经常会在维护AD的同时有可能误删除用户,OU... QUEST Object Restore for Active Directory(这是QUEST很少的免费软件之一,相比QUEST Recovery Manager for Active Directory功能弱很多,但是我们还是可以使用到)

    postgresql-14.1-1-windows-x64

    A dump/restore is not required for those running 14.X. However, note that installations using physical replication should update standby servers before the primary server, as explained in the third ...

    Killtest 分享000-M77 题库

    根据给定的信息,我们可以推断出这是一份与IT认证考试相关的资料,特别是关于IBM Information Management Optim Technical Mastery Test v2(000-M77)的题库分享。接下来,我们将详细解析这份材料中的关键知识点。 ...

    network_data_restore

    这里的“network_data_restore”项目可能涉及到一系列与网络数据备份、存储和恢复相关的代码和过程。根据描述,这是一个开发者用于测试和临时保存网络数据恢复功能的代码库。 1. **网络数据备份**:网络数据备份是...

    oracle恢复工具-FY_Recover_Data

    15:33:19: [restore_table] Trying to restore data to SYS.TRUNTAB1$$2 15:33:20: [restore_table] Expected Records in this round: 411 15:33:20: [restore_table] 411 records recovered 此处省略N行输出.....

    Data-Unit_MongoDB_Restore_v2.1.zip

    Data-Unit_MongoDB_Restore适用于磁盘存储故障、勒索病毒删除、误操作删除等导致的数据库丢失恢复。运行工具后将数据文件拖入本窗口即可。也支持扫描分区和裸磁盘,建议扫描磁盘镜像文件,效果更好。 免费版每个集合...

    QTP11补丁发布 - 支持FireFox 3.6

    * After installing the patch and Firefox 3.6 on a computer with UAC (User Account Control) enabled, you need to start QuickTest at least one time using the “Run as administrator” mode. ...

    Tivoli TSM restore commands

    ### Tivoli TSM Restore Commands详解 #### 一、引言 Tivoli Storage Manager (TSM) 是一款由IBM开发的企业级数据备份与恢复解决方案。TSM 的核心功能之一是能够通过各种命令来实现对文件和目录的有效备份与恢复。...

    Data Protection for VMWare技术概览.pptx

    * Restore粒度挑战:虚拟机的备份需要考虑恢复粒度问题,例如图像级备份和项目级恢复。 * 许可成本挑战:虚拟机的备份需要考虑许可成本问题,例如备份ISV是否按虚拟机数量、CPU核心或其他指标进行计费。 解决方案 ...

    高中英语单词天天记restore素材

    - 例如:"The court will make every effort to restore the child to his mother."(法院将尽力把孩子送回母亲身边) 理解并熟练运用"restore"的这些用法,对于提高英语水平和在实际交流中准确表达是非常有帮助的...

    DATAUNIT_MySQL_PAGE_RESTORE_v2.3_release_2020-03-16.zip

    支持从裸磁盘、分区、文件中搜索所有IBD page碎片。 1、输入字母a-z :搜索对应的逻辑分区A-Z。此模式请以管理员身份运行。 2、输入数字1-9 :搜索物理磁盘,对应“磁盘管理器”中的磁盘0-9。...

    USB Restore-v3.13.0.0 解除U盘写保护

    USB Restore_v3.13.0.0 解除 u盘写保护,操作简单很方便。一款实用的u盘写保护解除工具。usb restore最新版可以轻松地恢复从USB驱动器也很受欢迎,如笔式驱动器,记忆棒,拇指驱动器,USB闪存驱动器等无法访问的文件...

    Missing and Modified Data in Nonparametric Estimation with R

    This book presents a systematic and unified approach for modern nonparametric treatment of missing and modified data via examples of density and hazard rate estimation, nonparametric regression, ...

    RESTORE DATABASE命令还原SQLServer 2005 数据库

    RESTORE DATABASE命令是SQL Server数据库管理系统中用于还原数据库的SQL语句。该命令用于从备份文件中恢复数据库的全部或部分内容,保证数据库系统的数据安全和数据恢复能力。在SQL Server 2005版本中,该命令的基本...

    [量产部落]Restore_v3.26.0.0.rar

    【量产部落】Restore_v3.26.0.0是一款针对USB闪存盘进行量产修复和管理的工具,主要用于解决USB设备出现的各种问题,如无法识别、速度慢、格式化失败等。该软件的主要功能包括对USB设备进行初始化、低级格式化、恢复...

    restore-symbol

    restore-symbol

    Synology Restore Media Creator-2.1.1-0576.zip

    "Synology Restore Media Creator-2.1.1-0576.zip" 是群晖(Synology)公司推出的一款恢复工具,主要用于帮助用户对他们的群晖NAS系统进行备份和恢复操作。这款工具的重要性和实用性在于它能确保在系统出现问题或者...

    USB Restore_v3.13.0.0.zip

    标题中的“USB Restore_v3.13.0.0.zip”是一个软件的压缩包,它主要用于U盘的恢复和格式化功能。这个版本号(v3.13.0.0)表明这是该软件的第三个主要版本,第十三个小版本,零次修订,可能包含了若干错误修复和功能...

Global site tag (gtag.js) - Google Analytics