Created
September 7, 2012 01:56
-
-
Save ssimeonov/3662530 to your computer and use it in GitHub Desktop.
RSpec hierarchical data structure evolution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=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