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