Sometimes a problem has to kick you upside the head so you can learn an important lesson. Tonight’s head slapper was an interaction between Cucumber and MemCacheD.
If you are using CUCUMBER AND MEMCACHE read this post carefully so you don’t get burned. If you’re using MemCache and not writing tests then return to Jail, do not collect $200.
It’s important to note that Cucumber has the handy side effect of running each scenario in a transaction. The impact is that the data from each scenario does not impact the next scenario. (note: you can pre-load data into cucumber using fixtures).
However, Cucumber does not do any rollback for Cache keys added into MemCache. In fact, your MemCache entries will happily persist between your development and test systems.
WhatTheBus has a simple check to reduce database writes – it only writes to the database if there is no cache hit for the bus. My thinking is that we only need to add a new bus if there is no key as shown in this partial snippet:
cache = Rails.cache.read params[:id] if cache.nil? bus = Bus.find_or_create_by_xref :name => params[:name], :xref => params[:id] end
This works great for live testing, but fails in technicolor for Cucumber because tests with the same ID will not make it to the find_or_create.
To solve the problem, I had to add a pre-condition (‘given’ in Cucumber speak) to each scenario to make sure the cache was cleared. It looks like this in the scenario feature:
Given no cache for "1234"
And that’s translated as code in the steps like so:
Given /^no cache for "([^\"]*)"$/ do |id| Rails.cache.delete id end