【问题标题】:Rails test environment partials not appearing in Redis cacheRails 测试环境部分未出现在 Redis 缓存中
【发布时间】:2015-11-10 06:47:33
【问题描述】:

我在 Ruby 2.1.5 上有一个 Rails 3.2.21 应用程序,它使用 Postgres、Redis 作为缓存存储 (config.cache_store = :redis_store)、后台工作人员(主要用于视图缓存预热)和 sidekiq。俄罗斯娃娃缓存与 cache_digests gem 一起使用,所以你最终会得到像views/my_lovely_partial/5506949e3754753ad58190924d5b029f 这样的缓存键。使用 RSpec、Factory Girl 和 Capybara 运行测试。

对于测试环境,我设置了一个并行 Redis 服务器,与生产和开发不同的端口,并在测试 rb 中有“config.action_controller.perform_caching = true”。除了端口不同之外,开发和测试中的 redis 设置相同。 通过控制器规范或功能规范进行测试,我看到缓存在 Redis 中的对象的存在,无论是通过测试本身还是直接查看 redis-cli 中的键。

当我尝试在 Redis 中测试视图部分时,我发现它们没有被缓存,例如在同一台机器上的开发环境中,视图部分出现在 redis 缓存中,而在测试中它们不会出现 - 只出现缓存的对象;通过查看开发和测试 redis 实例的 redis-cli 可以确认这一点。 'render_template' 和 'have_content' 以及查看测试页面(使用 'capybara-screenshot' gem)确认内容已成功提供,但部分内容未在测试中缓存。

专门用于测试的宝石:rspec-rails、factory_girl_rails、faker、capybara、capybara-screenshot、capybara-user_agent、pry、guard-rspec、launchy、database_cleaner、shouda-matchers、redis、turn。

我在 spec.rb 中检查了 perform_caching 仍然是正确的;尝试暂时删除 pry、guard-rspec、launchy、should-matchers 宝石,但没有区别。尝试删除 database_cleaner gem,禁用所有测试缓存清除并再次运行测试以发现 redis 中仅存在对象缓存,没有部分。

test.rb

SmashingSuperApp::Application.configure do

  config.cache_classes = true

  config.whiny_nils = true

  config.consider_all_requests_local       = false

  config.action_dispatch.show_exceptions = true

  config.action_controller.allow_forgery_protection    = false

  config.action_mailer.delivery_method = :test

  config.active_support.deprecation = :stderr

  config.action_controller.perform_caching = true 

  config.cache_store = :redis_store, "redis://localhost:6378/0/cache", { expires_in: 1176.hours }

  ENV["REDIS_URL"] ||= "redis://localhost:6378/0"

  config.action_mailer.raise_delivery_errors = false

  config.active_support.deprecation = :log

  config.action_dispatch.best_standards_support = :builtin

  config.active_record.mass_assignment_sanitizer = :strict

  config.active_record.auto_explain_threshold_in_seconds = 0.5

  config.log_tags = [:uuid, :remote_ip]

  config.before_initialize do |app|
    app.config.paths.add 'app/models', :eager_load => true
  end

  config.to_prepare do
    Dir["#{Rails.root}/app/models/*"].each do |model_name|
      require_dependency model_name unless model_name == "." || model_name == ".."
    end
  end

  Rails.application.routes.default_url_options[:host]= 'smashingsuperapp.co.uk:3000'

end

rails_helper.rb

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

require 'capybara/rails'
require 'capybara-screenshot/rspec'
require 'shoulda/matchers'
require 'faker'
require 'redis'

RSpec.configure do |config|

  config.include Rails.application.routes.url_helpers

  config.infer_spec_type_from_file_location!

  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    Rails.cache.clear # Clear redis cache
  end

  config.before(:each) do |example|
    DatabaseCleaner.strategy= example.metadata[:js] ? :truncation : :transaction
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
    Rails.cache.clear # Clear redis cache
  end

  config.include FactoryGirl::Syntax::Methods

  config.after do |example|
    if example.metadata[:type] == :feature and example.exception.present?
      save_and_open_page
    end
  end

end

def set_host (host)
  default_url_options[:host] = host
  Capybara.app_host = "http://" + host
end 

spec_helper.rb

require 'capybara/user_agent'

Capybara::UserAgent.add_user_agents(mechanize: 'Mechanize')

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end

  config.include Capybara::UserAgent::DSL

  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end

=begin
  config.filter_run :focus
  config.run_all_when_everything_filtered = true

  config.disable_monkey_patching!

  if config.files_to_run.one?
    config.default_formatter = 'doc'
  end

  config.profile_examples = 10

  config.order = :random

  Kernel.srand config.seed
=end
end

def get_path(path)
  parsed_params = Rails.application.routes.recognize_path path
  controller = parsed_params.delete(:controller)
  action = parsed_params.delete(:action)
  get(action, parsed_params)
end

功能规范使用“访问”,控制器规范使用“获取”到正确的 URL 并呈现正确的内容。

非常感谢任何关于为什么在这种情况下不会缓存部分内容的指针。提前致谢。

【问题讨论】:

    标签: ruby-on-rails caching rspec capybara factory-bot


    【解决方案1】:

    我想尝试添加“selenium-webdriver”gem,在测试环境中进行了大量具有讽刺意味的调试/试验/错误之后,我发现缓存的部分出现在 Redis 中。 以防它帮助别人,因为我发现信息有点不完整;

    进一步补充

    gem 'selenium-webdriver'
    

    进入 Gem 文件的测试组。

    修改了下面的 /spec/rails_helper.rb。特别注意 Capybara.server_port = 10000, Capybara.always_include_port = true, Capybara.javascript_driver = :selenium - 默认端口在 js 标记的测试中没有被拾取,因此必须将其锁定在那里。

    ENV['RAILS_ENV'] ||= 'test'
    require 'spec_helper'
    require File.expand_path('../../config/environment', __FILE__)
    require 'rspec/rails'
    
    require 'capybara/rails'
    require 'capybara-screenshot/rspec'
    require "rack_session_access/capybara"
    require 'shoulda/matchers'
    require 'faker'
    require 'redis'
    
    require 'support/wait_for_ajax'
    
    RSpec.configure do |config|
    
      config.include Rails.application.routes.url_helpers
    
      config.infer_spec_type_from_file_location!
    
      config.use_transactional_fixtures = false
    
      config.before(:suite) do
        DatabaseCleaner.clean_with(:truncation)
        Rails.cache.clear # Clear redis cache
    
        # To prevent FactoryGirl creating persons with an id that are reserved for 'special' persons
        ActiveRecord::Base.connection.execute("ALTER SEQUENCE persons_id_seq START with 4000 RESTART;")
      end
    
      config.before(:each) do |example|
        DatabaseCleaner.strategy= example.metadata[:js] ? :truncation : :transaction
        DatabaseCleaner.start
      end
    
      config.after(:each) do
        DatabaseCleaner.clean
        Rails.cache.clear # Clear redis cache
      end
    
      config.include FactoryGirl::Syntax::Methods
    
      config.after do |example|
        if example.metadata[:type] == :feature and example.exception.present?
          save_and_open_page
        end
      end
    
    end
    
    Capybara.server_port = 10000
    
    Capybara.always_include_port = true
    
    Capybara.javascript_driver = :selenium
    
    def set_host (host)
      # host! host
      default_url_options[:host] = host
      Capybara.app_host = "http://" + host
    end
    

    上面描述的here 中的“require 'support/wait_for_ajax'”是我在尝试启动和运行 selenium 时遇到的,这对于 ajax 测试来说看起来很方便。虽然 ajax 在我正在测试的缓存部分中没有发挥作用,但还有其他一些使用 ajax 调用的地方,这会很方便。

    对于使用 selenium 的功能测试,将这些测试放在自己的描述块中,例如

      describe "special person accesses event with JS tests" do
    
        before(:each) do
          Capybara.current_driver = :selenium
        end
    
        after(:all) do
          Capybara.use_default_driver
        end
    
        scenario 'can view persons partial with cache insertion', js: true do
    
          visit some_cached_page_path(id:some_page_id)
    
        ...
    

    然后任何使用 rack_test 的后续测试(默认没有完整的浏览器和没有 js 测试)将它们放在单独的描述块中,但没有 'js: true' 和之前和之后的块。最初我以为我只需要用“js:true”标记 selenium 驱动的测试块,但后来发现基于基本 rack_test 的块存在问题,直到我采用上述描述块方法。

    【讨论】:

      猜你喜欢
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-09
      • 1970-01-01
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多