Sunday, August 26, 2007

Cache Test Dummy

I use page caching in a lot of my projects, but could never figure out how to test them properly. There's a pretty good plugin that does this but I could never get it to work right. Until today, when I noticed that caching is turned off in testing mode! No wonder I couldn't test it!

So, it seems obvious now, but it never occurred to me to change this line in my test.rb file:

config.action_controller.perform_caching = true


Note that you will have to make sure your pages get swept properly after running your tests. I have a rake task that deletes all of the files, I think I got it from the Peepcode caching episode:


desc "Delete all cached files"
task :sweep_cache => "tmp:cache:clear" do

%w(index.html shows* about.html audio.html contact.html photos.html photos/*.html).each do |pattern|

rm_rf(Dir[File.join(RAILS_ROOT, "public", pattern)])

end

end



A little clunky, but it works. I might someday come up with a way to invoke all of my sweepers instead so I don't have to manually add all of those filenames. I think call this task from an autotest hook:




[:red, :green].each do |hook|
Autotest.add_hook hook do |at|
`rake sweep_cache` if File.exist?("#{FileUtils.pwd}/lib/tasks/cache.rake")
end
end



Because the plugin doesn't have many examples, here's a couple of my tests:
caching_story_test.rb



class CachingStoryTest < ActionController::IntegrationTest
fixtures :all

def test_page_caching
assert_cache_pages(about_path, contact_path)
end

def test_storyteller_caching
storyteller = storytellers(:storyteller_show_1_id_1)
assert_cache_pages(show_storyteller_path(:id => storyteller.id, :show_id => storyteller.show.id))
end

end



sweeping_story_test.rb


class SweepingStoryTest < ActionController::IntegrationTest

fixtures :all
include LoginLogoutDSL
include StoopDefaults

def test_should_sweep_news_items

logs_in
news_item = news_items(:double_whammy)

assert_expire_pages(news_items_path, news_item_path(news_item), index_path) do |*urls|
put news_item_path(:id => news_item.id), :news_item => @@news_item_default_values
end

assert_expire_pages(news_items_path, index_path) do |*urls|
post news_items_path, :news_item => @@news_item_default_values
end

assert_expire_pages(news_items_path, news_item_path(news_item), index_path) do |*urls|
delete news_item_path(:id => news_item.id)
end

end
end


(I'm sure there's a way to DRY up that last test, but I found it much harder to figure out which test was failing when I did that.

Last note: the expiration test only work with path routes, not url routes. So you call "delete news_item_path(...)" vs "delete news_item_url(...)".

No comments: