Skip to content

Instantly share code, notes, and snippets.

@ssimeonov
Created September 7, 2012 01:56
Show Gist options
  • Save ssimeonov/3662530 to your computer and use it in GitHub Desktop.
Save ssimeonov/3662530 to your computer and use it in GitHub Desktop.
RSpec hierarchical data structure evolution
=begin
Allows for a data structure to be safely evolved hierarchically during testing
Example:
context "with one try" do
with_data tries: 1
describe "with suppressed exceptions" do
with_data raise_on_fail: false
specify { retry_raise_hell(1, my_data).should be_nil }
specify { retry_raise_hell(1, my_data.merge(return_on_fail: "failure")).should == "failure" }
end
end
Data structures are maintained on a stack in thread-local storage for maximum safety.
Multiple data structures can be maintained in parallel by passing a name argument.
Hashes are automatically merged.
=end
module MyData
module Helper
KEY = :spx_rspec_my_data
# Retrieves the stack for a data structure from thread-local storage
def get_my_data_stack(name)
Thread::current[KEY] ||= {}
Thread::current[KEY][name] ||= []
Thread::current[KEY][name]
end
end
module ExampleGroupMethods
include Helper
# Use with_data to modify the data structure in example groups
def with_data(data = {}, name = :my_rspec_data)
my_data = get_my_data_stack(name)
around do |example|
begin
if my_data.empty?
new_top = data
else
top = my_data.last
new_top = (top.instance_of?(Hash) && data.instance_of?(Hash)) ? top.merge(data) : data
end
#puts "\n#{my_data.length}: pushing #{new_top.inspect}"
my_data << new_top
example.run
ensure
#puts "\n#{my_data.length}: top is #{my_data.last}; popping"
my_data.pop
end
end
end
end
module ExampleMethods
include Helper
# Use my_data to refer to the current (top of the stack) data structure in examples
def my_data(name = :my_rspec_data)
get_my_data_stack(name).last
end
end
def self.included(receiver)
receiver.extend ExampleGroupMethods
receiver.send :include, ExampleMethods
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment