`

Rails UnitTest 测试机制浅析

阅读更多
    一直以来,都想知道,Rails在进行UnitTest的时候,是怎么处理数据的。怎么保证单元测试结束后,可以清除上一个测试的数据的。今天,稍微有时间就借着一位老大的问题,浅浅的探究了一下,理解不对的地方大家指正。

首先,应该弄明白Ruby的测试怎么跑的,因为很显然
module ActiveSupport
  class TestCase < Test::Unit::TestCase

Rails的ActiveSupport调用了Ruby的测试。那么,找到Ruby当前目录的test/unit下看看怎么运行的。

  module Unit
    # If set to false Test::Unit will not automatically run at exit.
    def self.run=(flag)
      @run = flag
    end

    # Automatically run tests at exit?
    def self.run?
      @run ||= false
    end
  end
end

at_exit do
  unless $! || Test::Unit.run?
    exit Test::Unit::AutoRunner.run
  end
end



当然,rails一定调用ruby的这个流程。
简单讲,注册at_exit这个例程,这个kernel方法,在执行结束,执行Test::Unit::AutoRunner.run
在找到对应代码的,对应部分,会看到如下执行:

      RUNNERS = {
        :console => proc do |r|
          require 'test/unit/ui/console/testrunner'
          Test::Unit::UI::Console::TestRunner
        end,
        :gtk => proc do |r|
          require 'test/unit/ui/gtk/testrunner'
          Test::Unit::UI::GTK::TestRunner
        end,
        :gtk2 => proc do |r|
          require 'test/unit/ui/gtk2/testrunner'
          Test::Unit::UI::GTK2::TestRunner
        end,
        :fox => proc do |r|
          require 'test/unit/ui/fox/testrunner'
          Test::Unit::UI::Fox::TestRunner
        end,
        :tk => proc do |r|
          require 'test/unit/ui/tk/testrunner'
          Test::Unit::UI::Tk::TestRunner
        end,
      }



看了这个源代码,就对ruby处理单元测试,大体了解,这很好的说明,为什么Rails里的UnitTest根本不写执行,就写一堆def就行了。
那么想知道Rails对数据库怎么处理的那得继续看相应的看源代码了
于是,找到rubyonrails的api看到相应的类
Class
ActiveSupport::TestCase
In: 
vendor/rails/railties/lib/test_help.rb 
vendor/rails/activesupport/lib/active_support/test_case.rb

下面有
    * ActiveRecord::TestFixtures
    * Rails::BacktraceFilterForTestUnit
    * ActiveSupport::Testing::Default
    * ActiveSupport::Testing::SetupAndTeardown
    * ActiveSupport::Testing::Assertions
    * ActiveSupport::Testing::Deprecation


而ActiveRecord::TestFixtures是我们要找的,需要加载数据的那个
现在,看还挺理所当然的,当时,可是看了好多源码才确定这个文件的部分,才是导致数据加载的部分。
继续读有如下方法:

Methods

    * included
    * run_in_transaction?
    * setup_fixtures
    * teardown_fixtures



再看几个代码就清楚多了,一个加载环境,一个回滚。所以,理论上讲如果,你不想加载数据,也可以从这里修改。


     def self.included(base)
       base.class_eval do
         setup :setup_fixtures
         teardown :teardown_fixtures
 
         superclass_delegating_accessor :fixture_path
         superclass_delegating_accessor :fixture_table_names
         superclass_delegating_accessor :fixture_class_names
         superclass_delegating_accessor :use_transactional_fixtures
         superclass_delegating_accessor :use_instantiated_fixtures   # true, false, or :no_instances
         superclass_delegating_accessor :pre_loaded_fixtures
 
         self.fixture_table_names = []
         self.use_transactional_fixtures = false
         self.use_instantiated_fixtures = true
         self.pre_loaded_fixtures = false
 
         self.fixture_class_names = {}
       end
 
       base.extend ClassMethods
     end





     def setup_fixtures
       return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
 
       if pre_loaded_fixtures && !use_transactional_fixtures
         raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
       end

      @fixture_cache = {}
       @@already_loaded_fixtures ||= {}
 
       # Load fixtures once and begin transaction.
       if run_in_transaction?
         if @@already_loaded_fixtures[self.class]
           @loaded_fixtures = @@already_loaded_fixtures[self.class]
        else
          load_fixtures
           @@already_loaded_fixtures[self.class] = @loaded_fixtures
        end
         ActiveRecord::Base.connection.increment_open_transactions
         ActiveRecord::Base.connection.transaction_joinable = false
        ActiveRecord::Base.connection.begin_db_transaction
       # Load fixtures for every test.
       else
         Fixtures.reset_cache
         @@already_loaded_fixtures[self.class] = nil
         load_fixtures
       end
 
      # Instantiate fixtures for every test if requested.
       instantiate_fixtures if use_instantiated_fixtures
     end


哈,这就是我一直想找的代码,而且,注释写的太直接了。每次测试加载一次Fixture


下面是回滚的部分:

     def teardown_fixtures
       return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
       unless run_in_transaction?
         Fixtures.reset_cache
       end
 
       # Rollback changes if a transaction is active.
       if run_in_transaction? && ActiveRecord::Base.connection.open_transactions != 0
         ActiveRecord::Base.connection.rollback_db_transaction
         ActiveRecord::Base.connection.decrement_open_transactions
      end
       ActiveRecord::Base.clear_active_connections!
     end



分享到:
评论
3 楼 Hooopo 2009-06-03  
rails 2.3的test/fixtures下文件不自动加载?在哪里设置呀?
2 楼 woody1983 2009-05-23  
我刚开始接触测试的时候 发现Fixture加载的只有三组数据 每次测试的时候发现test数据库一直都是三条记录 而不是一直累积上去。 原来是因为这个 O.O
1 楼 night_stalker 2009-03-20  
赞!
grep "Load fixtures" *.rb

相关推荐

    深入解析Rails测试策略:单元测试与功能测试的区别

    在软件开发中,测试是确保...通过本文的探讨,我们了解到了Rails中单元测试和功能测试的区别,以及如何利用Rails的测试工具来编写高质量的测试代码。掌握这些知识,将有助于开发者在Rails项目中实施有效的测试策略。

    combustion, 简单,优雅的Rails 引擎测试.zip

    combustion, 简单,优雅的Rails 引擎测试 燃烧in是一个以简单有效的方式测试 Rails 引擎的库,而不是在规范或者测试文件夹中创建完整的Rails 应用。它允许你在引擎的上下文中编写你的规格,只使用你需要的Rails 应用...

    Ruby-APITaster一种快速而简单的方法来可视化测试你的Rails应用API

    Ruby-APITaster是一款强大的工具,专为Rails应用的API测试和可视化设计。它使得开发者能够迅速地对API接口进行互动式测试,从而确保API的功能正确性和性能稳定性。这款工具的出现,极大地简化了API测试过程,提高了...

    使用RSpec 测试Rails 程序.pdf

    ### 使用RSpec 测试Rails 程序的知识点总结 #### 一、RSpec与Rails结合的基础概念 **RSpec**(RSpec is not a unit testing framework)是一种为Ruby编程语言设计的行为驱动开发(BDD)框架,而**Rails**是基于...

    举例理解Ruby on Rails的页面缓存机制

    在标题和描述中提到的“举例理解Ruby on Rails的页面缓存机制”,主要是指通过具体的例子来阐述如何在实际项目中运用页面缓存。例如,IBM 官方技术文档中的内容可能包含以下示例: 1. **启用页面缓存**:在 Rails ...

    rails指南 中文版

    12. **Migrations**:Rails的迁移机制允许开发者通过Ruby代码来管理数据库结构的变化,使得数据库版本控制变得简单。 学习Rails指南中文版,开发者将全面了解Rails的各个方面,包括基础概念、核心组件、最佳实践...

    Ruby on Rails Guides_ A Guide to Testing Rails Applications.pdf

    该指南不仅覆盖了Rails内置的测试机制,还帮助读者理解Rails测试术语,撰写单元、功能和集成测试,并介绍了流行的测试方法和插件。它假设读者对Rails的基本操作方式有初步了解,但并不教如何编写一个Rails应用,而是...

    rails2-sample

    这部分内容会更进一步地探索Rails的内部机制,包括其架构、工作流程以及一些高级特性。例如,Rails的路由系统是如何工作的,以及如何使用Rails进行RESTful API的开发。这些知识对于深入理解和优化Rails应用至关重要...

    rails性能优化

    Rails性能优化是一个涉及多个方面的复杂过程,它要求开发者对Ruby on Rails框架的内部机制有深刻的理解,并且能够合理地应用各种技术和工具来提升应用的性能。在性能优化的过程中,首先应该避免盲目优化,而是要通过...

    关于rails 3.1 cucumber-rails 1.2.0

    Rails 3.1 和 Cucumber-Rails 1.2.0 是两个在Web开发领域非常重要的工具,尤其对于Ruby on Rails框架的测试和自动化流程。本文将深入探讨这两个组件,以及它们如何协同工作来增强软件开发的效率和质量。 首先,...

    Ruby on Rails:Rails中的测试驱动开发.docx

    Ruby on Rails:Rails中的测试驱动开发.docx

    Rails 4 Test Prescriptions

    《Rails 4 Test Prescriptions》是一本专注于教授开发者如何为Rails应用编写测试的书籍,作者Noel Rappin凭借多年的经验提炼出了一系列实用且有效的测试策略。本书受到了来自RSpec的主要维护者Myron Marston、...

    Rails项目源代码

    Rails鼓励TDD(测试驱动开发),包括单元测试、集成测试和功能测试。RSpec、Capybara等库可以帮助编写和运行这些测试,确保代码质量。 这个Rails项目提供了学习和研究Web开发的机会,特别是对于Ruby on Rails新手...

    Rails 101 入门电子书

    - 测试安装: 创建一个简单的Rails应用来验证是否成功安装。 #### 五、练习作业0-Hello World - **目标**: - 学习如何创建第一个Rails应用程序。 - **过程**: - 创建新项目。 - 设置数据库配置。 - 创建控制器...

    Ruby on Rails安装指南(Ruby 1.8.6+Rails 2.0.2)

    最后,创建测试的 Rails 应用程序,并启动 Mongrel 服务器。 知识点1:Ruby 安装 * 下载 Ruby One-Click Installer 版本 * 安装 Ruby * 检查 Ruby 版本 知识点2:Rails 安装 * 下载 Rails 2.0.2 版本 * 安装 ...

Global site tag (gtag.js) - Google Analytics