可选地在Rails 3功能测试中测试缓存

时间:2021-10-09 05:54:50

Generally, I want my functional tests to not perform action caching. Rails seems to be on my side, defaulting to config.action_controller.perform_caching = false in environment/test.rb. This leads to normal functional tests not testing the caching.

通常,我希望我的功能测试不执行动作缓存。 Rails似乎在我身边,在environment / test.rb中默认为config.action_controller.perform_caching = false。这导致正常的功能测试没有测试缓存。

So how do I test caching in Rails 3.

那么我如何在Rails 3中测试缓存。

The solutions proposed in this thread seem rather hacky or taylored towards Rails 2: How to enable page caching in a functional test in rails?

这个线程中提出的解决方案似乎相当hacky或者对Rails 2:如何在rails中的功能测试中启用页面缓存?

I want to do something like:

我想做的事情如下:

test "caching of index method" do
  with_caching do
    get :index
    assert_template 'index'
    get :index
    assert_template ''
  end
end

Maybe there is also a better way of testing that the cache was hit?

也许还有更好的方法来测试缓存是否被击中?

5 个解决方案

#1


27  

You're liable to end up with tests stomping on each other. You should wrap this up with ensure and reset it to old values appropriately. An example:

你最终可能会互相踩踏测试。您应该将其包装起来并确保将其重置为旧值。一个例子:

module ActionController::Testing::Caching
  def with_caching(on = true)
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = on
    yield
  ensure
    ActionController::Base.perform_caching = caching
  end

  def without_caching(&block)
    with_caching(false, &block)
  end
end

I've also put this into a module so you can just include this in your test class or parent class.

我还把它放到一个模块中,这样你就可以把它包含在你的测试类或父类中。

#2


30  

A solution for rspec:

rspec的解决方案:

Add an around block with a custom metadata key to your configuration.

在配置中添加带有自定义元数据键的around块。

RSpec.configure do |config|
  config.around(:each, :caching) do |example|
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = example.metadata[:caching]
    example.run
    Rails.cache.clear
    ActionController::Base.perform_caching = caching
  end
end

Add the metadata key when caching is needed.

需要缓存时添加元数据键。

describe "visit the homepage", :caching => true do
  # test cached stuff
end

#3


5  

My version that works:

我的版本有效:

RSpec.configure do |config|
  config.around(:each) do |example|
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = example.metadata[:caching]
    example.run
    Rails.cache.clear
    ActionController::Base.perform_caching = caching
  end
end

Credit to Rossti, but

感谢罗斯蒂,但是

  1. Cache needs to be cleared between examples
  2. 需要在示例之间清除缓存
  3. Cache store can not be set differently on examples, only at init in case anyone wondered
  4. 缓存存储不能在示例上设置不同,只有在init时才会有人想知道

#4


2  

Here is my current solution to the problem: In environment/test.rb I set

这是我目前解决问题的方法:在环境/ test.rb中设置

config.action_controller.perform_caching = true

Also, I am monkey patching Test::Unit::TestCase as follows:

另外,我是猴子修补Test :: Unit :: TestCase如下:

class Test::Unit::TestCase
  def setup_with_disable_caching
    setup_without_disable_caching
    disable_caching
  end
  alias_method_chain :setup, :disable_caching

  def disable_caching
    ActionController::Base.perform_caching = false
  end

  def enable_caching(&blk)
    ActionController::Base.perform_caching = true
    if blk
      yield
      disable_caching
    end
  end
end

This allows me to write the following tests:

这允许我编写以下测试:

test "info about caching (with caching)" do
  enable_caching do
    get :about, :locale => :en
    assert_template 'about'
    get :about, :locale => :en
    assert_template nil
  end
end

test "info about caching (without caching)" do
  get :about, :locale => :en
  assert_template 'about'
  get :about, :locale => :en
  assert_template 'about'
end

It's not perfect, but works for now. I am still interested in better ideas!!

它并不完美,但现在可以使用。我仍然对更好的想法感兴趣!!

#5


2  

This is not an answer, rather a few limitations to be aware of which don't fit in a comment.

这不是一个答案,而是要注意哪些不适合评论的一些限制。

  • All the (amazing) answers relying on ActionController::Base.perform_caching will not work for low-level caching (cf this answer). The only option you have is the module independent config.cache_store setting that you set to :null_store.

    依赖于ActionController :: Base.perform_caching的所有(惊人)答案都不适用于低级缓存(参见此答案)。您拥有的唯一选项是您设置为的模块独立config.cache_store设置:null_store。

  • As @viktor-trón said earlier setting the cache_store is not possible between tests, only at init.

    正如@ viktor-trón先前所说,在测试之间设置cache_store是不可能的,只能在init。

  • The cache is shared between environments for the default cache_store. As a result, (i) the cache should be cleared before testing if you fear stuff from your development session, (ii) running tests clears the cache of your other environments. However, your production environment should use something like the mem_cache_store or whatever else more suited for it, so it should be fine.

    缓存在默认cache_store的环境之间共享。因此,(i)如果您担心开发会话中的内容,应在测试之前清除缓存,(ii)运行测试会清除其他环境的缓存。但是,您的生产环境应该使用类似mem_cache_store或其他更适合它的东西,所以应该没问题。

