Reputation: 1
I've got a Rails 3.2.21 app on Ruby 2.1.5 that uses Postgres, Redis as the cache store (config.cache_store = :redis_store
), background workers (mostly for view cache warming) with sidekiq. Russian doll caching used with the cache_digests gem so you end up with cache keys like views/my_lovely_partial/5506949e3754753ad58190924d5b029f
. Running tests with RSpec, Factory Girl and Capybara.
For the test environment I have set up a parallel Redis server, different port to production and dev, and have "config.action_controller.perform_caching = true" in test rb. It's the same redis setup in dev and test apart from the port being different. Testing through either controller spec or feature spec I see the presence of objects cached in Redis, either through the tests themselves or directly viewing the keys in redis-cli.
When I try to test for view partials in Redis I find they are not being cached e.g. In dev environment on the same machine the view partials appear in the redis cache whereas in test they don't - only cached objects appear; this is confirmed by viewing through the redis-cli for both dev and test redis instances. 'render_template' and 'have_content' together with viewing the tested page (Using the 'capybara-screenshot' gem) confirm the content is being served successfully but the partials are not being cached in test.
Gems used specifically in test : rspec-rails, factory_girl_rails, faker, capybara, capybara-screenshot, capybara-user_agent, pry, guard-rspec, launchy, database_cleaner, shoulda-matchers, redis, turn.
I've checked in the spec.rb's that perform_caching is still true; tried temporarily removing pry, guard-rspec, launchy, shoulda-matchers gems but no difference. Tried removing database_cleaner gem, disabling all test cache clearing and ran tests again to find only object caching present in redis, no partials.
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
Feature specs use 'visit' and controller specs use 'get' to the correct URL's and render the correct content.
Any pointers as to why partials wouldn't be being cached in this situation very much appreciated. Thanks in advance.
Upvotes: 0
Views: 1945
Reputation: 1
Thought I'd try adding the 'selenium-webdriver' gem and after lots of irony debugging/trial/error in the test environment I then found cached partials were appearing in Redis. In case it helps others as I found a information a bit patchy;
Further added
gem 'selenium-webdriver'
into test group of Gem file.
Modified /spec/rails_helper.rb below. Note particularly Capybara.server_port = 10000, Capybara.always_include_port = true, Capybara.javascript_driver = :selenium - default port was not being picked up in js marked tests so had to lock it down there.
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
The "require 'support/wait_for_ajax'" in the above, described here, is something I came across whilst trying to get selenium up and running that looks handy for ajax testing. Although ajax was not playing a role in the cached partials I was testing for this, there are others with ajax calls where this would be handy.
For the feature tests using selenium, have those tests in their own describe block e.g.
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)
...
And then any following tests that use rack_test (default no full browser and no js tests) put them in a separate describe block but without 'js: true' and those before and after blocks. Initially I thought I would only need to mark selenium driven test blocks with "js: true" but found issues then with the basic rack_test based blocks until I took the above describe block approach.
Upvotes: 0