【问题标题】:SimpleCov reports not generating in Rails 3 app after running RSpec tests with Spork使用 Spork 运行 RSpec 测试后,SimpleCov 报告未在 Rails 3 应用程序中生成
【发布时间】:2012-07-07 19:30:54
【问题描述】:

我刚刚安装了 SimpleCov gem 以在我的 Rails 3.2.6 应用程序上生成代码覆盖率报告,它与 RSpec 配合得很好,但与 Spork 配合得很好。我可以通过运行 rspec --no-drb spec/ 来获得所需的正确报告,但我还想通过使用 rspec spec/ 运行 Spork 来获得它们。

鉴于有人在这方面取得了成功,看来我的设置可能有错误。我有read through the setup instructionsGitHub issue,它们声称为Spork 用户提供了修复,但仍然没有运气。我想知道是否有人可以提供他们工作 spec/spec_helper.rb 文件的完整示例,我可以用作参考,因为广泛的谷歌搜索只出现了 sn-ps。根据其他网站的建议,我尝试将 config/environments/test.rb 中的config.cache_classes 从默认的true 更改为false!(ENV['DRB'] == 'true'),但没有成功.

作为参考,我是这样设置的:

宝石文件

group :development, :test do
  # ...
  gem 'rspec-rails', '2.10.1'
end

group :test do
  # ...
  gem 'spork', '0.9.0'
  gem 'simplecov', '0.6.4', require: false
end

.spec

--colour
--drb

spec/spec_helper.rb(根据GitHub issue更改)

require 'simplecov'
SimpleCov.start 'rails'

require 'rubygems'
require 'spork'

Spork.prefork do
  unless ENV['DRB']
    require 'simplecov'
    SimpleCov.start 'rails'
  end

  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'

  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    config.mock_with :rspec
    config.fixture_path = "#{::Rails.root}/spec/fixtures"
    config.use_transactional_fixtures = true
    config.infer_base_class_for_anonymous_controllers = false
  end
end

Spork.each_run do
  if ENV['DRB']
    require 'simplecov'
    SimpleCov.start 'rails'
  end
end

我已尝试注释掉/更改此文件的前两个 SimpleCov 语句和 Spork 块内的 Simplecov 语句,但似乎找不到有效的组合。

我错过了什么?还有其他需要更改的文件吗?

【问题讨论】:

    标签: ruby-on-rails-3 rspec code-coverage ruby-on-rails-3.2 spork


    【解决方案1】:

    感谢a comment on the Github issue 将我发送到this blog entryits example spec/spec_helper.rb . 为什么这个工作的所有原因都包含在(非常详细!)博客条目中。将 SampleApp 替换为您的应用程序名称。

    spec/spec_helper.rb

    require 'rubygems'
    require 'spork'
    
    Spork.prefork do
      unless ENV['DRB']
        require 'simplecov'
        SimpleCov.start 'rails'
      end
    
      require 'rails/application'
      require Rails.root.join("config/application")
    
      ENV["RAILS_ENV"] ||= 'test'
      require 'rspec/rails'
      require 'rspec/autorun'
    
      RSpec.configure do |config|
        config.mock_with :rspec
        config.fixture_path = "#{::Rails.root}/spec/fixtures"
        config.use_transactional_fixtures = false
    
        config.before :each do
          if Capybara.current_driver == :rack_test
            DatabaseCleaner.strategy = :transaction
          else
            DatabaseCleaner.strategy = :truncation
          end
          DatabaseCleaner.start
        end
    
        config.after do
          DatabaseCleaner.clean
        end
    
        config.infer_base_class_for_anonymous_controllers = false
      end
    end
    
    Spork.each_run do
      if ENV['DRB']
        require 'simplecov'
        SimpleCov.start 'rails'
        SampleApp::Application.initialize!
        class SampleApp::Application
          def initialize!; end
        end
      end
    
      Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
    end
    

    编辑

    如果您使用Travis-CI,请不要按原样使用此代码,因为您可能会收到undefined method 'root' for Rails:Module (NoMethodError) 错误。如果您知道如何解决此问题,请分享。

    编辑 2

    我让 Travis CI 工作,基本上将所有内容都放在 Spork.each_run 块中,这似乎显着减慢了测试速度。必须有更好的方法来做到这一点,或者因为不必运行$ rspec --no-drb spec/ 一次来获取 SimpleCov 报告,这似乎不值得......

    spec/spec_helper.rb

    require 'rubygems'
    require 'spork'
    
    Spork.prefork do
      unless ENV['DRB']
        require 'simplecov'
        SimpleCov.start 'rails'
      end
    
      require 'rails/application'
      ENV["RAILS_ENV"] ||= 'test'
    end
    
    Spork.each_run do
      if ENV['DRB']
        require 'simplecov'
        SimpleCov.start 'rails'
        require Rails.root.join("config/application")
        SampleApp::Application.initialize!
        class SampleApp::Application
          def initialize!; end
        end
      end
    
      unless ENV['DRB']
        require File.expand_path("../../config/environment", __FILE__)
      end
    
      require 'rspec/rails'
      require 'rspec/autorun'
    
      Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
    
      RSpec.configure do |config|
        config.mock_with :rspec
    
        config.fixture_path = "#{::Rails.root}/spec/fixtures"
        config.use_transactional_fixtures = false
        config.before :each do
          if Capybara.current_driver == :rack_test
            DatabaseCleaner.strategy = :transaction
          else
            DatabaseCleaner.strategy = :truncation
          end
          DatabaseCleaner.start
        end
    
        config.after do
          DatabaseCleaner.clean
        end
        config.infer_base_class_for_anonymous_controllers = false
      end
    end
    

    编辑 3

    使用此配置几天后,它似乎并没有像我之前想象的那样减慢速度,所以除非发布更优雅的答案,否则我会认为这是公认的答案。

    编辑 4

    使用这个配置几个月后,我开始意识到它比我想象的要慢。部分原因是意识到 Spork 似乎可以减慢测试套件的速度,并且最适合快速迭代集中测试,而不是始终使用它运行整个测试套件。以下 SO 问题和博客文章将我带到了下面的 spec_helper.rb 文件,它可以在有或没有 Spork 的情况下运行 SimpleCov,运行速度比以前更快,并且可以与 Capybara 2.0 一起使用。

    spec/spec_helper.rb

    require 'rubygems'
    require 'spork'
    require 'simplecov'
    #uncomment the following line to use spork with the debugger
    #require 'spork/ext/ruby-debug'
    
    Spork.prefork do
      ENV["RAILS_ENV"] ||= 'test'
      unless ENV['DRB']
        SimpleCov.start 'rails'
        require File.expand_path("../../config/environment", __FILE__)
      end
    
      require 'rspec/rails'
      require 'rspec/autorun'
      require 'capybara/rails'
      require 'capybara/rspec'
    
      # files to preload based on results of Kernel override code below
      # ie they took more than 100 ms to load
      require "sprockets"
      require "sprockets/eco_template"
      require "sprockets/base"
      require "active_record/connection_adapters/postgresql_adapter"
      require "tzinfo"
      require "tilt"
      require "journey"
      require "journey/router"
      require "haml/template"
    
      RSpec.configure do |config|
        config.mock_with :rspec
    
        # If you're not using ActiveRecord, or you'd prefer not to run each of your
        # examples within a transaction, remove the following line or assign false
        # instead of true.
        config.use_transactional_fixtures = false
    
        # If true, the base class of anonymous controllers will be inferred
        # automatically. This will be the default behavior in future versions of
        # rspec-rails.
        config.infer_base_class_for_anonymous_controllers = false
    
        config.include FactoryGirl::Syntax::Methods
    
        config.before :suite do
          # PerfTools::CpuProfiler.start("/tmp/rspec_profile")
          DatabaseCleaner.strategy = :transaction
          DatabaseCleaner.clean_with(:truncation)
        end
    
        # Request specs cannot use a transaction because Capybara runs in a
        # separate thread with a different database connection.
        config.before type: :request do
          DatabaseCleaner.strategy = :truncation
        end
    
        # Reset so other non-request specs don't have to deal with slow truncation.
        config.after type: :request  do
          DatabaseCleaner.strategy = :transaction
        end
    
        RESERVED_IVARS = %w(@loaded_fixtures)
        last_gc_run = Time.now
    
        config.before(:each) do
          GC.disable
        end
    
        config.before do
          DatabaseCleaner.start
        end
    
        config.after do
          DatabaseCleaner.clean
        end
    
        # Release instance variables and trigger garbage collection
        # manually every second to make tests faster
        # http://blog.carbonfive.com/2011/02/02/crank-your-specs/
        config.after(:each) do
          (instance_variables - RESERVED_IVARS).each do |ivar|
            instance_variable_set(ivar, nil)
          end
          if Time.now - last_gc_run > 1.0
            GC.enable
            GC.start
            last_gc_run = Time.now
          end
        end
    
        config.after :suite do
          # PerfTools::CpuProfiler.stop
    
          # REPL to query ObjectSpace
          # http://blog.carbonfive.com/2011/02/02/crank-your-specs/
          # while true
          #   '> '.display
          #   begin
          #     puts eval($stdin.gets)
          #   rescue Exception => e
          #     puts e.message
          #   end
          # end
        end
      end
    
      # Find files to put into preload
      # http://www.opinionatedprogrammer.com/2011/02/profiling-spork-for-faster-start-up-time/
      # module Kernel
      #   def require_with_trace(*args)
      #     start = Time.now.to_f
      #     @indent ||= 0
      #     @indent += 2
      #     require_without_trace(*args)
      #     @indent -= 2
      #     Kernel::puts "#{' '*@indent}#{((Time.now.to_f - start)*1000).to_i} #{args[0]}"
      #   end
      #   alias_method_chain :require, :trace
      # end
    end
    
    Spork.each_run do
      # This code will be run each time you run your specs.
      if ENV['DRB']
        SimpleCov.start 'rails'
        SampleApp::Application.initialize!
        class SampleApp::Application
          def initialize!; end
        end
      end
    
      # Requires supporting ruby files with custom matchers and macros, etc,
      # in spec/support/ and its subdirectories.
      Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
      FactoryGirl.reload
      I18n.backend.reload!
    end
    

    【讨论】:

      【解决方案2】:

      我在具有这些特定版本的 Rails 应用程序中工作:

      • rails (3.2.8)
      • guard (1.3.2)
      • guard-spork (1.1.0)
      • spork (0.9.2)
      • simplecov (0.6.4)
      • rspec-rails (2.11.0)

      spec/spec_helper.rb 看起来像这样:

      require "spork"
      
      Spork.prefork do
      
      end
      
      Spork.each_run do
        require "simplecov"
        SimpleCov.start "rails"
      
        ENV["RAILS_ENV"] ||= "test"
        require File.expand_path("../../config/environment", __FILE__)
        require "rspec/rails"
        require "capybara/rspec"
      
        Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
      
        FactoryGirl.reload
      end
      

      虽然从性能的角度来看,要求 Spork.each_run 块中的所有内容可能不太理想,但这会在每次测试调用时正确运行 SimpleCov,并且开销似乎相对较低。

      我希望这会有所帮助。祝你好运!

      【讨论】:

      • 非常感谢您的回答。我升级了我的红宝石宝石以匹配你的宝石,我给你的spec_helper.rb 进行了试运行,但不幸的是它对我不起作用;它实际上最终使我的一些测试失败了。我的spec_helper.rb 是否可以在您的应用中使用?
      • 感谢您提示我再次查看此内容。我设法使用答案中的代码解决了我的问题。希望它也适用于您,或者至少提供某种参考。
      • 嗨,Paul,spec_helper.rb 是从一个工作应用程序中提取的,尽管目前还没有使用 Travis。我很高兴你让它工作了!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-19
      • 2012-08-27
      相关资源
      最近更新 更多