From the two first points, it seems that testing for low-level caching is not possible as a per example basis.

从两个第一点来看,似乎不能以每个示例为基础测试低级缓存。

#1


27  

You're liable to end up with tests stomping on each other. You should wrap this up with ensure and reset it to old values appropriately. An example:

你最终可能会互相踩踏测试。您应该将其包装起来并确保将其重置为旧值。一个例子:

module ActionController::Testing::Caching
  def with_caching(on = true)
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = on
    yield
  ensure
    ActionController::Base.perform_caching = caching
  end

  def without_caching(&block)
    with_caching(false, &block)
  end
end

I've also put this into a module so you can just include this in your test class or parent class.

我还把它放到一个模块中,这样你就可以把它包含在你的测试类或父类中。

#2


30  

A solution for rspec:

rspec的解决方案:

Add an around block with a custom metadata key to your configuration.

在配置中添加带有自定义元数据键的around块。

RSpec.configure do |config|
  config.around(:each, :caching) do |example|
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = example.metadata[:caching]
    example.run
    Rails.cache.clear
    ActionController::Base.perform_caching = caching
  end
end

Add the metadata key when caching is needed.

需要缓存时添加元数据键。

describe "visit the homepage", :caching => true do
  # test cached stuff
end

#3


5  

My version that works:

我的版本有效:

RSpec.configure do |config|
  config.around(:each) do |example|
    caching = ActionController::Base.perform_caching
    ActionController::Base.perform_caching = example.metadata[:caching]
    example.run
    Rails.cache.clear
    ActionController::Base.perform_caching = caching
  end
end

Credit to Rossti, but

感谢罗斯蒂,但是

  1. Cache needs to be cleared between examples
  2. 需要在示例之间清除缓存
  3. Cache store can not be set differently on examples, only at init in case anyone wondered
  4. 缓存存储不能在示例上设置不同,只有在init时才会有人想知道

#4


2  

Here is my current solution to the problem: In environment/test.rb I set

这是我目前解决问题的方法:在环境/ test.rb中设置

config.action_controller.perform_caching = true

Also, I am monkey patching Test::Unit::TestCase as follows:

另外,我是猴子修补Test :: Unit :: TestCase如下:

class Test::Unit::TestCase
  def setup_with_disable_caching
    setup_without_disable_caching
    disable_caching
  end
  alias_method_chain :setup, :disable_caching

  def disable_caching
    ActionController::Base.perform_caching = false
  end

  def enable_caching(&blk)
    ActionController::Base.perform_caching = true
    if blk
      yield
      disable_caching
    end
  end
end

This allows me to write the following tests:

这允许我编写以下测试:

test "info about caching (with caching)" do
  enable_caching do
    get :about, :locale => :en
    assert_template 'about'
    get :about, :locale => :en
    assert_template nil
  end
end

test "info about caching (without caching)" do
  get :about, :locale => :en
  assert_template 'about'
  get :about, :locale => :en
  assert_template 'about'
end

It's not perfect, but works for now. I am still interested in better ideas!!

它并不完美,但现在可以使用。我仍然对更好的想法感兴趣!!

#5


2  

This is not an answer, rather a few limitations to be aware of which don't fit in a comment.

这不是一个答案,而是要注意哪些不适合评论的一些限制。

  • All the (amazing) answers relying on ActionController::Base.perform_caching will not work for low-level caching (cf this answer). The only option you have is the module independent config.cache_store setting that you set to :null_store.

    依赖于ActionController :: Base.perform_caching的所有(惊人)答案都不适用于低级缓存(参见此答案)。您拥有的唯一选项是您设置为的模块独立config.cache_store设置:null_store。

  • As @viktor-trón said earlier setting the cache_store is not possible between tests, only at init.

    正如@ viktor-trón先前所说,在测试之间设置cache_store是不可能的,只能在init。

  • The cache is shared between environments for the default cache_store. As a result, (i) the cache should be cleared before testing if you fear stuff from your development session, (ii) running tests clears the cache of your other environments. However, your production environment should use something like the mem_cache_store or whatever else more suited for it, so it should be fine.

    缓存在默认cache_store的环境之间共享。因此,(i)如果您担心开发会话中的内容,应在测试之前清除缓存,(ii)运行测试会清除其他环境的缓存。但是,您的生产环境应该使用类似mem_cache_store或其他更适合它的东西,所以应该没问题。

From the two first points, it seems that testing for low-level caching is not possible as a per example basis.

从两个第一点来看,似乎不能以每个示例为基础测试低级缓存。